From de202dd376ea3109e21f535554647689dda23c7b Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Mon, 28 Dec 2015 11:16:40 +0000 Subject: [PATCH] New USB API finalized, updated OTGv1, USBv1 not yet updated. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8653 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/usb.h | 22 ++-- os/hal/ports/STM32/LLD/OTGv1/usb_lld.c | 104 +++++++-------- os/hal/ports/STM32/LLD/OTGv1/usb_lld.h | 2 - os/hal/src/serial_usb.c | 48 ++----- os/hal/src/usb.c | 159 +++++++++-------------- testhal/STM32/STM32F7xx/USB_RAW/Makefile | 2 +- testhal/STM32/STM32F7xx/USB_RAW/main.c | 39 ++++-- 7 files changed, 158 insertions(+), 218 deletions(-) diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h index 4aed90a08..cd2384b26 100644 --- a/os/hal/include/usb.h +++ b/os/hal/include/usb.h @@ -412,9 +412,9 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, * @param[in] usbp pointer to the @p USBDriver object * @return The current frame number. * - * @api + * @xclass */ -#define usbGetFrameNumber(usbp) usb_lld_get_frame_number(usbp) +#define usbGetFrameNumberX(usbp) usb_lld_get_frame_number(usbp) /** * @brief Returns the status of an IN endpoint. @@ -454,9 +454,9 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, * @param[in] ep endpoint number * @return Received data size. * - * @iclass + * @xclass */ -#define usbGetReceiveTransactionSizeI(usbp, ep) \ +#define usbGetReceiveTransactionSizeX(usbp, ep) \ usb_lld_get_transaction_size(usbp, ep) /** @@ -469,7 +469,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, * @param[in] n number of bytes to be transferred * @param[in] endcb callback to be invoked after the transfer or @p NULL * - * @api + * @special */ #define usbSetupTransfer(usbp, buf, n, endcb) { \ (usbp)->ep0next = (buf); \ @@ -580,7 +580,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp, } \ osalSysLockFromISR(); \ osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \ - usbGetReceiveTransactionSizeI(usbp, ep)); \ + usbGetReceiveTransactionSizeX(usbp, ep)); \ osalSysUnlockFromISR(); \ } #else @@ -608,12 +608,10 @@ extern "C" { const USBEndpointConfig *epcp); void usbDisableEndpointsI(USBDriver *usbp); void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf); - void usbPrepareReceive(USBDriver *usbp, usbep_t ep, - uint8_t *buf, size_t n); - void usbPrepareTransmit(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n); - bool usbStartReceiveI(USBDriver *usbp, usbep_t ep); - bool usbStartTransmitI(USBDriver *usbp, usbep_t ep); + void usbStartReceiveI(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n); + void usbStartTransmitI(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n); #if USB_USE_WAIT == TRUE msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n); msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n); diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c index a4a784d2a..e0d817d05 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c +++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c @@ -369,7 +369,6 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) { cover the remaining.*/ isp->txsize = isp->totsize - isp->txsize; isp->txcnt = 0; - usb_lld_prepare_transmit(usbp, ep); osalSysLockFromISR(); usb_lld_start_in(usbp, ep); osalSysUnlockFromISR(); @@ -415,13 +414,14 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) { /* Receive transfer complete.*/ USBOutEndpointState *osp = usbp->epc[ep]->out_state; - if (osp->rxsize < osp->totsize) { + /* A short packet always terminates a transaction.*/ + if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) && + (osp->rxsize < osp->totsize)) { /* In case the transaction covered only part of the total transfer then another transaction is immediately started in order to cover the remaining.*/ osp->rxsize = osp->totsize - osp->rxsize; osp->rxcnt = 0; - usb_lld_prepare_receive(usbp, ep); osalSysLockFromISR(); usb_lld_start_out(usbp, ep); osalSysUnlockFromISR(); @@ -476,7 +476,6 @@ static void otg_isoc_in_failed_handler(USBDriver *usbp) { * * @notapi */ - static void otg_isoc_out_failed_handler(USBDriver *usbp) { usbep_t ep; stm32_otg_t *otgp = usbp->otg; @@ -1134,60 +1133,6 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) { memcpy(buf, usbp->epc[ep]->setup_buf, 8); } -/** - * @brief Prepares for a receive operation. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) { - uint32_t pcnt; - USBOutEndpointState *osp = usbp->epc[ep]->out_state; - - /* Transfer initialization.*/ - osp->totsize = osp->rxsize; - if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE)) - osp->rxsize = EP0_MAX_OUTSIZE; - - pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) / - usbp->epc[ep]->out_maxsize; - usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) | - DOEPTSIZ_XFRSIZ(osp->rxsize); - -} - -/** - * @brief Prepares for a transmit operation. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @notapi - */ -void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - /* Transfer initialization.*/ - isp->totsize = isp->txsize; - if (isp->txsize == 0) { - /* Special case, sending zero size packet.*/ - usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0); - } - else { - if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE)) - isp->txsize = EP0_MAX_INSIZE; - - /* Normal case.*/ - uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) / - usbp->epc[ep]->in_maxsize; - /* TODO: Support more than one packet per frame for isochronous transfers.*/ - usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) | - DIEPTSIZ_XFRSIZ(isp->txsize); - } -} - /** * @brief Starts a receive operation on an OUT endpoint. * @@ -1197,7 +1142,28 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) { * @notapi */ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { + uint32_t pcnt, rxsize; + USBOutEndpointState *osp = usbp->epc[ep]->out_state; + /* Transfer initialization.*/ + osp->totsize = osp->rxsize; + if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE)) + osp->rxsize = EP0_MAX_OUTSIZE; + + /* Transaction size is rounded to a multiple of packet size because the + following requirement in the RM: + "For OUT transfers, the transfer size field in the endpoint's transfer + size register must be a multiple of the maximum packet size of the + endpoint, adjusted to the Word boundary".*/ + pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) / + usbp->epc[ep]->out_maxsize; + rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU; + + /*Setting up transaction parameters in DOEPTSIZ.*/ + usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) | + DOEPTSIZ_XFRSIZ(rxsize); + + /* Special case of isochronous endpoint.*/ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { /* Odd/even bit toggling for isochronous endpoint.*/ if (usbp->otg->DSTS & DSTS_FNSOF_ODD) @@ -1206,6 +1172,7 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM; } + /* Starting operation.*/ usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK; } @@ -1218,7 +1185,27 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) { * @notapi */ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { + USBInEndpointState *isp = usbp->epc[ep]->in_state; + /* Transfer initialization.*/ + isp->totsize = isp->txsize; + if (isp->txsize == 0) { + /* Special case, sending zero size packet.*/ + usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0); + } + else { + if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE)) + isp->txsize = EP0_MAX_INSIZE; + + /* Normal case.*/ + uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) / + usbp->epc[ep]->in_maxsize; + /* TODO: Support more than one packet per frame for isochronous transfers.*/ + usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) | + DIEPTSIZ_XFRSIZ(isp->txsize); + } + + /* Special case of isochronous endpoint.*/ if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) { /* Odd/even bit toggling.*/ if (usbp->otg->DSTS & DSTS_FNSOF_ODD) @@ -1227,6 +1214,7 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM; } + /* Starting operation.*/ usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK; usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep); } diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h index c90424c36..85038a9e2 100644 --- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h +++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h @@ -540,8 +540,6 @@ 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); - void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep); - void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep); 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); diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index a5e8247a8..d4525c52f 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -146,13 +146,8 @@ static void ibnotify(io_buffers_queue_t *bqp) { uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue); if (buf != NULL) { /* Buffer found, starting a new transaction.*/ - osalSysUnlock(); - - usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); - - osalSysLock(); - (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out); + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, + buf, SERIAL_USB_BUFFERS_SIZE); } } } @@ -179,12 +174,7 @@ static void obnotify(io_buffers_queue_t *bqp) { uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n); if (buf != NULL) { /* Buffer found, starting a new transaction.*/ - osalSysUnlock(); - - usbPrepareTransmit(sdup->config->usbp, sdup->config->bulk_in, buf, n); - - osalSysLock(); - (void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in); + usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n); } } } @@ -319,9 +309,8 @@ void sduConfigureHookI(SerialUSBDriver *sdup) { osalDbgAssert(buf != NULL, "no free buffer"); - usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); - (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out); + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, + buf, SERIAL_USB_BUFFERS_SIZE); } /** @@ -392,12 +381,7 @@ void sduSOFHookI(SerialUSBDriver *sdup) { osalDbgAssert(buf != NULL, "queue is empty"); - osalSysUnlockFromISR(); - - usbPrepareTransmit(sdup->config->usbp, sdup->config->bulk_in, buf, n); - - osalSysLockFromISR(); - (void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in); + usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n); } } @@ -431,13 +415,10 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { /* Checking if there is a buffer ready for transmission.*/ buf = obqGetFullBufferI(&sdup->obqueue, &n); - /* Unlocking the critical zone.*/ - osalSysUnlockFromISR(); - if (buf != NULL) { /* The endpoint cannot be busy, we are in the context of the callback, so it is safe to transmit without a check.*/ - usbPrepareTransmit(usbp, ep, buf, n); + usbStartTransmitI(usbp, ep, buf, n); } else if ((usbp->epc[ep]->in_state->txsize > 0U) && ((usbp->epc[ep]->in_state->txsize & @@ -446,17 +427,13 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { size. Otherwise the recipient may expect more data coming soon and not return buffered data to app. See section 5.8.3 Bulk Transfer Packet Size Constraints of the USB Specification document.*/ - usbPrepareTransmit(usbp, ep, usbp->setup, 0); + usbStartTransmitI(usbp, ep, usbp->setup, 0); } else { /* Nothing to transmit.*/ - return; } - /* Locking again and starting transmission.*/ - osalSysLockFromISR(); - (void) usbStartTransmitI(usbp, ep); osalSysUnlockFromISR(); } @@ -483,7 +460,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { /* Posting the filled buffer in the queue.*/ ibqPostFullBufferI(&sdup->ibqueue, - usbGetReceiveTransactionSizeI(sdup->config->usbp, + usbGetReceiveTransactionSizeX(sdup->config->usbp, sdup->config->bulk_out)); /* The endpoint cannot be busy, we are in the context of the callback, @@ -492,11 +469,8 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { buf = ibqGetEmptyBufferI(&sdup->ibqueue); if (buf != NULL) { /* Buffer found, starting a new transaction.*/ - osalSysUnlockFromISR(); - usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out, - buf, SERIAL_USB_BUFFERS_SIZE); - osalSysLockFromISR(); - (void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out); + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out, + buf, SERIAL_USB_BUFFERS_SIZE); } osalSysUnlockFromISR(); } diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c index b6813c381..4f52424fb 100644 --- a/os/hal/src/usb.c +++ b/os/hal/src/usb.c @@ -401,22 +401,31 @@ void usbDisableEndpointsI(USBDriver *usbp) { } /** - * @brief Prepares for a receive transaction on an OUT endpoint. - * @post The endpoint is ready for @p usbStartReceiveI(). - * @note This function can be called both in ISR and thread context. + * @brief Starts a receive transaction on an OUT endpoint. + * @note This function is meant to be called from ISR context outside + * critical zones because there is a potentially slow operation + * inside. * * @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 transaction size + * @param[in] n transaction size. It is recommended a multiple of + * the packet size because the excess is discarded. * - * @special + * @iclass */ -void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { +void usbStartReceiveI(USBDriver *usbp, usbep_t ep, + uint8_t *buf, size_t n) { USBOutEndpointState *osp; + osalDbgCheckClassI(); osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS)); + osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving"); + /* Marking the endpoint as active.*/ + usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); + + /* Setting up the transfer.*/ osp = usbp->epc[ep]->out_state; osp->rxbuf = buf; osp->rxsize = n; @@ -425,29 +434,35 @@ void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { osp->thread = NULL; #endif - usb_lld_prepare_receive(usbp, ep); + /* Starting transfer.*/ + usb_lld_start_out(usbp, ep); } /** - * @brief Prepares for a transmit transaction on an IN endpoint. - * @post The endpoint is ready for @p usbStartTransmitI(). - * @note This function can be called both in ISR and thread context. - * @note The queue must contain at least the amount of data specified - * as transaction size. + * @brief Starts a transmit transaction on an IN endpoint. + * @note This function is meant to be called from ISR context outside + * critical zones because there is a potentially slow operation + * inside. * * @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 transaction size * - * @special + * @iclass */ -void usbPrepareTransmit(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n) { +void usbStartTransmitI(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { USBInEndpointState *isp; + osalDbgCheckClassI(); osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS)); + osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting"); + /* Marking the endpoint as active.*/ + usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); + + /* Setting up the transfer.*/ isp = usbp->epc[ep]->in_state; isp->txbuf = buf; isp->txsize = n; @@ -456,63 +471,8 @@ void usbPrepareTransmit(USBDriver *usbp, usbep_t ep, isp->thread = NULL; #endif - usb_lld_prepare_transmit(usbp, ep); -} - -/** - * @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) && (ep <= USB_MAX_ENDPOINTS)); - - if (usbGetReceiveStatusI(usbp, ep)) { - return true; - } - - usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep); - usb_lld_start_out(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) && (ep <= USB_MAX_ENDPOINTS)); - - if (usbGetTransmitStatusI(usbp, ep)) { - return true; - } - - usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep); + /* Starting transfer.*/ usb_lld_start_in(usbp, ep); - return false; } #if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__) @@ -527,18 +487,23 @@ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) { * * @return The received effective data size, it can be less than * the amount specified. - * @retval MSG_RESET operation aborted by a reset. - * @retval MSG_TIMEOUT operation aborted by a suspend. + * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation + * has been aborted by an USB reset or a transition to + * the @p USB_SUSPENDED state. * * @api */ msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { msg_t msg; - usbPrepareReceive(usbp, ep, buf, n); - osalSysLock(); - usbStartReceiveI(usbp, ep); + + if (usbGetDriverStateI(usbp) != USB_ACTIVE) { + osalSysUnlock(); + return MSG_RESET; + } + + usbStartReceiveI(usbp, ep, buf, n); msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread); osalSysUnlock(); @@ -555,18 +520,23 @@ msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { * * @return The operation status. * @retval MSG_OK operation performed successfully. - * @retval MSG_RESET operation aborted by a reset. - * @retval MSG_TIMEOUT operation aborted by a suspend. + * @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation + * has been aborted by an USB reset or a transition to + * the @p USB_SUSPENDED state. * * @api */ msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) { msg_t msg; - usbPrepareTransmit(usbp, ep, buf, n); - osalSysLock(); - usbStartTransmitI(usbp, ep); + + if (usbGetDriverStateI(usbp) != USB_ACTIVE) { + osalSysUnlock(); + return MSG_RESET; + } + + usbStartTransmitI(usbp, ep, buf, n); msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread); osalSysUnlock(); @@ -700,10 +670,10 @@ void _usb_suspend(USBDriver *usbp) { if (usbp->epc[i] != NULL) { osalSysLockFromISR(); if (usbp->epc[i]->in_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_TIMEOUT); + osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET); } if (usbp->epc[i]->out_state != NULL) { - osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_TIMEOUT); + osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET); } osalSysUnlockFromISR(); } @@ -787,9 +757,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { if (usbp->ep0n != 0U) { /* Starts the transmit phase.*/ usbp->ep0state = USB_EP0_TX; - usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n); osalSysLockFromISR(); - (void) usbStartTransmitI(usbp, 0); + usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n); osalSysUnlockFromISR(); } else { @@ -797,9 +766,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { packet.*/ usbp->ep0state = USB_EP0_WAITING_STS; #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - usbPrepareReceive(usbp, 0, NULL, 0); osalSysLockFromISR(); - (void) usbStartReceiveI(usbp, 0); + usbStartReceiveI(usbp, 0, NULL, 0); osalSysUnlockFromISR(); #else usb_lld_end_setup(usbp, ep); @@ -811,9 +779,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { if (usbp->ep0n != 0U) { /* Starts the receive phase.*/ usbp->ep0state = USB_EP0_RX; - usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n); osalSysLockFromISR(); - (void) usbStartReceiveI(usbp, 0); + usbStartReceiveI(usbp, 0, usbp->ep0next, usbp->ep0n); osalSysUnlockFromISR(); } else { @@ -821,9 +788,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { packet.*/ usbp->ep0state = USB_EP0_SENDING_STS; #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - usbPrepareTransmit(usbp, 0, NULL, 0); osalSysLockFromISR(); - (void) usbStartTransmitI(usbp, 0); + usbStartTransmitI(usbp, 0, NULL, 0); osalSysUnlockFromISR(); #else usb_lld_end_setup(usbp, ep); @@ -854,9 +820,8 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) { transmitted.*/ if ((usbp->ep0n < max) && ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) { - usbPrepareTransmit(usbp, 0, NULL, 0); osalSysLockFromISR(); - (void) usbStartTransmitI(usbp, 0); + usbStartTransmitI(usbp, 0, NULL, 0); osalSysUnlockFromISR(); usbp->ep0state = USB_EP0_WAITING_TX0; return; @@ -866,9 +831,8 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) { /* Transmit phase over, receiving the zero sized status packet.*/ usbp->ep0state = USB_EP0_WAITING_STS; #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - usbPrepareReceive(usbp, 0, NULL, 0); osalSysLockFromISR(); - (void) usbStartReceiveI(usbp, 0); + usbStartReceiveI(usbp, 0, NULL, 0); osalSysUnlockFromISR(); #else usb_lld_end_setup(usbp, ep); @@ -919,9 +883,8 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) { /* Receive phase over, sending the zero sized status packet.*/ usbp->ep0state = USB_EP0_SENDING_STS; #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - usbPrepareTransmit(usbp, 0, NULL, 0); osalSysLockFromISR(); - (void) usbStartTransmitI(usbp, 0); + usbStartTransmitI(usbp, 0, NULL, 0); osalSysUnlockFromISR(); #else usb_lld_end_setup(usbp, ep); @@ -931,7 +894,7 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) { /* Status packet received, it must be zero sized, invoking the callback if defined.*/ #if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) - if (usbGetReceiveTransactionSizeI(usbp, 0) != 0U) { + if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) { break; } #endif diff --git a/testhal/STM32/STM32F7xx/USB_RAW/Makefile b/testhal/STM32/STM32F7xx/USB_RAW/Makefile index 8d169d51f..3988aeb34 100644 --- a/testhal/STM32/STM32F7xx/USB_RAW/Makefile +++ b/testhal/STM32/STM32F7xx/USB_RAW/Makefile @@ -5,7 +5,7 @@ # Compiler options here. ifeq ($(USE_OPT),) - USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16 + USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16 endif # C specific options here (added to USE_OPT). diff --git a/testhal/STM32/STM32F7xx/USB_RAW/main.c b/testhal/STM32/STM32F7xx/USB_RAW/main.c index c2c4845e2..9d4011f00 100644 --- a/testhal/STM32/STM32F7xx/USB_RAW/main.c +++ b/testhal/STM32/STM32F7xx/USB_RAW/main.c @@ -23,8 +23,7 @@ #include "usbcfg.h" -/* Can be measured using dd if=/dev/xxxx of=/dev/null bs=512 count=10000.*/ -static uint8_t buf[] = +static const uint8_t txbuf[] = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" @@ -42,8 +41,12 @@ static uint8_t buf[] = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; +static uint8_t rxbuf[1024]; + /* - * Red LED blinker thread, times are in milliseconds. + * USB writer. This thread writes data to the USB at maximum rate. + * Can be measured using: + * dd if=/dev/xxxx of=/dev/null bs=512 count=10000 */ static THD_WORKING_AREA(waWriter, 128); static THD_FUNCTION(Writer, arg) { @@ -51,13 +54,28 @@ static THD_FUNCTION(Writer, arg) { (void)arg; chRegSetThreadName("writer"); while (true) { - if (USBD2.state == USB_ACTIVE) { - msg_t msg = usbTransmit(&USBD2, USBD2_DATA_REQUEST_EP, - buf, sizeof (buf) - 1); - if (msg == MSG_OK) - continue; - } - chThdSleepMilliseconds(500); + msg_t msg = usbTransmit(&USBD2, USBD2_DATA_REQUEST_EP, + txbuf, sizeof (txbuf) - 1); + if (msg == MSG_RESET) + chThdSleepMilliseconds(500); + } +} + +/* + * USB reader. This thread reads data from the USB at maximum rate. + * Can be measured using: + * dd if=bigfile of=/dev/xxx bs=512 count=10000 + */ +static THD_WORKING_AREA(waReader, 128); +static THD_FUNCTION(Reader, arg) { + + (void)arg; + chRegSetThreadName("reader"); + while (true) { + msg_t msg = usbReceive(&USBD2, USBD2_DATA_AVAILABLE_EP, + rxbuf, sizeof (rxbuf) - 1); + if (msg == MSG_RESET) + chThdSleepMilliseconds(500); } } @@ -116,6 +134,7 @@ int main(void) { */ chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); chThdCreateStatic(waWriter, sizeof(waWriter), NORMALPRIO, Writer, NULL); + chThdCreateStatic(waReader, sizeof(waReader), NORMALPRIO, Reader, NULL); /* * Normal main() thread activity, in this demo it does nothing except