From de202dd376ea3109e21f535554647689dda23c7b Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Mon, 28 Dec 2015 11:16:40 +0000 Subject: 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/src/serial_usb.c | 48 ++++----------- os/hal/src/usb.c | 159 +++++++++++++++++++----------------------------- 2 files changed, 72 insertions(+), 135 deletions(-) (limited to 'os/hal/src') 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 -- cgit v1.2.3