/** * @brief Disables all the active endpoints. * @details This function disables all the active endpoints except the * endpoint zero. * @note This function must be invoked in response of a SET_CONFIGURATION * message with configuration number zero. * * @param[in] usbp pointer to the @p USBDriver object * * @iclass */ void usbDisableEndpointsI(USBDriver *usbp) { unsigned i; osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state"); usbp->transmitting &= 1U; usbp->receiving &= 1U; for (i = 1; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { #if USB_USE_WAIT == TRUE /* Signaling the event to threads waiting on endpoints.*/ if (usbp->epc[i] != NULL) { osalSysLockFromISR(); if (usbp->epc[i]->in_state != NULL) { osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); } if (usbp->epc[i]->out_state != NULL) { osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); } osalSysUnlockFromISR(); } #endif usbp->epc[i] = NULL; } /* Low level endpoints deactivation.*/ usb_lld_disable_endpoints(usbp); }
/** * @brief Resets an output queue. * @details All the data in the output queue is erased and lost, any waiting * thread is resumed with status @p Q_RESET. * @note A reset operation can be used by a low level driver in order to * obtain immediate attention from the high level layers. * * @param[in] oqp pointer to an @p output_queue_t structure * * @iclass */ void oqResetI(output_queue_t *oqp) { osalDbgCheckClassI(); oqp->q_rdptr = oqp->q_buffer; oqp->q_wrptr = oqp->q_buffer; oqp->q_counter = qSizeX(oqp); osalThreadDequeueAllI(&oqp->q_waiting, Q_RESET); }
/** * @brief Resets an input queue. * @details All the data in the input queue is erased and lost, any waiting * thread is resumed with status @p Q_RESET. * @note A reset operation can be used by a low level driver in order to * obtain immediate attention from the high level layers. * * @param[in] iqp pointer to an @p input_queue_t structure * * @iclass */ void iqResetI(input_queue_t *iqp) { osalDbgCheckClassI(); iqp->q_rdptr = iqp->q_buffer; iqp->q_wrptr = iqp->q_buffer; iqp->q_counter = 0; osalThreadDequeueAllI(&iqp->q_waiting, Q_RESET); }
/** * @brief Deasserts the slave select signal. * @details The previously selected peripheral is unselected. * @pre ILI9341 is active. * * @param[in] driverp pointer to the @p ILI9341Driver object * * @iclass */ void ili9341UnselectI(ILI9341Driver *driverp) { osalDbgCheckClassI(); osalDbgCheck(driverp != NULL); osalDbgAssert(driverp->state == ILI9341_ACTIVE, "invalid state"); spiUnselectI(driverp->config->spi); driverp->state = ILI9341_READY; }
/** * @brief Starts the timer in continuous mode. * * @param[in] gptp pointer to the @p GPTDriver object * @param[in] interval period in ticks * * @iclass */ void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval) { osalDbgCheckClassI(); osalDbgCheck(gptp != NULL); osalDbgAssert(gptp->state == GPT_READY, "invalid state"); gptp->state = GPT_CONTINUOUS; gpt_lld_start_timer(gptp, interval); }
/** * @brief Starts a transmission on the UART peripheral. * @note The buffers are organized as uint8_t arrays for data sizes below * or equal to 8 bits else it is organized as uint16_t arrays. * @note This function has to be invoked from a lock zone. * * @param[in] uartp pointer to the @p UARTDriver object * @param[in] n number of data frames to send * @param[in] txbuf the pointer to the transmit buffer * * @iclass */ void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) { osalDbgCheckClassI(); osalDbgCheck((uartp != NULL) && (n > 0U) && (txbuf != NULL)); osalDbgAssert(uartp->state == UART_READY, "is active"); osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); uart_lld_start_send(uartp, n, txbuf); uartp->txstate = UART_TX_ACTIVE; }
/** * @brief Starts the timer in one shot mode. * * @param[in] gptp pointer to the @p GPTDriver object * @param[in] interval time interval in ticks * * @api */ void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval) { osalDbgCheckClassI(); osalDbgCheck(gptp != NULL); osalDbgAssert(gptp->state == GPT_READY, "invalid state"); gptp->state = GPT_ONESHOT; gpt_lld_start_timer(gptp, interval); }
/** * @brief Handles incoming data. * @details This function must be called from the input interrupt service * routine in order to enqueue incoming data and generate the * related events. * @note The incoming data event is only generated when the input queue * becomes non-empty. * @note In order to gain some performance it is suggested to not use * this function directly but copy this code directly into the * interrupt service routine. * * @param[in] sdp pointer to a @p SerialDriver structure * @param[in] b the byte to be written in the driver's Input Queue * * @iclass */ void sdIncomingDataI(SerialDriver *sdp, uint8_t b) { osalDbgCheckClassI(); osalDbgCheck(sdp != NULL); if (iqIsEmptyI(&sdp->iqueue)) chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE); if (iqPutI(&sdp->iqueue, b) < MSG_OK) chnAddFlagsI(sdp, SD_QUEUE_FULL_ERROR); }
/** * @brief Starts a receive operation on the UART peripheral. * @note The buffers are organized as uint8_t arrays for data sizes below * or equal to 8 bits else it is organized as uint16_t arrays. * @note This function has to be invoked from a lock zone. * * @param[in] uartp pointer to the @p UARTDriver object * @param[in] n number of data frames to receive * @param[out] rxbuf the pointer to the receive buffer * * @iclass */ void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) { osalDbgCheckClassI(); osalDbgCheck((uartp != NULL) && (n > 0U) && (rxbuf != NULL)); osalDbgAssert(uartp->state == UART_READY, "is active"); osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); uart_lld_start_receive(uartp, n, rxbuf); uartp->rxstate = UART_RX_ACTIVE; }
/** * @brief Handles outgoing data. * @details Must be called from the output interrupt service routine in order * to get the next byte to be transmitted. * @note In order to gain some performance it is suggested to not use * this function directly but copy this code directly into the * interrupt service routine. * * @param[in] sdp pointer to a @p SerialDriver structure * @return The byte value read from the driver's output queue. * @retval MSG_TIMEOUT if the queue is empty (the lower driver usually * disables the interrupt source when this happens). * * @iclass */ msg_t sdRequestDataI(SerialDriver *sdp) { msg_t b; osalDbgCheckClassI(); osalDbgCheck(sdp != NULL); b = oqGetI(&sdp->oqueue); if (b < MSG_OK) chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); return b; }
/** * @brief Stops the timer. * * @param[in] gptp pointer to the @p GPTDriver object * * @api */ void gptStopTimerI(GPTDriver *gptp) { osalDbgCheckClassI(); osalDbgCheck(gptp != NULL); osalDbgAssert((gptp->state == GPT_READY) || (gptp->state == GPT_CONTINUOUS) || (gptp->state == GPT_ONESHOT), "invalid state"); gptp->state = GPT_READY; gpt_lld_stop_timer(gptp); }
/** * @brief Stalls an OUT endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval false Endpoint stalled. * @retval true Endpoint busy, not stalled. * * @iclass */ bool usbStallReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetReceiveStatusI(usbp, ep)) return true; usb_lld_stall_out(usbp, ep); return false; }
/** * @brief Stalls an IN endpoint. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval false Endpoint stalled. * @retval true Endpoint busy, not stalled. * * @iclass */ bool usbStallTransmitI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetTransmitStatusI(usbp, ep)) return true; usb_lld_stall_in(usbp, ep); return false; }
/** * @brief Starts a transmit transaction on an IN endpoint. * @post The endpoint callback is invoked when the transfer has been * completed. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval FALSE Operation started successfully. * @retval TRUE Endpoint busy, operation not started. * * @iclass */ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetTransmitStatusI(usbp, ep)) return TRUE; usbp->transmitting |= (1 << ep); usb_lld_start_in(usbp, ep); return FALSE; }
/** * @brief Starts a receive transaction on an OUT endpoint. * @post The endpoint callback is invoked when the transfer has been * completed. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval FALSE Operation started successfully. * @retval TRUE Endpoint busy, operation not started. * * @iclass */ bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetReceiveStatusI(usbp, ep)) return TRUE; usbp->receiving |= (1 << ep); usb_lld_start_out(usbp, ep); return FALSE; }
/** * @brief Stops any ongoing receive operation. * @note Stopping a receive operation also suppresses the receive callbacks. * @note This function has to be invoked from a lock zone. * * @param[in] uartp pointer to the @p UARTDriver object * * @return The number of data frames not received by the * stopped receive operation. * @retval 0 There was no receive operation in progress. * * @iclass */ size_t uartStopReceiveI(UARTDriver *uartp) { osalDbgCheckClassI(); osalDbgCheck(uartp != NULL); osalDbgAssert(uartp->state == UART_READY, "not active"); if (uartp->rxstate == UART_RX_ACTIVE) { size_t n = uart_lld_stop_receive(uartp); uartp->rxstate = UART_RX_IDLE; return n; } return 0; }
/** * @brief Starts a transmit transaction on an IN endpoint. * @post The endpoint callback is invoked when the transfer has been * completed. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval false Operation started successfully. * @retval true Endpoint busy, operation not started. * * @iclass */ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetTransmitStatusI(usbp, ep)) { return true; } usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); usb_lld_start_in(usbp, ep); return false; }
/** * @brief Starts a receive transaction on an OUT endpoint. * @post The endpoint callback is invoked when the transfer has been * completed. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * * @return The operation status. * @retval false Operation started successfully. * @retval true Endpoint busy, operation not started. * * @iclass */ bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); if (usbGetReceiveStatusI(usbp, ep)) { return true; } usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); usb_lld_start_out(usbp, ep); return false; }
/** * @brief Aborts the ongoing SPI operation. * * @param[in] spip pointer to the @p SPIDriver object * * @iclass */ void spiAbortI(SPIDriver *spip) { osalDbgCheckClassI(); osalDbgCheck(spip != NULL); osalDbgAssert((spip->state == SPI_ACTIVE) || (spip->state == SPI_COMPLETE), "invalid state"); spi_lld_abort(spip); spip->state = SPI_READY; #if SPI_USE_WAIT == TRUE osalThreadResumeI(&spip->thread, MSG_OK); #endif }
/** * @brief Disables all the active endpoints. * @details This function disables all the active endpoints except the * endpoint zero. * @note This function must be invoked in response of a SET_CONFIGURATION * message with configuration number zero. * * @param[in] usbp pointer to the @p USBDriver object * * @iclass */ void usbDisableEndpointsI(USBDriver *usbp) { unsigned i; osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); osalDbgAssert(usbp->state == USB_SELECTED, "invalid state"); usbp->transmitting &= ~1; usbp->receiving &= ~1; for (i = 1; i <= USB_MAX_ENDPOINTS; i++) usbp->epc[i] = NULL; /* Low level endpoints deactivation.*/ usb_lld_disable_endpoints(usbp); }
/** * @brief Stops an ongoing conversion. * @details This function stops the currently ongoing conversion and returns * the driver in the @p DAC_READY state. If there was no conversion * being processed then the function does nothing. * * @param[in] dacp pointer to the @p DACDriver object * * @iclass */ void dacStopConversionI(DACDriver *dacp) { osalDbgCheckClassI(); osalDbgCheck(dacp != NULL); osalDbgAssert((dacp->state == DAC_READY) || (dacp->state == DAC_ACTIVE) || (dacp->state == DAC_COMPLETE), "invalid state"); if (dacp->state != DAC_READY) { dac_lld_stop_conversion(dacp); dacp->grpp = NULL; dacp->state = DAC_READY; _dac_reset_i(dacp); } }
/** * @brief Stops an ongoing conversion. * @details This function stops the currently ongoing conversion and returns * the driver in the @p ADC_READY state. If there was no conversion * being processed then the function does nothing. * * @param[in] adcp pointer to the @p ADCDriver object * * @iclass */ void adcStopConversionI(ADCDriver *adcp) { osalDbgCheckClassI(); osalDbgCheck(adcp != NULL); osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE) || (adcp->state == ADC_COMPLETE), "invalid state"); if (adcp->state != ADC_READY) { adc_lld_stop_conversion(adcp); adcp->grpp = NULL; adcp->state = ADC_READY; _adc_reset_i(adcp); } }
/** * @brief Input queue write. * @details A byte value is written into the low end of an input queue. * * @param[in] iqp pointer to an @p input_queue_t structure * @param[in] b the byte value to be written in the queue * @return The operation status. * @retval Q_OK if the operation has been completed with success. * @retval Q_FULL if the queue is full and the operation cannot be * completed. * * @iclass */ msg_t iqPutI(input_queue_t *iqp, uint8_t b) { osalDbgCheckClassI(); if (iqIsFullI(iqp)) { return Q_FULL; } iqp->q_counter++; *iqp->q_wrptr++ = b; if (iqp->q_wrptr >= iqp->q_top) { iqp->q_wrptr = iqp->q_buffer; } osalThreadDequeueNextI(&iqp->q_waiting, Q_OK); return Q_OK; }
/** * @brief Starts an ADC conversion. * @details Starts an asynchronous conversion operation. * @post The callbacks associated to the conversion group will be invoked * on buffer fill and error events. * @note The buffer is organized as a matrix of M*N elements where M is the * channels number configured into the conversion group and N is the * buffer depth. The samples are sequentially written into the buffer * with no gaps. * * @param[in] adcp pointer to the @p ADCDriver object * @param[in] grpp pointer to a @p ADCConversionGroup object * @param[out] samples pointer to the samples buffer * @param[in] depth buffer depth (matrix rows number). The buffer depth * must be one or an even number. * * @iclass */ void adcStartConversionI(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth) { osalDbgCheckClassI(); osalDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && (depth > 0U) && ((depth == 1U) || ((depth & 1U) == 0U))); osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ERROR), "not ready"); adcp->samples = samples; adcp->depth = depth; adcp->grpp = grpp; adcp->state = ADC_ACTIVE; adc_lld_start_conversion(adcp); }
/** * @brief Starts a DAC conversion. * @details Starts an asynchronous conversion operation. * @post The callbacks associated to the conversion group will be invoked * on buffer fill and error events. * @note The buffer is organized as a matrix of M*N elements where M is the * channels number configured into the conversion group and N is the * buffer depth. The samples are sequentially written into the buffer * with no gaps. * * @param[in] dacp pointer to the @p DACDriver object * @param[in] grpp pointer to a @p DACConversionGroup object * @param[in] samples pointer to the samples buffer * @param[in] depth buffer depth (matrix rows number). The buffer depth * must be one or an even number. * * @iclass */ void dacStartConversionI(DACDriver *dacp, const DACConversionGroup *grpp, const dacsample_t *samples, size_t depth) { osalDbgCheckClassI(); osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) && ((depth == 1) || ((depth & 1) == 0))); osalDbgAssert((dacp->state == DAC_READY) || (dacp->state == DAC_COMPLETE) || (dacp->state == DAC_ERROR), "not ready"); dacp->samples = samples; dacp->depth = depth; dacp->grpp = grpp; dacp->state = DAC_ACTIVE; dac_lld_start_conversion(dacp); }
/** * @brief Output queue read. * @details A byte value is read from the low end of an output queue. * * @param[in] oqp pointer to an @p output_queue_t structure * @return The byte value from the queue. * @retval Q_EMPTY if the queue is empty. * * @iclass */ msg_t oqGetI(output_queue_t *oqp) { uint8_t b; osalDbgCheckClassI(); if (oqIsEmptyI(oqp)) { return Q_EMPTY; } oqp->q_counter++; b = *oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) { oqp->q_rdptr = oqp->q_buffer; } osalThreadDequeueNextI(&oqp->q_waiting, Q_OK); return (msg_t)b; }
/** * @brief Enables an endpoint. * @details This function enables an endpoint, both IN and/or OUT directions * depending on the configuration structure. * @note This function must be invoked in response of a SET_CONFIGURATION * or SET_INTERFACE message. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number * @param[in] epcp the endpoint configuration * * @iclass */ void usbInitEndpointI(USBDriver *usbp, usbep_t ep, const USBEndpointConfig *epcp) { osalDbgCheckClassI(); osalDbgCheck((usbp != NULL) && (epcp != NULL)); osalDbgAssert(usbp->state == USB_ACTIVE, "invalid state"); osalDbgAssert(usbp->epc[ep] == NULL, "already initialized"); /* Logically enabling the endpoint in the USBDriver structure.*/ if (epcp->in_state != NULL) memset(epcp->in_state, 0, sizeof(USBInEndpointState)); if (epcp->out_state != NULL) memset(epcp->out_state, 0, sizeof(USBOutEndpointState)); usbp->epc[ep] = epcp; /* Low level endpoint activation.*/ usb_lld_init_endpoint(usbp, ep); }
/** * @brief Can frame receive attempt. * @details The function tries to fetch a frame from a mailbox. * * @param[in] canp pointer to the @p CANDriver object * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @param[out] crfp pointer to the buffer where the CAN frame is copied * @return The operation result. * @retval false Frame fetched. * @retval true Mailbox empty. * * @iclass */ bool canTryReceiveI(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp) { osalDbgCheckClassI(); osalDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox <= (canmbx_t)CAN_RX_MAILBOXES)); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); /* If the RX mailbox is empty then the function fails.*/ if (!can_lld_is_rx_nonempty(canp, mailbox)) { return true; } /* Fetching the frame.*/ can_lld_receive(canp, mailbox, crfp); return false; }
/** * @brief Can frame transmission attempt. * @details The specified frame is queued for transmission, if the hardware * queue is full then the function fails. * * @param[in] canp pointer to the @p CANDriver object * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @param[in] ctfp pointer to the CAN frame to be transmitted * @return The operation result. * @retval false Frame transmitted. * @retval true Mailbox full. * * @iclass */ bool canTryTransmitI(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp) { osalDbgCheckClassI(); osalDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= (canmbx_t)CAN_TX_MAILBOXES)); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); /* If the RX mailbox is full then the function fails.*/ if (!can_lld_is_tx_empty(canp, mailbox)) { return true; } /* Transmitting frame.*/ can_lld_transmit(canp, mailbox, ctfp); return false; }
/** * @brief System timer handler. * @details The handler is used for scheduling and Virtual Timers management. * * @iclass */ void osalOsTimerHandlerI(void) { osalDbgCheckClassI(); }