ソースを参照

Update wch driver

Chen Leeren 2 年 前
コミット
a51edd9231
2 ファイル変更142 行追加54 行削除
  1. 40 24
      port/ch32/usb_hc_usbfs.c
  2. 102 30
      port/ch32/usb_hc_usbhs.c

+ 40 - 24
port/ch32/usb_hc_usbfs.c

@@ -87,7 +87,7 @@ struct chusb_hcd {
     volatile bool prv_get_zero;
     volatile bool prv_set_zero;
     volatile bool main_pipe_using;
-    uint32_t current_pipe_timeout;
+    // uint32_t current_pipe_timeout;
     struct chusb_pipe *current_pipe;
     struct chusb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM][2]; /* Support Bidirectional ep */
 } g_chusb_hcd;
@@ -215,7 +215,7 @@ static int8_t chusb_host_pipe_transfer(struct chusb_pipe *pipe, uint8_t pid, uin
     /*!< Updata curretn pipe */
     g_chusb_hcd.current_pipe = pipe;
     /*!< Updata curretn pipe timeout */
-    g_chusb_hcd.current_pipe_timeout = pipe->urb->timeout;
+    // g_chusb_hcd.current_pipe_timeout = pipe->urb->timeout;
     /*!< Updata main pipe using flag */
     g_chusb_hcd.main_pipe_using = true;
 
@@ -650,15 +650,6 @@ int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
     ppipe->hport = ep_cfg->hport;
 
     if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) {
-        if (ppipe->speed == USB_SPEED_HIGH) {
-            USB_LOG_INFO("ep0 reconfigure USB_SPEED_HIGH \r\n");
-        } else if (ppipe->speed == USB_SPEED_FULL) {
-            USB_LOG_INFO("ep0 reconfigure USB_SPEED_FULL \r\n");
-            chusbh_set_self_speed(USB_SPEED_FULL);
-        } else if (ppipe->speed == USB_SPEED_LOW) {
-            USB_LOG_INFO("ep0 reconfigure USB_SPEED_LOW \r\n");
-            chusbh_set_self_speed(USB_SPEED_LOW);
-        }
     } else {
         if (ppipe->speed == USB_SPEED_HIGH) {
         } else if (ppipe->speed == USB_SPEED_FULL) {
@@ -748,13 +739,14 @@ int usbh_submit_urb(struct usbh_urb *urb)
             goto errout_timeout;
         }
 
-        g_chusb_hcd.current_pipe_timeout = 0;
+        // g_chusb_hcd.current_pipe_timeout = 0;
 
         ret = urb->errorcode;
     }
     return ret;
 errout_timeout:
     pipe->waiter = false;
+    g_chusb_hcd.current_token = 0;
     usbh_kill_urb(urb);
     return ret;
 }
@@ -831,7 +823,7 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
                     USBFS_HOST->INT_FG = USBFS_UIF_TRANSFER;
                     return -3;
                 } else {
-                    if (g_chusb_hcd.current_pipe_timeout > 0) {
+                    if (g_chusb_hcd.current_pipe->waiter == true) {
                         USB_LOG_DBG("Control endpoint out nak and retry\r\n");
                         chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_OUT,
                                                  g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
@@ -849,7 +841,7 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
                     urb->actual_length = g_chusb_hcd.current_pipe->xfrd;
                     chusb_pipe_waitup(g_chusb_hcd.current_pipe, true);
                 } else {
-                    if (g_chusb_hcd.current_pipe_timeout > 0) {
+                    if (g_chusb_hcd.current_pipe->waiter == true) {
                         USB_LOG_DBG("Normal endpoint out nak and retry\r\n");
                         urb->errorcode = -EAGAIN;
                         chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_OUT,
@@ -978,7 +970,16 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
         case 0:
             if (g_chusb_hcd.current_pipe->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
                 if (g_chusb_hcd.current_token == USB_PID_SETUP) {
-                    USB_LOG_ERR("SETUP TIMEOUT \r\n");
+                    if ((g_chusb_hcd.ep0_state == USB_EP0_STATE_SETUP) && (g_chusb_hcd.current_pipe->waiter == true)) {
+                        USB_LOG_WRN("Setup Timeout and retry\r\n");
+                        chusb_control_pipe_init(g_chusb_hcd.current_pipe, urb->setup,
+                                                urb->transfer_buffer, urb->transfer_buffer_length);
+                    } else {
+                        USB_LOG_ERR("Setup Timeout\r\n");
+                        urb->errorcode = -EIO;
+                        USBFS_HOST->INT_FG = USBFS_UIF_TRANSFER;
+                        return -5;
+                    }
                 } else {
                     USB_LOG_ERR("OUT TIMEOUT \r\n");
                     if (g_chusb_hcd.current_pipe->ep_type != USB_ENDPOINT_TYPE_CONTROL) {
@@ -989,8 +990,6 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
                     }
                 }
                 urb->errorcode = -EIO;
-                USBFS_HOST->INT_FG = USBFS_UIF_TRANSFER;
-                return -5;
             } else {
                 /**
                  * No response from isochronous endpoint out
@@ -1031,7 +1030,7 @@ static int8_t chusb_inpipe_irq_handler(uint8_t res_state)
         case USB_PID_NAK:
             g_chusb_hcd.current_token = 0;
             if (g_chusb_hcd.current_pipe->ep_type == USB_ENDPOINT_TYPE_CONTROL) {
-                if (g_chusb_hcd.current_pipe_timeout > 0) {
+                if (g_chusb_hcd.current_pipe->waiter == true) {
                     urb->errorcode = -EAGAIN;
                     chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_IN,
                                              g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
@@ -1056,7 +1055,7 @@ static int8_t chusb_inpipe_irq_handler(uint8_t res_state)
                             /**
                              * Data was transmitted last time, but this time NAK
                              */
-                            if (g_chusb_hcd.current_pipe_timeout > 0) {
+                            if (g_chusb_hcd.current_pipe->waiter == true) {
                                 /**
                                  * Retry in
                                  */
@@ -1077,12 +1076,26 @@ static int8_t chusb_inpipe_irq_handler(uint8_t res_state)
                             }
                         } else {
                             /**
-                             * The device did not send any data. We do not need to call a callback
+                             * The device did not send any data. 
                              */
-                            urb->errorcode = -EBUSY;
-                            g_chusb_hcd.current_token = 0;
-                            urb->actual_length = 0;
-                            chusb_pipe_waitup(g_chusb_hcd.current_pipe, false);
+                            if (g_chusb_hcd.current_pipe->waiter == true) {
+                                /**
+                                 *  Try again
+                                 */                                
+                                USB_LOG_DBG("The device does not transmit data, try again\r\n");
+                                chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_IN,
+                                                         g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
+                            } else {
+                                /**
+                                 * g_chusb_hcd.current_pipe->waiter = false
+                                 * We do not need to call a callback
+                                 */
+                                USB_LOG_DBG("Do not need try again\r\n");
+                                urb->errorcode = -EBUSY;
+                                g_chusb_hcd.current_token = 0;
+                                urb->actual_length = 0;
+                                chusb_pipe_waitup(g_chusb_hcd.current_pipe, false);
+                            }
                         }
                     } else {
                         urb->errorcode = -EIO;
@@ -1247,6 +1260,9 @@ void USBH_IRQHandler(void)
                     goto pipe_wait;
                 }
                 break;
+            default:
+                USBFS_HOST->INT_FG = USBFS_UIF_TRANSFER;
+                break;
         }
     } else if (intflag & USBFS_UIF_DETECT) {
         if (USBFS_HOST->MIS_ST & USBFS_UMS_DEV_ATTACH) {

+ 102 - 30
port/ch32/usb_hc_usbhs.c

@@ -58,7 +58,8 @@ struct chusb_hcd {
     volatile bool prv_get_zero;
     volatile bool prv_set_zero;
     volatile bool main_pipe_using;
-    uint32_t current_pipe_timeout;
+    // uint32_t current_pipe_timeout;
+    uint8_t dev_speed;
     struct chusb_pipe *current_pipe;
     struct chusb_pipe pipe_pool[CONFIG_USBHOST_PIPE_NUM][2]; /* Support Bidirectional ep */
 } g_chusb_hcd;
@@ -186,9 +187,9 @@ static int8_t chusb_host_pipe_transfer(struct chusb_pipe *pipe, uint8_t pid, uin
     /*!< Updata curretn pipe */
     g_chusb_hcd.current_pipe = pipe;
     /*!< Updata curretn pipe timeout */
-    g_chusb_hcd.current_pipe_timeout = pipe->urb->timeout;
+    // g_chusb_hcd.current_pipe_timeout = pipe->urb->timeout;
     /*!< Updata main pipe using flag */
-    g_chusb_hcd.main_pipe_using = true;
+    // g_chusb_hcd.main_pipe_using = true;
 
     if (data == NULL && len > 0) {
         return -1;
@@ -203,7 +204,7 @@ static int8_t chusb_host_pipe_transfer(struct chusb_pipe *pipe, uint8_t pid, uin
             return -3;
         }
 
-        USBHS_HOST->HOST_TX_DMA = (uint16_t)(uint32_t)data;
+        USBHS_HOST->HOST_TX_DMA = (uint32_t)data;
 
         /*!< Record the data buffer address */
         pipe->buffer = data;
@@ -230,7 +231,7 @@ static int8_t chusb_host_pipe_transfer(struct chusb_pipe *pipe, uint8_t pid, uin
             return -3;
         }
 
-        USBHS_HOST->HOST_TX_DMA = (uint16_t)(uint32_t)data;
+        USBHS_HOST->HOST_TX_DMA = (uint32_t)data;
 
         /*!< Record the data buffer address */
         pipe->buffer = data;
@@ -253,7 +254,7 @@ static int8_t chusb_host_pipe_transfer(struct chusb_pipe *pipe, uint8_t pid, uin
                 USB_LOG_INFO("IN DMA address is not align \r\n");
                 return -3;
             }
-            USBHS_HOST->HOST_RX_DMA = (uint16_t)(uint32_t)data;
+            USBHS_HOST->HOST_RX_DMA = (uint32_t)data;
             pipe->buffer = data;
         }
 
@@ -479,6 +480,15 @@ static void chusbh_set_self_speed(uint8_t speed)
 
 static int usbh_reset_port(const uint8_t port)
 {
+    USB_LOG_INFO("Reset port \r\n");
+    /*!< Disable detect interrupt */
+    USBHS_HOST->INT_EN &= (~USBHS_DETECT_EN);
+
+    USBHS_HOST->HOST_CTRL &= ~USBHS_SEND_SOF_EN;
+
+    /*!< Clear flags that may not have been cleared */
+    // g_chusb_hcd.main_pipe_using = false;
+
     g_chusb_hcd.port_pe = 0;
     /*!< Set dev add 0 */
     USBHS_HOST->DEV_AD = (0x00 & 0x7F);
@@ -490,31 +500,70 @@ static int usbh_reset_port(const uint8_t port)
     /*!< Stop reset */
     USBHS_HOST->HOST_CTRL &= ~USBHS_SEND_BUS_RESET;
     usb_osal_msleep(20);
-    // USBHS_HOST->HOST_CTRL |= USBHS_SEND_SOF_EN;
     g_chusb_hcd.port_pe = 1;
+
+    if ((USBHS_HOST->HOST_CTRL & USBHS_SEND_SOF_EN) == 0) {
+        volatile uint8_t speed = USBHS_HOST->SPEED_TYPE & USBSPEED_MASK;
+        if (speed == 0x02) {
+            USB_LOG_INFO("Dev USB_SPEED_LOW \r\n");
+            g_chusb_hcd.dev_speed = USB_SPEED_LOW;
+        } else if (speed == 0x00) {
+            USB_LOG_INFO("Dev USB_SPEED_FULL \r\n");
+            g_chusb_hcd.dev_speed = USB_SPEED_FULL;
+        } else if (speed == 0x01) {
+            USB_LOG_INFO("Dev USB_SPEED_HIGH \r\n");
+            g_chusb_hcd.dev_speed = USB_SPEED_HIGH;
+        }
+    }
+
+    if (g_chusb_hcd.dev_speed == USB_SPEED_HIGH) {
+        USBHS_HOST->HOST_CTRL |= USBHS_SEND_SOF_EN;
+        uint32_t timeout = 100000;
+        while (timeout--) {
+            if (USBHS_HOST->INT_FG & USBHS_DETECT_FLAG) {
+                if (USBHS_HOST->MIS_ST & USBHS_ATTACH) {
+                    USBHS_HOST->INT_FG = USBHS_DETECT_FLAG;
+                    break;
+                } else {
+                    USBHS_HOST->INT_FG = USBHS_DETECT_FLAG;
+                }
+            }
+        }
+    }
+
+    // USBHS_HOST->HOST_CTRL |= USBHS_SEND_SOF_EN;
+    USBHS_HOST->INT_EN |= USBHS_DETECT_EN;
     return 0;
 }
 
 static uint8_t usbh_get_port_speed(const uint8_t port)
 {
     (void)port;
+#if 0
+    /*!< Stop reset */
+    USBHS_HOST->HOST_CTRL &= ~USBHS_SEND_BUS_RESET;
     uint8_t speed = 0;
     if (USBHS_HOST->MIS_ST & 0x02) {
         if ((USBHS_HOST->HOST_CTRL & USBHS_SEND_SOF_EN) == 0) {
             speed = USBHS_HOST->SPEED_TYPE & USBSPEED_MASK;
 
             if (speed == 0x02) {
+                USB_LOG_INFO("Dev USB_SPEED_LOW \r\n");
                 speed = USB_SPEED_LOW;
             } else if (speed == 0x00) {
+                USB_LOG_INFO("Dev USB_SPEED_FULL \r\n");
                 speed = USB_SPEED_FULL;
             } else if (speed == 0x01) {
+                USB_LOG_INFO("Dev USB_SPEED_HIGH \r\n");
                 speed = USB_SPEED_HIGH;
             }
         }
     }
 
     USBHS_HOST->HOST_CTRL |= USBHS_SEND_SOF_EN;
-    return speed;
+#endif
+    USBHS_HOST->HOST_CTRL |= USBHS_SEND_SOF_EN;
+    return g_chusb_hcd.dev_speed;
 }
 
 __WEAK void usb_hc_low_level_init(void)
@@ -712,16 +761,6 @@ int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
     ppipe->hport = ep_cfg->hport;
 
     if (ep_cfg->ep_type == USB_ENDPOINT_TYPE_CONTROL) {
-        if (ppipe->speed == USB_SPEED_HIGH) {
-            USB_LOG_INFO("ep0 reconfigure USB_SPEED_HIGH \r\n");
-            chusbh_set_self_speed(USB_SPEED_HIGH);
-        } else if (ppipe->speed == USB_SPEED_FULL) {
-            USB_LOG_INFO("ep0 reconfigure USB_SPEED_FULL \r\n");
-            chusbh_set_self_speed(USB_SPEED_FULL);
-        } else if (ppipe->speed == USB_SPEED_LOW) {
-            USB_LOG_INFO("ep0 reconfigure USB_SPEED_LOW \r\n");
-            chusbh_set_self_speed(USB_SPEED_LOW);
-        }
     } else {
         if (ppipe->speed == USB_SPEED_HIGH) {
             if ((ep_cfg->ep_type == USB_ENDPOINT_TYPE_ISOCHRONOUS) ||
@@ -784,10 +823,12 @@ int usbh_submit_urb(struct usbh_urb *urb)
         return -EBUSY;
     }
 
+#if 0
     if (g_chusb_hcd.main_pipe_using == true) {
         USB_LOG_INFO("usbh_submit_urb//main pipe is using\r\n");
         return -EBUSY;
     }
+#endif
 
     flags = usb_osal_enter_critical_section();
 
@@ -826,13 +867,13 @@ int usbh_submit_urb(struct usbh_urb *urb)
             goto errout_timeout;
         }
 
-        g_chusb_hcd.current_pipe_timeout = 0;
-
         ret = urb->errorcode;
     }
     return ret;
 errout_timeout:
     pipe->waiter = false;
+    g_chusb_hcd.current_token = 0;
+    // g_chusb_hcd.main_pipe_using = false;
     usbh_kill_urb(urb);
     return ret;
 }
@@ -848,7 +889,7 @@ static inline void chusb_pipe_waitup(struct chusb_pipe *pipe, bool callback)
 
     urb = pipe->urb;
     pipe->urb = NULL;
-    g_chusb_hcd.main_pipe_using = false;
+    // g_chusb_hcd.main_pipe_using = false;
 
     if (pipe->waiter) {
         pipe->waiter = false;
@@ -903,7 +944,7 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
                     USBHS_HOST->INT_FG = USBHS_TRANSFER_FLAG;
                     return -3;
                 } else {
-                    if (g_chusb_hcd.current_pipe_timeout > 0) {
+                    if (g_chusb_hcd.current_pipe->waiter == true) {
                         USB_LOG_DBG("Control endpoint out nak and retry\r\n");
                         chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_OUT,
                                                  g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
@@ -921,7 +962,7 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
                     urb->actual_length = g_chusb_hcd.current_pipe->xfrd;
                     chusb_pipe_waitup(g_chusb_hcd.current_pipe, true);
                 } else {
-                    if (g_chusb_hcd.current_pipe_timeout > 0) {
+                    if (g_chusb_hcd.current_pipe->waiter == true) {
                         USB_LOG_DBG("Normal endpoint out nak and retry\r\n");
                         chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_OUT,
                                                  g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
@@ -1046,7 +1087,16 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
         case 0:
             if (g_chusb_hcd.current_pipe->ep_type != USB_ENDPOINT_TYPE_ISOCHRONOUS) {
                 if (g_chusb_hcd.current_token == USB_PID_SETUP) {
-                    USB_LOG_ERR("SETUP TIMEOUT \r\n");
+                    if ((g_chusb_hcd.ep0_state == USB_EP0_STATE_SETUP) && (g_chusb_hcd.current_pipe->waiter == true)) {
+                        USB_LOG_WRN("Setup Timeout and retry\r\n");
+                        chusb_control_pipe_init(g_chusb_hcd.current_pipe, urb->setup,
+                                                urb->transfer_buffer, urb->transfer_buffer_length);
+                    } else {
+                        USB_LOG_ERR("Setup Timeout\r\n");
+                        urb->errorcode = -EIO;
+                        USBHS_HOST->INT_FG = USBHS_TRANSFER_FLAG;
+                        return -5;
+                    }
                 } else {
                     USB_LOG_ERR("OUT TIMEOUT \r\n");
                     if (g_chusb_hcd.current_pipe->ep_type != USB_ENDPOINT_TYPE_CONTROL) {
@@ -1057,8 +1107,6 @@ static int8_t chusb_outpipe_irq_handler(uint8_t res_state)
                     }
                 }
                 urb->errorcode = -EIO;
-                USBHS_HOST->INT_FG = USBHS_TRANSFER_FLAG;
-                return -5;
             } else {
                 /**
                  * No response from isochronous endpoint out
@@ -1100,7 +1148,7 @@ static int8_t chusb_inpipe_irq_handler(uint8_t res_state)
             urb->errorcode = -EAGAIN;
             g_chusb_hcd.current_token = 0;
             if (g_chusb_hcd.current_pipe->ep_type == USB_ENDPOINT_TYPE_CONTROL) {
-                if (g_chusb_hcd.current_pipe_timeout > 0) {
+                if (g_chusb_hcd.current_pipe->waiter == true) {
                     chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_IN,
                                              g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
                 }
@@ -1122,7 +1170,7 @@ static int8_t chusb_inpipe_irq_handler(uint8_t res_state)
                             /**
                              * Data was transmitted last time, but this time NAK
                              */
-                            if (g_chusb_hcd.current_pipe_timeout > 0) {
+                            if (g_chusb_hcd.current_pipe->waiter == true) {
                                 chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_IN,
                                                          g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
                             } else {
@@ -1134,8 +1182,27 @@ static int8_t chusb_inpipe_irq_handler(uint8_t res_state)
                                 chusb_pipe_waitup(g_chusb_hcd.current_pipe, true);
                             }
                         } else {
-                            g_chusb_hcd.current_token = 0;
-                            chusb_pipe_waitup(g_chusb_hcd.current_pipe, false);
+                            /**
+                             * The device did not send any data. 
+                             */
+                            if (g_chusb_hcd.current_pipe->waiter == true) {
+                                /**
+                                 * Try again
+                                 */
+                                USB_LOG_DBG("The device does not transmit data, try again\r\n");
+                                chusb_host_pipe_transfer(g_chusb_hcd.current_pipe, USB_PID_IN,
+                                                         g_chusb_hcd.current_pipe->buffer, g_chusb_hcd.current_pipe->xferlen);
+                            } else {
+                                /**
+                                 * g_chusb_hcd.current_pipe->waiter = false
+                                 * We do not need to call a callback
+                                 */
+                                USB_LOG_DBG("Do not need try again\r\n");
+                                urb->errorcode = -EBUSY;
+                                g_chusb_hcd.current_token = 0;
+                                urb->actual_length = 0;
+                                chusb_pipe_waitup(g_chusb_hcd.current_pipe, false);
+                            }
                         }
                     } else {
                         USB_LOG_ERR("xferlen == 0//should get zero package\r\n");
@@ -1298,6 +1365,9 @@ __attribute__((interrupt("WCH-Interrupt-fast"))) void USBH_IRQHandler(void)
                     goto pipe_wait;
                 }
                 break;
+            default:
+                USBHS_HOST->INT_FG = USBHS_TRANSFER_FLAG;
+                break;
         }
     } else if (intflag & USBHS_DETECT_FLAG) {
         if (USBHS_HOST->MIS_ST & USBHS_ATTACH) {
@@ -1308,9 +1378,11 @@ __attribute__((interrupt("WCH-Interrupt-fast"))) void USBH_IRQHandler(void)
             usbh_roothub_thread_wakeup(1);
         } else {
             USB_LOG_INFO("Dev remove \r\n");
+#if 0
             if (g_chusb_hcd.main_pipe_using) {
                 g_chusb_hcd.main_pipe_using = false;
             }
+#endif
             g_chusb_hcd.port_csc = 1;
             g_chusb_hcd.port_pec = 1;
             g_chusb_hcd.port_pe = 0;