diff options
| author | Chen Leeren <[email protected]> | 2023-04-07 18:26:17 +0800 |
|---|---|---|
| committer | sakumisu <[email protected]> | 2023-04-08 19:32:27 +0800 |
| commit | a51edd92312a95686f4de5fac0e31f8784c7acef (patch) | |
| tree | 1dc4d6fa9d919726edb5adb83942689b30a5ae57 | |
| parent | 5a06a8548430356a03175bae2cd2a8e99e65e317 (diff) | |
Update wch driver
| -rw-r--r-- | port/ch32/usb_hc_usbfs.c | 64 | ||||
| -rw-r--r-- | port/ch32/usb_hc_usbhs.c | 132 |
2 files changed, 142 insertions, 54 deletions
diff --git a/port/ch32/usb_hc_usbfs.c b/port/ch32/usb_hc_usbfs.c index 16ce5aa4..190ba047 100644 --- a/port/ch32/usb_hc_usbfs.c +++ b/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) { diff --git a/port/ch32/usb_hc_usbhs.c b/port/ch32/usb_hc_usbhs.c index bce61ca9..46cf51f7 100644 --- a/port/ch32/usb_hc_usbhs.c +++ b/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; |
