/** * @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(); }
static void usb_fifo_read(USBDriver *usbp, usbep_t ep, size_t n) { const USBEndpointConfig *epcp = usbp->epc[ep]; USBOutEndpointState *osp = epcp->out_state; syssts_t sts; if (n > epcp->out_maxsize) n = epcp->out_maxsize; /* Must lock for entire operation to ensure nothing changes the ENUM value */ sts = osalSysGetStatusAndLockX(); UENUM = ep & 0xf; if (osp->rxqueued) { input_queue_t *inq = osp->mode.queue.rxqueue; uint8_t i; for (i = 0; i < n; ++i) { uint8_t b = UEDATX; *inq->q_wrptr++ = b; if (inq->q_wrptr >= inq->q_top) { inq->q_wrptr = inq->q_buffer; } } /* Update queue state */ inq->q_counter += n; osalThreadDequeueAllI(&inq->q_waiting, Q_OK); } else { uint8_t i; for (i = 0; i < n; ++i) { osp->mode.linear.rxbuf[i] = UEDATX; } osp->mode.linear.rxbuf += n; } osalSysRestoreStatusX(sts); }
static void usb_fifo_write(USBDriver *usbp, usbep_t ep, size_t n) { const USBEndpointConfig *epcp = usbp->epc[ep]; USBInEndpointState *isp = epcp->in_state; syssts_t sts; if (n > epcp->in_maxsize) n = epcp->in_maxsize; /* Must lock for entire operation to ensure nothing changes the ENUM value */ sts = osalSysGetStatusAndLockX(); UENUM = ep & 0xf; if (isp->txqueued) { output_queue_t *outq = isp->mode.queue.txqueue; uint8_t i; /* TODO not enough for a 256b endpoint! */ for (i = 0; i < n; ++i) { uint8_t b = *outq->q_rdptr++; UEDATX = b; if (outq->q_rdptr >= outq->q_top) { outq->q_rdptr = outq->q_buffer; } } /* Update queue state */ outq->q_counter += n; osalThreadDequeueAllI(&outq->q_waiting, Q_OK); } else { uint8_t i; /* TODO not enough for a 256b endpoint! */ for (i = 0; i < n; ++i) { UEDATX = isp->mode.linear.txbuf[i]; } isp->mode.linear.txbuf += n; } isp->last_tx_size = n; osalSysRestoreStatusX(sts); }
/** * @brief Writes to a dedicated packet buffer. * * @param[in] udp pointer to a @p stm32_usb_descriptor_t * @param[in] buf buffer where to fetch the packet data * @param[in] n maximum number of bytes to copy. This value must * not exceed the maximum packet size for this endpoint. * * @notapi */ static void usb_packet_write_from_queue(stm32_usb_descriptor_t *udp, output_queue_t *oqp, size_t n) { size_t nhw; syssts_t sts; stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->TXADDR0); nhw = n / 2; while (nhw > 0) { stm32_usb_pma_t w; w = (stm32_usb_pma_t)*oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; w |= (stm32_usb_pma_t)*oqp->q_rdptr++ << 8; if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; *pmap++ = w; nhw--; } /* Last byte for odd numbers.*/ if ((n & 1) != 0) { *pmap = (stm32_usb_pma_t)*oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; } /* Updating queue.*/ sts = osalSysGetStatusAndLockX(); oqp->q_counter += n; osalThreadDequeueAllI(&oqp->q_waiting, Q_OK); osalSysRestoreStatusX(sts); }
/** * @brief Reads from a dedicated packet buffer. * * @param[in] udp pointer to a @p stm32_usb_descriptor_t * @param[in] iqp pointer to an @p input_queue_t object * @param[in] n maximum number of bytes to copy. This value must * not exceed the maximum packet size for this endpoint. * * @notapi */ static void usb_packet_read_to_queue(stm32_usb_descriptor_t *udp, input_queue_t *iqp, size_t n) { size_t nhw; stm32_usb_pma_t *pmap= USB_ADDR2PTR(udp->RXADDR0); nhw = n / 2; while (nhw > 0) { stm32_usb_pma_t w; w = *pmap++; *iqp->q_wrptr++ = (uint8_t)w; if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; *iqp->q_wrptr++ = (uint8_t)(w >> 8); if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; nhw--; } /* Last byte for odd numbers.*/ if ((n & 1) != 0) { *iqp->q_wrptr++ = (uint8_t)*pmap; if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; } /* Updating queue.*/ osalSysLockFromISR(); iqp->q_counter += n; osalThreadDequeueAllI(&iqp->q_waiting, Q_OK); osalSysUnlockFromISR(); }
/** * @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 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 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 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 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(); }