/** * @brief Deactivates the USB peripheral. * * @param[in] usbp pointer to the @p USBDriver object * * @api */ void usbStop(USBDriver *usbp) { unsigned i; osalDbgCheck(usbp != NULL); osalSysLock(); osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) || (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) || (usbp->state == USB_SUSPENDED), "invalid state"); usb_lld_stop(usbp); usbp->config = NULL; usbp->state = USB_STOP; /* Resetting all ongoing synchronous operations.*/ for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) { #if USB_USE_WAIT == TRUE if (usbp->epc[i] != NULL) { 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); } } #endif usbp->epc[i] = NULL; } osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Writes to a TX FIFO fetching data from a queue. * * @param[in] fifop pointer to the FIFO register * @param[in] oqp pointer to an @p output_queue_t object * @param[in] n maximum number of bytes to copy * * @notapi */ static void otg_fifo_write_from_queue(volatile uint32_t *fifop, output_queue_t *oqp, size_t n) { uint32_t w; size_t i; /* Pushing all complete words.*/ i = 0; w = 0; while (i < n) { w |= (uint32_t)*oqp->q_rdptr << ((i & 3) * 8); oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) { oqp->q_rdptr = oqp->q_buffer; } i++; if ((i & 3) == 0) { *fifop = w; w = 0; } } /* Remaining bytes.*/ if ((i & 3) != 0) { *fifop = w; } /* Updating queue.*/ osalSysLock(); oqp->q_counter += n; osalThreadDequeueAllI(&oqp->q_waiting, Q_OK); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Aborts the ongoing SPI operation, if any. * * @param[in] spip pointer to the @p SPIDriver object * * @api */ void spiAbort(SPIDriver *spip) { osalSysLock(); osalDbgAssert((spip->state == SPI_READY) || (spip->state == SPI_ACTIVE), "invalid state"); if (spip->state == SPI_ACTIVE) { spiAbortI(spip); osalOsRescheduleS(); } osalSysUnlock(); }
/** * @brief Stops the driver. * @details Any thread waiting on the driver's queues will be awakened with * the message @p Q_RESET. * * @param[in] sdp pointer to a @p SerialDriver object * * @api */ void sdStop(SerialDriver *sdp) { osalDbgCheck(sdp != NULL); osalSysLock(); osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), "invalid state"); sd_lld_stop(sdp); sdp->state = SD_STOP; oqResetI(&sdp->oqueue); iqResetI(&sdp->iqueue); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Deactivates the CAN peripheral. * * @param[in] canp pointer to the @p CANDriver object * * @api */ void canStop(CANDriver *canp) { osalDbgCheck(canp != NULL); osalSysLock(); osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), "invalid state"); can_lld_stop(canp); canp->state = CAN_STOP; osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET); osalThreadDequeueAllI(&canp->txqueue, MSG_RESET); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Enforces leaving the sleep mode. * @note The sleep mode is supposed to be usually exited automatically by * an hardware event. * * @param[in] canp pointer to the @p CANDriver object */ void canWakeup(CANDriver *canp) { osalDbgCheck(canp != NULL); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); if (canp->state == CAN_SLEEP) { can_lld_wakeup(canp); canp->state = CAN_READY; osalEventBroadcastFlagsI(&canp->wakeup_event, (eventflags_t)0); osalOsRescheduleS(); } osalSysUnlock(); }
/** * @brief Writes to a TX FIFO fetching data from a queue. * * @param[in] fifop pointer to the FIFO register * @param[in] oqp pointer to an @p output_queue_t object * @param[in] n maximum number of bytes to copy * * @notapi */ static void otg_fifo_write_from_queue(volatile uint32_t *fifop, output_queue_t *oqp, size_t n) { size_t ntogo; ntogo = n; while (ntogo > 0) { uint32_t w, i; size_t nw = ntogo / 4; if (nw > 0) { size_t streak; uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4; ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4; oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak); if (oqp->q_rdptr >= oqp->q_top) { oqp->q_rdptr = oqp->q_buffer; continue; } } /* If this condition is not satisfied then there is a word lying across queue circular buffer boundary or there are some remaining bytes.*/ if (ntogo <= 0) break; /* One byte at time.*/ w = 0; i = 0; while ((ntogo > 0) && (i < 4)) { w |= (uint32_t)*oqp->q_rdptr++ << (i * 8); if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; ntogo--; i++; } *fifop = w; } /* Updating queue.*/ osalSysLock(); oqp->q_counter += n; osalThreadDequeueAllI(&oqp->q_waiting, Q_OK); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Reads a packet from the RXFIFO. * * @param[in] fifop pointer to the FIFO register * @param[in] iqp pointer to an @p input_queue_t object * @param[in] n number of bytes to pull from the FIFO * * @notapi */ static void otg_fifo_read_to_queue(volatile uint32_t *fifop, input_queue_t *iqp, size_t n) { size_t ntogo; ntogo = n; while (ntogo > 0) { uint32_t w, i; size_t nw = ntogo / 4; if (nw > 0) { size_t streak; uint32_t nw2end = (iqp->q_wrptr - iqp->q_wrptr) / 4; ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4; iqp->q_wrptr = otg_do_pop(fifop, iqp->q_wrptr, streak); if (iqp->q_wrptr >= iqp->q_top) { iqp->q_wrptr = iqp->q_buffer; continue; } } /* If this condition is not satisfied then there is a word lying across queue circular buffer boundary or there are some remaining bytes.*/ if (ntogo <= 0) break; /* One byte at time.*/ w = *fifop; i = 0; while ((ntogo > 0) && (i < 4)) { *iqp->q_wrptr++ = (uint8_t)(w >> (i * 8)); if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; ntogo--; i++; } } /* Updating queue.*/ osalSysLock(); iqp->q_counter += n; osalThreadDequeueAllI(&iqp->q_waiting, Q_OK); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Enters the sleep mode. * @details This function puts the CAN driver in sleep mode and broadcasts * the @p sleep_event event source. * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported * by the low level driver. * * @param[in] canp pointer to the @p CANDriver object * * @api */ void canSleep(CANDriver *canp) { osalDbgCheck(canp != NULL); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); if (canp->state == CAN_READY) { can_lld_sleep(canp); canp->state = CAN_SLEEP; #if CAN_ENFORCE_USE_CALLBACKS == FALSE osalEventBroadcastFlagsI(&canp->sleep_event, (eventflags_t)0); osalOsRescheduleS(); #endif } osalSysUnlock(); }
/** * @brief Deactivates the CAN peripheral. * * @param[in] canp pointer to the @p CANDriver object * * @api */ void canStop(CANDriver *canp) { osalDbgCheck(canp != NULL); osalSysLock(); osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), "invalid state"); /* The low level driver is stopped.*/ can_lld_stop(canp); canp->state = CAN_STOP; /* Threads waiting on CAN APIs are notified that the driver has been stopped in order to not have stuck threads.*/ osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET); osalThreadDequeueAllI(&canp->txqueue, MSG_RESET); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Stops the driver. * @details Any thread waiting on the driver's queues will be awakened with * the message @p MSG_RESET. * * @param[in] uhdp pointer to a @p USBHIDDriver object * * @api */ void hidStop(USBHIDDriver *uhdp) { USBDriver *usbp = uhdp->config->usbp; osalDbgCheck(uhdp != NULL); osalSysLock(); osalDbgAssert((uhdp->state == HID_STOP) || (uhdp->state == HID_READY), "invalid state"); /* Driver in stopped state.*/ usbp->in_params[uhdp->config->int_in - 1U] = NULL; usbp->out_params[uhdp->config->int_out - 1U] = NULL; uhdp->state = HID_STOP; /* Enforces a disconnection.*/ hidDisconnectI(uhdp); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Stops the driver. * @details Any thread waiting on the driver's queues will be awakened with * the message @p Q_RESET. * * @param[in] hiddp pointer to a @p HIDDebugDriver object * * @api */ void hidDebugStop(HIDDebugDriver *hiddp) { USBDriver *usbp = hiddp->config->usbp; osalDbgCheck(hiddp != NULL); osalSysLock(); osalDbgAssert((hiddp->state == HIDDEBUG_STOP) || (hiddp->state == HIDDEBUG_READY), "invalid state"); /* Driver in stopped state.*/ usbp->in_params[hiddp->config->ep_in - 1U] = NULL; hiddp->state = HIDDEBUG_STOP; /* Stop the flush timer */ chVTResetI(&hid_debug_flush_timer); /* Queues reset in order to signal the driver stop to the application.*/ chnAddFlagsI(hiddp, CHN_DISCONNECTED); iqResetI(&hiddp->oqueue); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Stops the driver. * @details Any thread waiting on the driver's queues will be awakened with * the message @p Q_RESET. * * @param[in] sdup pointer to a @p SerialUSBDriver object * * @api */ void sduStop(SerialUSBDriver *sdup) { USBDriver *usbp = sdup->config->usbp; osalDbgCheck(sdup != NULL); osalSysLock(); osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), "invalid state"); /* Driver in stopped state.*/ usbp->in_params[sdup->config->bulk_in - 1U] = NULL; usbp->out_params[sdup->config->bulk_out - 1U] = NULL; if (sdup->config->int_in > 0U) { usbp->in_params[sdup->config->int_in - 1U] = NULL; } sdup->state = SDU_STOP; /* Enforces a disconnection.*/ sduDisconnectI(sdup); osalOsRescheduleS(); osalSysUnlock(); }
/** * @brief Stops the driver. * @details Any thread waiting on the driver's queues will be awakened with * the message @p Q_RESET. * * @param[in] sdup pointer to a @p SerialUSBDriver object * * @api */ void sduStop(SerialUSBDriver *sdup) { USBDriver *usbp = sdup->config->usbp; osalDbgCheck(sdup != NULL); osalSysLock(); osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), "invalid state"); /* Driver in stopped state.*/ usbp->in_params[sdup->config->bulk_in - 1U] = NULL; usbp->out_params[sdup->config->bulk_out - 1U] = NULL; if (sdup->config->int_in > 0U) { usbp->in_params[sdup->config->int_in - 1U] = NULL; } sdup->state = SDU_STOP; /* Queues reset in order to signal the driver stop to the application.*/ chnAddFlagsI(sdup, CHN_DISCONNECTED); iqResetI(&sdup->iqueue); oqResetI(&sdup->oqueue); osalOsRescheduleS(); osalSysUnlock(); }