From b6b473a6a1fde7e7154dc2f1a2abaa395d526f62 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 13 Aug 2012 10:14:45 +0000 Subject: Performance improvements to the STM32 OTG driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4562 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/include/serial_usb.h | 4 +- os/hal/platforms/STM32/OTGv1/usb_lld.c | 67 +++++++++++++++++++++------------- os/hal/platforms/STM32/OTGv1/usb_lld.h | 6 +++ 3 files changed, 49 insertions(+), 28 deletions(-) (limited to 'os/hal') diff --git a/os/hal/include/serial_usb.h b/os/hal/include/serial_usb.h index 4ad65d76d..104375391 100644 --- a/os/hal/include/serial_usb.h +++ b/os/hal/include/serial_usb.h @@ -47,11 +47,11 @@ * @brief Serial over USB buffers size. * @details Configuration parameter, the buffer size must be a multiple of * the USB data endpoint maximum packet size. - * @note The default is 64 bytes for both the transmission and receive + * @note The default is 256 bytes for both the transmission and receive * buffers. */ #if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) -#define SERIAL_USB_BUFFERS_SIZE 64 +#define SERIAL_USB_BUFFERS_SIZE 256 #endif /** @} */ diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.c b/os/hal/platforms/STM32/OTGv1/usb_lld.c index b4238a8a0..78fc45a71 100644 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.c +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.c @@ -85,6 +85,7 @@ static const USBEndpointConfig ep0config = { 0x40, &ep0_state.in, &ep0_state.out, + 1, ep0setup_buffer }; @@ -448,31 +449,43 @@ static void otg_rxfifo_handler(USBDriver *usbp) { * @notapi */ static void otg_txfifo_handler(USBDriver *usbp, usbep_t ep) { - uint32_t n; - - /* Number of bytes remaining in current transaction.*/ - n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt; - if (n > usbp->epc[ep]->in_maxsize) - n = usbp->epc[ep]->in_maxsize; - - if (usbp->epc[ep]->in_state->txqueued) { - /* Queue associated.*/ - otg_fifo_write_from_queue(ep, - usbp->epc[ep]->in_state->mode.queue.txqueue, - n); - } - else { - /* Linear buffer associated.*/ - otg_fifo_write_from_buffer(ep, - usbp->epc[ep]->in_state->mode.linear.txbuf, - n); - usbp->epc[ep]->in_state->mode.linear.txbuf += n; - } - usbp->epc[ep]->in_state->txcnt += n; - /* Interrupt disabled on transaction end.*/ - if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) - OTG->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep); + /* The TXFIFO is filled until there is space and data to be transmitted.*/ + while (TRUE) { + uint32_t n; + + /* Number of bytes remaining in current transaction.*/ + n = usbp->epc[ep]->in_state->txsize - usbp->epc[ep]->in_state->txcnt; + if (n > usbp->epc[ep]->in_maxsize) + n = usbp->epc[ep]->in_maxsize; + + /* Checks if in the TXFIFO there is enough space to accommodate the + next packet.*/ + if (((OTG->ie[ep].DTXFSTS & DTXFSTS_INEPTFSAV_MASK) * 4) < n) + return; + + /* Handles the two cases: linear buffer or queue.*/ + if (usbp->epc[ep]->in_state->txqueued) { + /* Queue associated.*/ + otg_fifo_write_from_queue(ep, + usbp->epc[ep]->in_state->mode.queue.txqueue, + n); + } + else { + /* Linear buffer associated.*/ + otg_fifo_write_from_buffer(ep, + usbp->epc[ep]->in_state->mode.linear.txbuf, + n); + usbp->epc[ep]->in_state->mode.linear.txbuf += n; + } + usbp->epc[ep]->in_state->txcnt += n; + + /* Interrupt disabled on transaction end.*/ + if (usbp->epc[ep]->in_state->txcnt >= usbp->epc[ep]->in_state->txsize) { + OTG->DIEPEMPMSK &= ~DIEPEMPMSK_INEPTXFEM(ep); + return; + } + } } /** @@ -650,8 +663,8 @@ void usb_lld_start(USBDriver *usbp) { - Full Speed 1.1 PHY.*/ OTG->GUSBCFG = GUSBCFG_FDMOD | GUSBCFG_TRDT(TRDT_VALUE) | GUSBCFG_PHYSEL; - /* Interrupt on TXFIFOs empty.*/ - OTG->GAHBCFG = GAHBCFG_PTXFELVL | GAHBCFG_TXFELVL; + /* Interrupts on TXFIFOs half empty.*/ + OTG->GAHBCFG = 0; /* 48MHz 1.1 PHY.*/ OTG->DCFG = 0x02200000 | DCFG_PFIVL(0) | DCFG_DSPD_FS11; @@ -806,6 +819,8 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) { if (usbp->epc[ep]->in_cb != NULL) { /* FIFO allocation for the IN endpoint.*/ fsize = usbp->epc[ep]->in_maxsize / 4; + if (usbp->epc[ep]->in_multiplier > 1) + fsize *= usbp->epc[ep]->in_multiplier; OTG->DIEPTXF[ep - 1] = DIEPTXF_INEPTXFD(fsize) | DIEPTXF_INEPTXSA(otg_ram_alloc(usbp, fsize)); otg_txfifo_flush(ep); diff --git a/os/hal/platforms/STM32/OTGv1/usb_lld.h b/os/hal/platforms/STM32/OTGv1/usb_lld.h index 8b2903982..30e96c71b 100644 --- a/os/hal/platforms/STM32/OTGv1/usb_lld.h +++ b/os/hal/platforms/STM32/OTGv1/usb_lld.h @@ -231,6 +231,12 @@ typedef struct { */ USBOutEndpointState *out_state; /* End of the mandatory fields.*/ + /** + * @brief Determines the space allocated for the TXFIFO as multiples of + * the packet size (@p in_maxsize). Note that zero is interpreted + * as one for simplicity and robustness. + */ + uint16_t in_multiplier; /** * @brief Pointer to a buffer for setup packets. * @details Setup packets require a dedicated 8-bytes buffer, set this -- cgit v1.2.3