From 309b1e411426e8d36d9a552ef2870da3db912a80 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 23 Oct 2011 11:39:45 +0000 Subject: Improvements to the USB driver, first phase. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3449 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/usb.h | 86 +++++++++++++++++---- os/hal/platforms/STM32/USBv1/usb_lld.c | 133 ++++++++++++++------------------- os/hal/platforms/STM32/USBv1/usb_lld.h | 20 ++--- os/hal/src/serial_usb.c | 91 +++++++++++++--------- os/hal/src/usb.c | 107 ++++++-------------------- os/kernel/include/chthreads.h | 10 +++ os/kernel/src/chqueues.c | 23 +++--- 7 files changed, 238 insertions(+), 232 deletions(-) (limited to 'os') diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h index 884b11e8d..18842abd3 100644 --- a/os/hal/include/usb.h +++ b/os/hal/include/usb.h @@ -172,11 +172,6 @@ USB_DESC_BYTE(bInterval) /** @} */ -/** - * @brief Returned by some functions to report a busy endpoint. - */ -#define USB_ENDPOINT_BUSY ((size_t)0xFFFFFFFF) - /** * @name Endpoint types and settings * @{ @@ -362,6 +357,75 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, */ #define usbGetReceiveStatusI(usbp, ep) ((usbp)->receiving & (1 << (ep))) +/** + * @brief Reads from a dedicated packet buffer. + * @pre In order to use this function he endpoint must have been + * initialized in packet mode. + * @note This function can be invoked both in thread and IRQ context. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the packet data + * @param[in] n maximum number of bytes to copy. This value must + * not exceed the maximum packet size for this endpoint. + * @return The received packet size regardless the specified + * @p n parameter. + * @retval 0 Zero size packet received. + * + * @special + */ +#define usbReadPacketBuffer(usbp, ep, buf, n) \ + usb_lld_read_packet_buffer(usbp, ep, buf, n) + +/** + * @brief Writes to a dedicated packet buffer. + * @pre In order to use this function he endpoint must have been + * initialized in packet mode. + * @note This function can be invoked both in thread and IRQ context. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @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. + * + * @special + */ +#define usbWritePacketBuffer(usbp, ep, buf, n) \ + usb_lld_write_packet_buffer(usbp, ep, buf, n) + +/** + * @brief Prepares for a receive transaction on an OUT endpoint. + * @pre In order to use this function he endpoint must have been + * initialized in transaction mode. + * @post The endpoint is ready for @p usbStartReceiveI(). + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[out] buf buffer where to copy the received data + * @param[in] n maximum number of bytes to copy + * + * @special + */ +#define usbPrepareReceive(usbp, ep, buf, n) \ + usb_lld_prepare_receive(usbp, ep, buf, n) + +/** + * @brief Prepares for a transmit transaction on an IN endpoint. + * @pre In order to use this function he endpoint must have been + * initialized in transaction mode. + * @post The endpoint is ready for @p usbStartTransmitI(). + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] buf buffer where to fetch the data to be transmitted + * @param[in] n maximum number of bytes to copy + * + * @special + */ +#define usbPrepareTransmit(usbp, ep, buf, n) \ + usb_lld_prepare_transmit(usbp, ep, buf, n) + /** * @brief Returns the exact size of a receive transaction. * @details The received size can be different from the size specified in @@ -417,7 +481,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, * callback in order to read the received setup packet. * @pre In order to use this function the endpoint must have been * initialized as a control endpoint. - * @post The endpoint is ready to accept another packet. + * @note This function can be invoked both in thread and IRQ context. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number @@ -511,14 +575,8 @@ extern "C" { const USBEndpointConfig *epcp); void usbDisableEndpointsI(USBDriver *usbp); void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf); - size_t usbReadPacketI(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n); - size_t usbWritePacketI(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n); - bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n); - bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n); + bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep); + bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep); bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep); bool_t usbStallTransmitI(USBDriver *usbp, usbep_t ep); void _usb_reset(USBDriver *usbp); diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.c b/os/hal/platforms/STM32/USBv1/usb_lld.c index 01bc50090..253f45197 100644 --- a/os/hal/platforms/STM32/USBv1/usb_lld.c +++ b/os/hal/platforms/STM32/USBv1/usb_lld.c @@ -109,58 +109,6 @@ static uint32_t pm_alloc(USBDriver *usbp, size_t size) { return next; } -/** - * @brief Copies a packet from memory into a packet buffer. - * - * @param[in] ep endpoint number - * @param[in] buf buffer where to fetch the endpoint data - * @param[in] n maximum number of bytes to copy - */ -static void write_packet(usbep_t ep, const uint8_t *buf, size_t n){ - uint32_t *pmap; - stm32_usb_descriptor_t *udp; - size_t count; - - udp = USB_GET_DESCRIPTOR(ep); - pmap = USB_ADDR2PTR(udp->TXADDR); - udp->TXCOUNT = n; - count = (n + 1) / 2; - while (count) { - *pmap++ = *(uint16_t *)buf; - buf += 2; - count--; - } - EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); -} - -/** - * @brief Copies a packet from a packet buffer into memory. - * - * @param[in] ep endpoint number - * @param[in] buf buffer where to copy the endpoint data - * @param[in] n maximum number of bytes to copy - * @return The packet size. - * @retval 0 Special case, zero sized packet. - */ -static size_t read_packet(usbep_t ep, uint8_t *buf, size_t n){ - uint32_t *pmap; - stm32_usb_descriptor_t *udp; - size_t count; - - udp = USB_GET_DESCRIPTOR(ep); - pmap = USB_ADDR2PTR(udp->RXADDR); - count = udp->RXCOUNT & RXCOUNT_COUNT_MASK; - if (n > count) - n = count; - count = (n + 1) / 2; - while (count) { - *(uint16_t *)buf = (uint16_t)*pmap++; - buf += 2; - count--; - } - return n; -} - /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -257,7 +205,8 @@ CH_IRQ_HANDLER(Vector90) { n = epcp->in_maxsize; else n = epcp->in_state->txsize; - write_packet(ep, epcp->in_state->txbuf, n); + usb_lld_write_packet_buffer(usbp, ep, epcp->in_state->txbuf, n); + usb_lld_start_in(usbp, ep); } else { /* Transfer completed, invokes the callback.*/ @@ -279,7 +228,10 @@ CH_IRQ_HANDLER(Vector90) { } else { /* Transaction mode.*/ - n = read_packet(ep, epcp->out_state->rxbuf, epcp->out_state->rxsize); + n = usb_lld_read_packet_buffer(usbp, ep, + epcp->out_state->rxbuf, + epcp->out_state->rxsize); + usb_lld_start_out(usbp, ep); epcp->out_state->rxbuf += n; epcp->out_state->rxcnt += n; epcp->out_state->rxsize -= n; @@ -569,14 +521,13 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { *(uint16_t *)buf = (uint16_t)*pmap++; buf += 2; } - EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); } /** - * @brief Reads a packet from the dedicated packet buffer. + * @brief Reads from a dedicated packet buffer. * @pre In order to use this function he endpoint must have been * initialized in packet mode. - * @post The endpoint is ready to accept another packet. + * @note This function can be invoked both in thread and IRQ context. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number @@ -589,8 +540,8 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { * * @notapi */ -size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n) { +size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n) { uint32_t *pmap; stm32_usb_descriptor_t *udp; size_t count; @@ -607,15 +558,14 @@ size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, buf += 2; n--; } - EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); return count; } /** - * @brief Writes a packet to the dedicated packet buffer. + * @brief Writes to a dedicated packet buffer. * @pre In order to use this function he endpoint must have been * initialized in packet mode. - * @post The endpoint is ready to transmit the packet. + * @note This function can be invoked both in thread and IRQ context. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number @@ -625,8 +575,8 @@ size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, * * @notapi */ -void usb_lld_write_packet(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n) { +void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { uint32_t *pmap; stm32_usb_descriptor_t *udp; @@ -640,21 +590,20 @@ void usb_lld_write_packet(USBDriver *usbp, usbep_t ep, buf += 2; n--; } - EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); } /** - * @brief Starts a receive operation on an OUT endpoint. + * @brief Prepares for a receive operation. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the endpoint data - * @param[in] n maximum number of bytes to copy in the buffer + * @param[out] buf buffer where to copy the received data + * @param[in] n maximum number of bytes to copy * * @notapi */ -void usb_lld_start_out(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n) { +void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n) { USBOutEndpointState *osp = usbp->epc[ep]->out_state; osp->rxbuf = buf; @@ -665,21 +614,20 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep, else osp->rxpkts = (uint16_t)((n + usbp->epc[ep]->out_maxsize - 1) / usbp->epc[ep]->out_maxsize); - EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); } /** - * @brief Starts a transmit operation on an IN endpoint. + * @brief Prepares for a transmit operation. * * @param[in] usbp pointer to the @p USBDriver object * @param[in] ep endpoint number - * @param[in] buf buffer where to fetch the endpoint data + * @param[in] buf buffer where to fetch the data to be transmitted * @param[in] n maximum number of bytes to copy * * @notapi */ -void usb_lld_start_in(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n) { +void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { USBInEndpointState *isp = usbp->epc[ep]->in_state; isp->txbuf = buf; @@ -687,7 +635,39 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep, isp->txcnt = 0; if (n > (size_t)usbp->epc[ep]->in_maxsize) n = (size_t)usbp->epc[ep]->in_maxsize; - write_packet(ep, buf, n); + usb_lld_write_packet_buffer(usbp, ep, buf, n); +} + +/** + * @brief Starts a receive operation on an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @notapi + */ +void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID); +} + +/** + * @brief Starts a transmit operation on an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] buf buffer where to fetch the endpoint data + * @param[in] n maximum number of bytes to copy + * + * @notapi + */ +void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + + EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); } /** @@ -701,6 +681,7 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep, void usb_lld_stall_out(USBDriver *usbp, usbep_t ep) { (void)usbp; + EPR_SET_STAT_RX(ep, EPR_STAT_RX_STALL); } diff --git a/os/hal/platforms/STM32/USBv1/usb_lld.h b/os/hal/platforms/STM32/USBv1/usb_lld.h index 47160af56..0ee9fd6c2 100644 --- a/os/hal/platforms/STM32/USBv1/usb_lld.h +++ b/os/hal/platforms/STM32/USBv1/usb_lld.h @@ -375,16 +375,18 @@ extern "C" { usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep); usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep); void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf); - size_t usb_lld_read_packet(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n); - void usb_lld_write_packet(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n); - void usb_lld_start_out(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n); - void usb_lld_start_in(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n); - void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); + size_t usb_lld_read_packet_buffer(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n); + void usb_lld_write_packet_buffer(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n); + void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n); + void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n); + void usb_lld_start_out(USBDriver *usbp, usbep_t ep); + void usb_lld_start_in(USBDriver *usbp, usbep_t ep); void usb_lld_stall_out(USBDriver *usbp, usbep_t ep); + void usb_lld_stall_in(USBDriver *usbp, usbep_t ep); void usb_lld_clear_out(USBDriver *usbp, usbep_t ep); void usb_lld_clear_in(USBDriver *usbp, usbep_t ep); #ifdef __cplusplus diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 16822502a..ea434b197 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -118,21 +118,26 @@ static const struct SerialUSBDriverVMT vmt = { */ static void inotify(GenericQueue *qp) { SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr; - size_t n; /* Writes to the input queue can only happen when the queue has been emptied, then a whole packet is loaded in the queue.*/ - if (chIQIsEmptyI(&sdup->iqueue)) { - - n = usbReadPacketI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP, - sdup->iqueue.q_buffer, SERIAL_USB_BUFFERS_SIZE); - if (n != USB_ENDPOINT_BUSY) { - chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; - } + if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) && + chIQIsEmptyI(&sdup->iqueue)) { + chSysUnlock(); + + /* Unlocked to make the potentially long read operation preemptable.*/ + size_t n = usbReadPacketBuffer(sdup->config->usbp, + USB_CDC_DATA_AVAILABLE_EP, + sdup->iqueue.q_buffer, + SERIAL_USB_BUFFERS_SIZE); + + chSysLock(); + usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); + chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + sdup->iqueue.q_counter = n; + while (notempty(&sdup->iqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } } @@ -141,14 +146,20 @@ static void inotify(GenericQueue *qp) { */ static void onotify(GenericQueue *qp) { SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr; - size_t w, n; + size_t n; /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); - w = usbWritePacketI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP, - sdup->oqueue.q_buffer, n); - if (w != USB_ENDPOINT_BUSY) { + if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) { + chSysUnlock(); + + /* Unlocked to make the potentially long write operation preemptable.*/ + usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP, + sdup->oqueue.q_buffer, n); + + chSysLock(); + usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); @@ -285,21 +296,27 @@ bool_t sduRequestsHook(USBDriver *usbp) { */ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { SerialUSBDriver *sdup = usbp->param; - size_t n, w; + size_t n; chSysLockFromIsr(); /* If there is any data in the output queue then it is sent within a single packet and the queue is emptied.*/ n = chOQGetFullI(&sdup->oqueue); if (n > 0) { - w = usbWritePacketI(usbp, ep, sdup->oqueue.q_buffer, n); - if (w != USB_ENDPOINT_BUSY) { - chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); - while (notempty(&sdup->oqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; - } + /* The endpoint cannot be busy, we are in the context of the callback, + so it is safe to transmit without a check.*/ + chSysUnlockFromIsr(); + + /* Unlocked to make the potentially long write operation preemptable.*/ + usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n); + + chSysLockFromIsr(); + usbStartTransmitI(usbp, ep); + chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); + sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; + sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); + while (notempty(&sdup->oqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } chSysUnlockFromIsr(); } @@ -319,17 +336,23 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { /* Writes to the input queue can only happen when the queue has been emptied, then a whole packet is loaded in the queue.*/ if (chIQIsEmptyI(&sdup->iqueue)) { + /* The endpoint cannot be busy, we are in the context of the callback, + so a packet is in the buffer for sure.*/ size_t n; - n = usbReadPacketI(usbp, ep, sdup->iqueue.q_buffer, - SERIAL_USB_BUFFERS_SIZE); - if (n != USB_ENDPOINT_BUSY) { - chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; - } + chSysUnlockFromIsr(); + + /* Unlocked to make the potentially long write operation preemptable.*/ + n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer, + SERIAL_USB_BUFFERS_SIZE); + + chSysLockFromIsr(); + usbStartReceiveI(usbp, ep); + chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); + sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; + sdup->iqueue.q_counter = n; + while (notempty(&sdup->iqueue.q_waiting)) + chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } chSysUnlockFromIsr(); } diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c index 44a772ab1..30919580c 100644 --- a/os/hal/src/usb.c +++ b/os/hal/src/usb.c @@ -309,7 +309,7 @@ void usbInitEndpointI(USBDriver *usbp, usbep_t ep, chDbgCheck((usbp != NULL) && (epcp != NULL), "usbInitEndpointI"); chDbgAssert(usbp->state == USB_ACTIVE, "usbEnableEndpointI(), #1", "invalid state"); - chDbgAssert(usbp->epc[ep] != NULL, + chDbgAssert(usbp->epc[ep] == NULL, "usbEnableEndpointI(), #2", "already initialized"); /* Logically enabling the endpoint in the USBDriver structure.*/ @@ -351,127 +351,55 @@ void usbDisableEndpointsI(USBDriver *usbp) { usb_lld_disable_endpoints(usbp); } -/** - * @brief Reads a packet from the dedicated packet buffer. - * @pre In order to use this function he endpoint must have been - * initialized in packet mode. - * @post The endpoint is ready to accept another packet. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[out] buf buffer where to copy the packet data - * @param[in] n maximum number of bytes to copy. This value must - * not exceed the maximum packet size for this endpoint. - * @return The received packet size regardless the specified - * @p n parameter. - * @retval USB_ENDPOINT_BUSY Endpoint busy receiving. - * @retval 0 Zero size packet received. - * - * @iclass - */ -size_t usbReadPacketI(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n) { - - chDbgCheckClassI(); - chDbgCheck((usbp != NULL) && (buf != NULL), "usbReadPacketI"); - - if (usbGetReceiveStatusI(usbp, ep)) - return USB_ENDPOINT_BUSY; - - usbp->receiving |= (1 << ep); - return usb_lld_read_packet(usbp, ep, buf, n);; -} - -/** - * @brief Writes a packet to the dedicated packet buffer. - * @pre In order to use this function he endpoint must have been - * initialized in packet mode. - * @post The endpoint is ready to transmit the packet. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @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. - * @return The operation status. - * @retval USB_ENDPOINT_BUSY Endpoint busy transmitting. - * @retval 0 Operation complete. - * - * @iclass - */ -size_t usbWritePacketI(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n) { - - chDbgCheckClassI(); - chDbgCheck((usbp != NULL) && (buf != NULL), "usbWritePacketI"); - - if (usbGetTransmitStatusI(usbp, ep)) - return USB_ENDPOINT_BUSY; - - usbp->transmitting |= (1 << ep); - usb_lld_write_packet(usbp, ep, buf, n); - return 0; -} - /** * @brief Starts a receive transaction on an OUT endpoint. - * @pre In order to use this function he endpoint must have been - * initialized in transaction mode. * @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 - * @param[out] buf buffer where to copy the received data - * @param[in] n maximum number of bytes to copy * @return The operation status. * @retval FALSE Operation started successfully. * @retval TRUE Endpoint busy, operation not started. * * @iclass */ -bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n) { +bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep) { chDbgCheckClassI(); - chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartReceiveI"); + chDbgCheck(usbp != NULL, "usbStartReceiveI"); if (usbGetReceiveStatusI(usbp, ep)) return TRUE; usbp->receiving |= (1 << ep); - usb_lld_start_out(usbp, ep, buf, n); + usb_lld_start_out(usbp, ep); return FALSE; } /** * @brief Starts a transmit transaction on an IN endpoint. - * @pre In order to use this function he endpoint must have been - * initialized in transaction mode. * @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 - * @param[in] buf buffer where to fetch the data to be transmitted - * @param[in] n maximum number of bytes to copy * @return The operation status. * @retval FALSE Operation started successfully. * @retval TRUE Endpoint busy, operation not started. * * @iclass */ -bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n) { +bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep) { chDbgCheckClassI(); - chDbgCheck((usbp != NULL) && (buf != NULL), "usbStartTransmitI"); + chDbgCheck(usbp != NULL, "usbStartTransmitI"); if (usbGetTransmitStatusI(usbp, ep)) return TRUE; usbp->transmitting |= (1 << ep); - usb_lld_start_in(usbp, ep, buf, n); + usb_lld_start_in(usbp, ep); return FALSE; } @@ -597,13 +525,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { if (usbp->ep0n > 0) { /* Starts the transmit phase.*/ usbp->ep0state = USB_EP0_TX; - usb_lld_start_in(usbp, 0, usbp->ep0next, usbp->ep0n); + usb_lld_prepare_transmit(usbp, 0, usbp->ep0next, usbp->ep0n); + usb_lld_start_in(usbp, 0); } else { /* No transmission phase, directly receiving the zero sized status packet.*/ usbp->ep0state = USB_EP0_WAITING_STS; - usb_lld_start_out(usbp, 0, NULL, 0); + usb_lld_prepare_receive(usbp, 0, NULL, 0); + usb_lld_start_out(usbp, 0); } } else { @@ -611,13 +541,15 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { if (usbp->ep0n > 0) { /* Starts the receive phase.*/ usbp->ep0state = USB_EP0_RX; - usb_lld_start_out(usbp, 0, usbp->ep0next, usbp->ep0n); + usb_lld_prepare_receive(usbp, 0, usbp->ep0next, usbp->ep0n); + usb_lld_start_out(usbp, 0); } else { /* No receive phase, directly sending the zero sized status packet.*/ usbp->ep0state = USB_EP0_SENDING_STS; - usb_lld_start_in(usbp, 0, NULL, 0); + usb_lld_prepare_transmit(usbp, 0, NULL, 0); + usb_lld_start_in(usbp, 0); } } } @@ -644,13 +576,15 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) { transmitted.*/ if ((usbp->ep0n < max) && ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) { - usb_lld_start_in(usbp, 0, NULL, 0); + usb_lld_prepare_transmit(usbp, 0, NULL, 0); + usb_lld_start_in(usbp, 0); return; } /* Transmit phase over, receiving the zero sized status packet.*/ usbp->ep0state = USB_EP0_WAITING_STS; - usb_lld_start_out(usbp, 0, NULL, 0); + usb_lld_prepare_receive(usbp, 0, NULL, 0); + usb_lld_start_out(usbp, 0); return; case USB_EP0_SENDING_STS: /* Status packet sent, invoking the callback if defined.*/ @@ -687,7 +621,8 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) { case USB_EP0_RX: /* Receive phase over, sending the zero sized status packet.*/ usbp->ep0state = USB_EP0_SENDING_STS; - usb_lld_start_in(usbp, 0, NULL, 0); + usb_lld_prepare_transmit(usbp, 0, NULL, 0); + usb_lld_start_in(usbp, 0); return; case USB_EP0_WAITING_STS: /* Status packet received, it must be zero sized, invoking the callback diff --git a/os/kernel/include/chthreads.h b/os/kernel/include/chthreads.h index 582b4e1e1..5848d5643 100644 --- a/os/kernel/include/chthreads.h +++ b/os/kernel/include/chthreads.h @@ -51,6 +51,16 @@ #define THD_STATE_WTMSG 12 /**< @brief Waiting for a message. */ #define THD_STATE_WTQUEUE 13 /**< @brief Waiting on an I/O queue. */ #define THD_STATE_FINAL 14 /**< @brief Thread terminated. */ + +/** + * @brief Thread states as array of strings. + * @details Each element in an array initialized with this macro can be + * indexed using the numeric thread state values. + */ +#define THD_STATE_NAMES \ + "READY", "CURRENT", "SUSPENDED", "WTSEM", "WTMTX", "WTCOND", "SLEEPING", \ + "WTEXIT", "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "WTQUEUE", \ + "FINAL" /** @} */ /** diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index cf3d21732..b32ccf803 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -152,9 +152,8 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { * @details This function reads a byte value from an input queue. If the queue * is empty then the calling thread is suspended until a byte arrives * in the queue or a timeout occurs. - * @note The callback is invoked if the queue is empty before entering the - * @p THD_STATE_WTQUEUE state in order to solicit the low level to - * start queue filling. + * @note The callback is invoked before reading the character from the + * buffer or before entering the state @p THD_STATE_WTQUEUE. * * @param[in] iqp pointer to an @p InputQueue structure * @param[in] time the number of ticks before the operation timeouts, @@ -172,12 +171,11 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { uint8_t b; chSysLock(); + if (iqp->q_notify) + iqp->q_notify(iqp); + while (chIQIsEmptyI(iqp)) { msg_t msg; - - if (iqp->q_notify) - iqp->q_notify(iqp); - if ((msg = qwait((GenericQueue *)iqp, time)) < Q_OK) { chSysUnlock(); return msg; @@ -201,9 +199,8 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { * been reset. * @note The function is not atomic, if you need atomicity it is suggested * to use a semaphore or a mutex for mutual exclusion. - * @note The callback is invoked if the queue is empty before entering the - * @p THD_STATE_WTQUEUE state in order to solicit the low level to - * start queue filling. + * @note The callback is invoked before reading each character from the + * buffer or before entering the state @p THD_STATE_WTQUEUE. * * @param[in] iqp pointer to an @p InputQueue structure * @param[out] bp pointer to the data buffer @@ -227,10 +224,10 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, chSysLock(); while (TRUE) { - while (chIQIsEmptyI(iqp)) { - if (nfy) - nfy(iqp); + if (nfy) + nfy(iqp); + while (chIQIsEmptyI(iqp)) { if (qwait((GenericQueue *)iqp, time) != Q_OK) { chSysUnlock(); return r; -- cgit v1.2.3