Explorar el Código

optimise musb driver

sakumisu hace 3 años
padre
commit
22f7322ed9
Se han modificado 2 ficheros con 130 adiciones y 58 borrados
  1. 2 8
      port/musb/usb_dc_musb.c
  2. 128 50
      port/musb/usb_hc_musb.c

+ 2 - 8
port/musb/usb_dc_musb.c

@@ -441,16 +441,14 @@ int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint
     uint8_t old_ep_idx;
 
     old_ep_idx = USBC_GetActiveEp();
-
+    USBC_SelectActiveEp(ep_idx);
     if (!data && data_len) {
         ret = -1;
         goto _RET;
     }
 
     if (ep_idx == 0x00) {
-        USBC_SelectActiveEp(ep_idx);
         while (HWREGB(USB_TXCSRLx_BASE) & USB_CSRL0_TXRDY) {
-            USBC_SelectActiveEp(ep_idx);
             if (HWREGB(USB_TXCSRLx_BASE) & USB_CSRL0_ERROR) {
                 ret = -2;
                 goto _RET;
@@ -461,9 +459,7 @@ int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint
             }
         }
     } else {
-        USBC_SelectActiveEp(ep_idx);
         while (HWREGB(USB_TXCSRLx_BASE) & USB_TXCSRL1_TXRDY) {
-            USBC_SelectActiveEp(ep_idx);
             if ((HWREGB(USB_TXCSRLx_BASE) & USB_TXCSRL1_ERROR) || (HWREGB(USB_TXCSRLx_BASE) & USB_TXCSRL1_UNDRN)) {
                 ret = -2;
                 goto _RET;
@@ -489,7 +485,6 @@ int usbd_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint
     usb_musb_write_packet(ep_idx, (uint8_t *)data, data_len);
 
     if (ep_idx != 0) {
-        USBC_SelectActiveEp(ep_idx);
         HWREGB(USB_TXCSRLx_BASE) = USB_TXCSRL1_TXRDY;
     }
     if (ret_bytes) {
@@ -509,13 +504,12 @@ int usbd_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_
     uint8_t old_ep_idx;
 
     old_ep_idx = USBC_GetActiveEp();
-
+    USBC_SelectActiveEp(ep_idx);
     if (!data && max_data_len) {
         ret = -1;
         goto _RET;
     }
 
-    USBC_SelectActiveEp(ep_idx);
     if (!max_data_len) {
         if (ep_idx != 0x00) {
             HWREGB(USB_RXCSRLx_BASE) &= ~(USB_RXCSRL1_RXRDY);

+ 128 - 50
port/musb/usb_hc_musb.c

@@ -107,7 +107,6 @@ struct usb_musb_chan {
     uint8_t interval; /* Polling interval */
     uint8_t *buffer;
     volatile uint32_t buflen;
-    volatile uint32_t once_outlen;
     volatile uint16_t xfrd;   /* Bytes transferred (at end of transfer) */
     volatile int result;      /* The result of the transfer */
     volatile bool waiter;     /* True: Thread is waiting for a channel event */
@@ -126,6 +125,7 @@ struct usb_musb_priv {
 } g_usbhost;
 
 volatile uint8_t usb_ep0_state = USB_EP0_STATE_SETUP;
+volatile uint8_t ep0_outlen = 0;
 
 /* get current active ep */
 static uint8_t USBC_GetActiveEp(void)
@@ -257,7 +257,7 @@ static int usb_musb_chan_alloc(void)
 
     /* Search the table of channels */
 
-    for (chidx = 2; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
+    for (chidx = 1; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) {
         /* Is this channel available? */
         if (!g_usbhost.chan[chidx].inuse) {
             /* Yes... make it "in use" and return the index */
@@ -399,7 +399,7 @@ static int usb_musb_chan_wait(struct usb_musb_chan *chan, uint32_t timeout)
         }
     }
 
-    /* The transfer is complete re-enable interrupts and return the result */
+    /* The transfer is complete and return the result */
     ret = chan->result;
 
     if (ret < 0) {
@@ -491,6 +491,7 @@ int usb_hc_init(void)
     USB->TXIE = USB_TXIE_EP0;
     USB->RXIE = 0;
 
+    USB->POWER |= USB_POWER_HSENAB;
     USB->DEVCTL |= USB_DEVCTL_SESSION;
 
 #ifdef USB_MUSB_SUNXI
@@ -539,8 +540,8 @@ int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uin
         return ret;
     }
 
-    USBC_SelectActiveEp(ep0);
-    HWREGB(USB_TXADDR_BASE(ep0)) = dev_addr;
+    USBC_SelectActiveEp(0);
+    HWREGB(USB_TXADDR_BASE(0)) = dev_addr;
 
     if (speed == USB_SPEED_HIGH) {
         USB->TYPE0 = USB_TYPE0_SPEED_HIGH;
@@ -550,7 +551,6 @@ int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uin
         USB->TYPE0 = USB_TYPE0_SPEED_LOW;
     }
 
-    chan = &g_usbhost.chan[ep0];
     chan->mps = ep_mps;
 
     usb_osal_mutex_give(chan->exclsem);
@@ -702,7 +702,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint
     usb_musb_chan_waitsetup(chan);
 
     usb_musb_write_packet(0, (uint8_t *)setup, 8);
-    chan->once_outlen = 8;
+    ep0_outlen = 8;
     if (setup->wLength && buffer) {
         if (setup->bmRequestType & 0x80) {
             usb_ep0_state = USB_EP0_STATE_IN_DATA;
@@ -756,12 +756,9 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
             buflen = chan->mps;
         }
 
-        usb_musb_write_packet(chidx, (uint8_t *)buffer, buflen);
+        usb_musb_write_packet(chidx, chan->buffer, buflen);
         USBC_SelectActiveEp(chidx);
         HWREGB(USB_TXCSRLx_BASE) = USB_TXCSRL1_TXRDY;
-        chan->buffer += buflen;
-        chan->buflen -= buflen;
-        chan->xfrd += buflen;
     }
     ret = usb_musb_chan_wait(chan, timeout);
     if (ret < 0) {
@@ -771,6 +768,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
     usb_osal_mutex_give(chan->exclsem);
     return ret;
 errout_with_mutex:
+    chan->waiter = false;
     usb_osal_mutex_give(chan->exclsem);
     return ret;
 }
@@ -801,12 +799,9 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
             buflen = chan->mps;
         }
 
-        usb_musb_write_packet(chidx, (uint8_t *)buffer, buflen);
+        usb_musb_write_packet(chidx, chan->buffer, buflen);
         USBC_SelectActiveEp(chidx);
         HWREGB(USB_TXCSRLx_BASE) = USB_TXCSRL1_TXRDY;
-        chan->buffer += buflen;
-        chan->buflen -= buflen;
-        chan->xfrd += buflen;
     }
     ret = usb_musb_chan_wait(chan, timeout);
     if (ret < 0) {
@@ -816,6 +811,7 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, ui
     usb_osal_mutex_give(chan->exclsem);
     return ret;
 errout_with_mutex:
+    chan->waiter = false;
     usb_osal_mutex_give(chan->exclsem);
     return ret;
 }
@@ -832,6 +828,25 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
         return ret;
     }
 
+    usb_musb_chan_asynchsetup(chan, callback, arg);
+
+    if (chan->in) {
+        chan->buffer = buffer;
+        chan->buflen = buflen;
+        USBC_SelectActiveEp(chidx);
+        HWREGB(USB_RXCSRLx_BASE) = USB_RXCSRL1_REQPKT;
+    } else {
+        chan->buffer = buffer;
+        chan->buflen = buflen;
+        if (buflen > chan->mps) {
+            buflen = chan->mps;
+        }
+
+        usb_musb_write_packet(chidx, chan->buffer, buflen);
+        USBC_SelectActiveEp(chidx);
+        HWREGB(USB_TXCSRLx_BASE) = USB_TXCSRL1_TXRDY;
+    }
+
     usb_osal_mutex_give(chan->exclsem);
     return ret;
 }
@@ -848,31 +863,88 @@ int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl
         return ret;
     }
 
+    usb_musb_chan_asynchsetup(chan, callback, arg);
+
+    if (chan->in) {
+        chan->buffer = buffer;
+        chan->buflen = buflen;
+        USBC_SelectActiveEp(chidx);
+        HWREGB(USB_RXCSRLx_BASE) = USB_RXCSRL1_REQPKT;
+    } else {
+        chan->buffer = buffer;
+        chan->buflen = buflen;
+        if (buflen > chan->mps) {
+            buflen = chan->mps;
+        }
+
+        usb_musb_write_packet(chidx, chan->buffer, buflen);
+        USBC_SelectActiveEp(chidx);
+        HWREGB(USB_TXCSRLx_BASE) = USB_TXCSRL1_TXRDY;
+    }
+
     usb_osal_mutex_give(chan->exclsem);
     return ret;
 }
 
 int usb_ep_cancel(usbh_epinfo_t ep)
 {
+    int ret;
+    uint32_t flags;
+    struct usb_musb_chan *chan;
+    uint8_t chidx = (uint8_t)ep;
+#ifdef CONFIG_USBHOST_ASYNCH
+    usbh_asynch_callback_t callback;
+    void *arg;
+#endif
+    chan = &g_usbhost.chan[chidx];
+
+    flags = usb_osal_enter_critical_section();
+
+    chan->result = -ESHUTDOWN;
+#ifdef CONFIG_USBHOST_ASYNCH
+    /* Extract the callback information */
+    callback = chan->callback;
+    arg = chan->arg;
+    chan->callback = NULL;
+    chan->arg = NULL;
+    chan->xfrd = 0;
+#endif
+    usb_osal_leave_critical_section(flags);
+    /* Is there a thread waiting for this transfer to complete? */
+
+    if (chan->waiter) {
+        /* Wake'em up! */
+        chan->waiter = false;
+        usb_osal_sem_give(chan->waitsem);
+    }
+#ifdef CONFIG_USBHOST_ASYNCH
+    /* No.. is an asynchronous callback expected when the transfer completes? */
+    else if (callback) {
+        /* Then perform the callback */
+        callback(arg, -ESHUTDOWN);
+    }
+#endif
     return 0;
 }
 
 void handle_ep0(void)
 {
     uint8_t ep0_status = USB->CSRL0;
+    struct usb_musb_chan *chan;
 
+    chan = &g_usbhost.chan[0];
     if (ep0_status & USB_HOST_EP0_ERROR) {
         usb_musb_ep_status_clear(0, USB_HOST_EP0_ERROR);
         usb_musb_fifo_flush(0);
         usb_ep0_state = USB_EP0_STATE_SETUP;
-        g_usbhost.chan[0].result = -EIO;
+        chan->result = -EIO;
         goto chan_wait;
     }
 
     if (ep0_status & USB_HOST_EP0_RX_STALL) {
         usb_musb_ep_status_clear(0, ep0_status & USB_HOST_IN_STATUS);
         usb_ep0_state = USB_EP0_STATE_SETUP;
-        g_usbhost.chan[0].result = -EPERM;
+        chan->result = -EPERM;
         goto chan_wait;
     }
     switch (usb_ep0_state) {
@@ -881,61 +953,65 @@ void handle_ep0(void)
         case USB_EP0_STATE_IN_DATA:
             USB->CSRL0 = USB_RXCSRL1_REQPKT;
             usb_ep0_state = USB_EP0_STATE_IN_DATA_C;
-            g_usbhost.chan[0].xfrd += g_usbhost.chan[0].once_outlen;
+            chan->xfrd += 8;
             break;
         case USB_EP0_STATE_IN_DATA_C:
             if (USB->CSRL0 & USB_CSRL0_RXRDY) {
-                uint32_t size = g_usbhost.chan[0].buflen;
-                if (size > g_usbhost.chan[0].mps) {
-                    size = g_usbhost.chan[0].mps;
+                uint32_t size = chan->buflen;
+                if (size > chan->mps) {
+                    size = chan->mps;
                 }
 
                 size = MIN(size, USB->COUNT0);
 
-                usb_musb_read_packet(0, g_usbhost.chan[0].buffer, size);
+                usb_musb_read_packet(0, chan->buffer, size);
                 USB->CSRL0 &= ~USB_CSRL0_RXRDY;
 
-                g_usbhost.chan[0].buffer += size;
-                g_usbhost.chan[0].buflen -= size;
-                g_usbhost.chan[0].xfrd += size;
-                if ((size < g_usbhost.chan[0].mps) || (g_usbhost.chan[0].buflen == 0)) {
-                    usb_ep0_state = USB_EP0_STATE_IN_STATUS_C;
+                chan->buffer += size;
+                chan->buflen -= size;
+                chan->xfrd += size;
+                if ((size < chan->mps) || (chan->buflen == 0)) {
+                    usb_ep0_state = USB_EP0_STATE_OUT_STATUS;
                     USB->CSRL0 = USB_CSRL0_TXRDY | USB_CSRL0_STATUS;
                 } else {
                     USB->CSRL0 = USB_RXCSRL1_REQPKT;
                 }
             }
             break;
+        case USB_EP0_STATE_OUT_STATUS:
+            usb_ep0_state = USB_EP0_STATE_SETUP;
+            chan->result = 0;
+            goto chan_wait;
         case USB_EP0_STATE_IN_STATUS_C:
             if (ep0_status & (USB_HOST_EP0_RXPKTRDY | USB_HOST_EP0_STATUS)) {
                 usb_musb_ep_status_clear(0, (USB_HOST_EP0_RXPKTRDY | USB_HOST_EP0_STATUS));
             }
 
             usb_ep0_state = USB_EP0_STATE_SETUP;
-            g_usbhost.chan[0].result = 0;
+            chan->result = 0;
             goto chan_wait;
 
             break;
         case USB_EP0_STATE_IN_STATUS:
             USB->CSRL0 = USB_CSRL0_REQPKT | USB_CSRL0_STATUS;
             usb_ep0_state = USB_EP0_STATE_IN_STATUS_C;
-            g_usbhost.chan[0].xfrd += g_usbhost.chan[0].once_outlen;
+            chan->xfrd += 8;
             break;
 
         case USB_EP0_STATE_OUT_DATA: {
-            g_usbhost.chan[0].xfrd += g_usbhost.chan[0].once_outlen;
-
-            uint32_t size = g_usbhost.chan[0].buflen;
-            if (size > g_usbhost.chan[0].mps) {
-                size = g_usbhost.chan[0].mps;
+            uint32_t size = chan->buflen;
+            if (size > chan->mps) {
+                size = chan->mps;
             }
 
-            usb_musb_write_packet(0, g_usbhost.chan[0].buffer, size);
+            chan->xfrd += ep0_outlen;
 
-            g_usbhost.chan[0].buffer += size;
-            g_usbhost.chan[0].buflen -= size;
-            g_usbhost.chan[0].once_outlen = size;
-            if (size == g_usbhost.chan[0].mps) {
+            usb_musb_write_packet(0, chan->buffer, size);
+
+            chan->buffer += size;
+            chan->buflen -= size;
+            ep0_outlen = size;
+            if (size == chan->mps) {
                 USB->CSRL0 = USB_CSRL0_TXRDY;
             } else {
                 USB->CSRL0 = USB_CSRL0_TXRDY;
@@ -947,7 +1023,7 @@ void handle_ep0(void)
     }
     return;
 chan_wait:
-    usb_musb_chan_wakeup(&g_usbhost.chan[0]);
+    usb_musb_chan_wakeup(chan);
 }
 void USBH_IRQHandler(void)
 {
@@ -1025,18 +1101,20 @@ void USBH_IRQHandler(void)
         } else {
             uint32_t size = chan->buflen;
 
-            if (size) {
-                if (size > chan->mps) {
-                    size = chan->mps;
-                }
-                usb_musb_write_packet(chidx, chan->buffer, size);
-                HWREGB(USB_TXCSRLx_BASE) = USB_TXCSRL1_TXRDY;
-                chan->buffer += size;
-                chan->buflen -= size;
-                chan->xfrd += size;
-            } else {
+            if (size > chan->mps) {
+                size = chan->mps;
+            }
+
+            chan->buffer += size;
+            chan->buflen -= size;
+            chan->xfrd += size;
+
+            if (chan->buflen == 0) {
                 chan->result = 0;
                 usb_musb_chan_wakeup(chan);
+            } else {
+                usb_musb_write_packet(chidx, chan->buffer, size);
+                HWREGB(USB_TXCSRLx_BASE) = USB_TXCSRL1_TXRDY;
             }
         }
     }