summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChen Leeren <[email protected]>2023-04-07 18:26:17 +0800
committersakumisu <[email protected]>2023-04-08 19:32:27 +0800
commita51edd92312a95686f4de5fac0e31f8784c7acef (patch)
tree1dc4d6fa9d919726edb5adb83942689b30a5ae57
parent5a06a8548430356a03175bae2cd2a8e99e65e317 (diff)
Update wch driver
-rw-r--r--port/ch32/usb_hc_usbfs.c64
-rw-r--r--port/ch32/usb_hc_usbhs.c132
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;