diff --git a/class/msc/usbh_msc.c b/class/msc/usbh_msc.c index 47685888..f78b4662 100644 --- a/class/msc/usbh_msc.c +++ b/class/msc/usbh_msc.c @@ -32,7 +32,7 @@ static uint32_t g_devinuse = 0; * Name: usbh_msc_devno_alloc * * Description: - * Allocate a unique /dev/ttyACM[n] minor number in the range 0-31. + * Allocate a unique /dev/sd[n] minor number in the range 0-31. * ****************************************************************************/ @@ -144,10 +144,10 @@ static inline int usbh_msc_scsi_testunitready(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); } @@ -173,13 +173,13 @@ static inline int usbh_msc_scsi_requestsense(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the sense data response */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_FIXEDSENSEDATA_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); } @@ -206,13 +206,13 @@ static inline int usbh_msc_scsi_inquiry(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the sense data response */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_INQUIRY_SIZEOF); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_INQUIRY_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); } @@ -238,16 +238,16 @@ static inline int usbh_msc_scsi_readcapacity10(struct usbh_msc *msc_class) usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the sense data response */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_READCAPACITY10_SIZEOF); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, SCSIRESP_READCAPACITY10_SIZEOF, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Save the capacity information */ msc_class->blocknum = GET_BE32(&msc_class->tx_buffer[0]) + 1; msc_class->blocksize = GET_BE32(&msc_class->tx_buffer[4]); /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); } @@ -275,13 +275,13 @@ int usbh_msc_scsi_write10(struct usbh_msc *msc_class, uint32_t start_sector, con usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Send the user data */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)buffer, msc_class->blocksize * nsectors); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); } @@ -310,13 +310,13 @@ int usbh_msc_scsi_read10(struct usbh_msc *msc_class, uint32_t start_sector, cons usbh_msc_cbw_dump(cbw); /* Send the CBW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkout, (uint8_t *)cbw, USB_SIZEOF_MSC_CBW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the user data */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, (uint8_t *)buffer, msc_class->blocksize * nsectors); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, (uint8_t *)buffer, msc_class->blocksize * nsectors, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { /* Receive the CSW */ - nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW); + nbytes = usbh_ep_bulk_transfer(msc_class->bulkin, msc_class->tx_buffer, USB_SIZEOF_MSC_CSW, CONFIG_USBHOST_MSC_TIMEOUT); if (nbytes >= 0) { usbh_msc_csw_dump((struct CSW *)msc_class->tx_buffer); } @@ -338,7 +338,6 @@ int usbh_msc_connect(struct usbh_hubport *hport, uint8_t intf) } memset(msc_class, 0, sizeof(struct usbh_msc)); - msc_class->hport = hport; usbh_msc_devno_alloc(msc_class); snprintf(hport->config.intf[intf].devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar); diff --git a/common/usb_hc.h b/common/usb_hc.h index 7a12a98b..fbf8eef8 100644 --- a/common/usb_hc.h +++ b/common/usb_hc.h @@ -66,6 +66,15 @@ struct usbh_endpoint_cfg { */ int usb_hc_init(void); +/** + * @brief get port connect status + * + * @param port + * @return true + * @return false + */ +bool usbh_get_port_connect_status(const uint8_t port); + /** * @brief reset roothub port * @@ -130,6 +139,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). * @param buflen The length of the data to be sent or received. + * @param timeout Timeout for transfer, unit is ms. * @return On success, a non-negative value is returned that indicates the number * of bytes successfully transferred. On a failure, a negated errno value * is returned that indicates the nature of the failure: @@ -141,7 +151,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint * EPIPE - Overrun errors * */ -int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen); +int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout); /** * @brief Process a request to handle a transfer descriptor. This method will @@ -151,6 +161,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen); * @param ep The IN or OUT endpoint descriptor for the device endpoint on which to perform the transfer. * @param buffer A buffer containing the data to be sent (OUT endpoint) or received (IN endpoint). * @param buflen The length of the data to be sent or received. + * @param timeout Timeout for transfer, unit is ms. * @return On success, a non-negative value is returned that indicates the number * of bytes successfully transferred. On a failure, a negated errno value * is returned that indicates the nature of the failure: @@ -162,7 +173,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen); * EPIPE - Overrun errors * */ -int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen); +int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout); /** * @brief Process a request to handle a transfer asynchronously. This method diff --git a/core/usbh_core.c b/core/usbh_core.c index d07c64ca..74454b42 100644 --- a/core/usbh_core.c +++ b/core/usbh_core.c @@ -57,8 +57,7 @@ struct usbh_roothubport_priv { struct usbh_core_priv { struct usbh_roothubport_priv rhport[CONFIG_USBHOST_RHPORTS]; volatile struct usbh_hubport *active_hport; /* Used to pass external hub port events */ - volatile bool pscwait; /* TRUE: Thread is waiting for port status change event */ - usb_osal_sem_t pscsem; /* Semaphore to wait for a port event */ + usb_osal_event_t pscevent; /* Semaphore to wait for a port event */ } usbh_core_cfg; static inline struct usbh_roothubport_priv *usbh_find_roothub_port(struct usbh_hubport *hport) @@ -671,23 +670,46 @@ errout: static int usbh_portchange_wait(struct usbh_hubport **hport) { struct usbh_hubport *connport = NULL; + uint32_t recved_event; uint32_t flags; int ret; /* Loop until a change in connection state is detected */ while (1) { - /* Check for a change in the connection state on any root hub port */ + ret = usb_osal_event_recv(usbh_core_cfg.pscevent, USBH_EVENT_CONNECTED | USBH_EVENT_DISCONNECTED, &recved_event); + if (ret < 0) { + continue; + } flags = usb_osal_enter_critical_section(); for (uint8_t port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { + /* Check for a change in the connection state on any root hub port */ connport = &usbh_core_cfg.rhport[port - 1].hport; - if (connport->port_change) { connport->port_change = false; - *hport = connport; - usb_osal_leave_critical_section(flags); - return 0; + /* debounce for port,in order to keep port connect status stability*/ + usb_osal_msleep(25); + if (recved_event & USBH_EVENT_CONNECTED) { + if (usbh_get_port_connect_status(port)) { + if (!connport->connected) { + connport->connected = true; + *hport = connport; + usb_osal_leave_critical_section(flags); + return 0; + } + } + } else if (recved_event & USBH_EVENT_DISCONNECTED) { + if (!usbh_get_port_connect_status(port)) { + if (connport->connected) { + connport->connected = false; + *hport = connport; + usb_osal_leave_critical_section(flags); + return 0; + } + } + } } } +#ifdef CONFIG_USBHOST_HUB /* Is a device connected to an external hub? */ if (usbh_core_cfg.active_hport) { connport = (struct usbh_hubport *)usbh_core_cfg.active_hport; @@ -696,13 +718,8 @@ static int usbh_portchange_wait(struct usbh_hubport **hport) usb_osal_leave_critical_section(flags); return 0; } - /* No changes on any port. Wait for a connection/disconnection event and check again */ - usbh_core_cfg.pscwait = true; +#endif usb_osal_leave_critical_section(flags); - ret = usb_osal_sem_take(usbh_core_cfg.pscsem); - if (ret < 0) { - return ret; - } } } @@ -762,15 +779,9 @@ void usbh_external_hport_connect(struct usbh_hubport *hport) hport->connected = true; usbh_core_cfg.active_hport = hport; - - if (usbh_core_cfg.pscwait) { - usbh_core_cfg.pscwait = false; - usb_osal_leave_critical_section(flags); - usb_osal_sem_give(usbh_core_cfg.pscsem); - return; - } - usb_osal_leave_critical_section(flags); + + usb_osal_event_send(usbh_core_cfg.pscevent, USBH_EVENT_CONNECTED); } void usbh_external_hport_disconnect(struct usbh_hubport *hport) @@ -778,45 +789,18 @@ void usbh_external_hport_disconnect(struct usbh_hubport *hport) uint32_t flags; flags = usb_osal_enter_critical_section(); + hport->connected = false; usbh_core_cfg.active_hport = hport; - if (usbh_core_cfg.pscwait) { - usbh_core_cfg.pscwait = false; - usb_osal_leave_critical_section(flags); - usb_osal_sem_give(usbh_core_cfg.pscsem); - return; - } - usb_osal_leave_critical_section(flags); + usb_osal_event_send(usbh_core_cfg.pscevent, USBH_EVENT_DISCONNECTED); } void usbh_event_notify_handler(uint8_t event, uint8_t rhport) { - switch (event) { - case USBH_EVENT_ATTACHED: - if (!usbh_core_cfg.rhport[rhport - 1].hport.connected) { - usbh_core_cfg.rhport[rhport - 1].hport.connected = true; - usbh_core_cfg.rhport[rhport - 1].hport.port_change = true; - if (usbh_core_cfg.pscwait) { - usbh_core_cfg.pscwait = false; - usb_osal_sem_give(usbh_core_cfg.pscsem); - } - } - break; - case USBH_EVENT_REMOVED: - if (usbh_core_cfg.rhport[rhport - 1].hport.connected) { - usbh_core_cfg.rhport[rhport - 1].hport.connected = false; - usbh_core_cfg.rhport[rhport - 1].hport.port_change = true; - if (usbh_core_cfg.pscwait) { - usbh_core_cfg.pscwait = false; - usb_osal_sem_give(usbh_core_cfg.pscsem); - } - } - break; - default: - break; - } + usbh_core_cfg.rhport[rhport - 1].hport.port_change = true; + usb_osal_event_send(usbh_core_cfg.pscevent, event); } int usbh_initialize(void) @@ -824,11 +808,11 @@ int usbh_initialize(void) usb_osal_thread_t usb_thread; memset(&usbh_core_cfg, 0, sizeof(struct usbh_core_priv)); - +#ifdef CONFIG_USBHOST_HUB usbh_workq_initialize(); - - usbh_core_cfg.pscsem = usb_osal_sem_create(0); - if (usbh_core_cfg.pscsem == NULL) { +#endif + usbh_core_cfg.pscevent = usb_osal_event_create(); + if (usbh_core_cfg.pscevent == NULL) { return -1; } @@ -880,6 +864,7 @@ int lsusb(int argc, char **argv) } } } +#ifdef CONFIG_USBHOST_HUB usb_slist_for_each(hub_list, &hub_class_head) { usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); @@ -897,6 +882,7 @@ int lsusb(int argc, char **argv) } } } +#endif } else if (strcmp(argv[1], "-v") == 0) { for (port = USBH_HUB_PORT_START_INDEX; port <= CONFIG_USBHOST_RHPORTS; port++) { if (usbh_core_cfg.rhport[port - 1].hport.connected) { @@ -905,7 +891,7 @@ int lsusb(int argc, char **argv) usbh_print_hubport_info(&usbh_core_cfg.rhport[port - 1].hport); } } - +#ifdef CONFIG_USBHOST_HUB usb_slist_for_each(hub_list, &hub_class_head) { usbh_hub_t *hub_class = usb_slist_entry(hub_list, struct usbh_hub, list); @@ -918,6 +904,7 @@ int lsusb(int argc, char **argv) } } } +#endif } return 0; diff --git a/core/usbh_core.h b/core/usbh_core.h index fb001771..dd46b17d 100644 --- a/core/usbh_core.h +++ b/core/usbh_core.h @@ -27,8 +27,10 @@ #include "usb_def.h" #include "usb_hc.h" #include "usb_osal.h" +#ifdef CONFIG_USBHOST_HUB #include "usb_workq.h" #include "usbh_hub.h" +#endif #include "usb_config.h" #ifdef __cplusplus @@ -49,11 +51,12 @@ extern "C" { #define CLASS_DISCONNECT(hport, i) ((hport)->config.intf[i].class_driver->disconnect(hport, i)) enum usbh_event_type { - USBH_EVENT_ATTACHED, - USBH_EVENT_REMOVED, + USBH_EVENT_CONNECTED = (1 << 0), + USBH_EVENT_DISCONNECTED = (1 << 1), }; struct usbh_class_info { + uint8_t match_flags; uint8_t class; /* Base device class code */ uint8_t subclass; /* Sub-class, depends on base class. Eg. */ uint8_t protocol; /* Protocol, depends on base class. Eg. */ diff --git a/demo/usb_host.c b/demo/usb_host.c index 26e38037..90210f47 100644 --- a/demo/usb_host.c +++ b/demo/usb_host.c @@ -30,7 +30,7 @@ int cdc_acm_test(void) } memset(cdc_buffer, 0, 512); - ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512); + ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000); if (ret < 0) { printf("bulk in error\r\n"); return ret; @@ -43,7 +43,7 @@ int cdc_acm_test(void) const uint8_t data1[10] = { 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x08, 0x14 }; memcpy(cdc_buffer, data1, 8); - ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkout, cdc_buffer, 8); + ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkout, cdc_buffer, 8, 3000); if (ret < 0) { printf("bulk out error\r\n"); return ret; @@ -53,7 +53,7 @@ int cdc_acm_test(void) #if 0 usbh_ep_bulk_async_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, usbh_cdc_acm_callback, cdc_acm_class); #else - ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512); + ret = usbh_ep_bulk_transfer(cdc_acm_class->bulkin, cdc_buffer, 512, 3000); if (ret < 0) { printf("bulk in error\r\n"); return ret; @@ -68,7 +68,6 @@ int cdc_acm_test(void) #endif } - #include "ff.h" int msc_test(void) @@ -130,14 +129,13 @@ int msc_test(void) /*unmount*/ f_mount(NULL, "2:", 1); } else { - printf("open error:%d\r\n",res_sd); + printf("open error:%d\r\n", res_sd); } usb_iofree(ReadBuffer); #endif return ret; } - uint8_t hid_buffer[128]; void usbh_hid_callback(void *arg, int nbytes) @@ -167,7 +165,7 @@ int hid_test(void) return ret; } #else - ret = usbh_ep_intr_transfer(hid_class->intin, hid_buffer, 128); + ret = usbh_ep_intr_transfer(hid_class->intin, hid_buffer, 128, 1000); if (ret < 0) { return ret; } diff --git a/osal/usb_osal.h b/osal/usb_osal.h index 04703c80..92957c33 100644 --- a/osal/usb_osal.h +++ b/osal/usb_osal.h @@ -25,11 +25,10 @@ #include -#define USB_OSAL_MS2TICK(ms) - typedef void *usb_osal_thread_t; typedef void *usb_osal_sem_t; typedef void *usb_osal_mutex_t; +typedef void *usb_osal_event_t; typedef void (*usb_thread_entry_t)(void *argument); usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args); @@ -39,7 +38,7 @@ void usb_osal_thread_resume(usb_osal_thread_t thread); usb_osal_sem_t usb_osal_sem_create(uint32_t initial_count); void usb_osal_sem_delete(usb_osal_sem_t sem); -int usb_osal_sem_take(usb_osal_sem_t sem); +int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout); int usb_osal_sem_give(usb_osal_sem_t sem); usb_osal_mutex_t usb_osal_mutex_create(void); @@ -47,11 +46,15 @@ void usb_osal_mutex_delete(usb_osal_mutex_t mutex); int usb_osal_mutex_take(usb_osal_mutex_t mutex); int usb_osal_mutex_give(usb_osal_mutex_t mutex); +usb_osal_event_t usb_osal_event_create(void); +void usb_osal_event_delete(usb_osal_event_t event); +int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved); +int usb_osal_event_send(usb_osal_event_t event, uint32_t set); + uint32_t usb_osal_enter_critical_section(void); void usb_osal_leave_critical_section(uint32_t flag); void usb_osal_msleep(uint32_t delay); -uint32_t usb_osal_get_tick(void); +#endif -#endif \ No newline at end of file diff --git a/osal/usb_osal_freertos.c b/osal/usb_osal_freertos.c index 6a551393..98b9ac1e 100644 --- a/osal/usb_osal_freertos.c +++ b/osal/usb_osal_freertos.c @@ -23,6 +23,8 @@ #include "usb_osal.h" #include #include "semphr.h" +#include "timers.h" +#include "event_groups.h" usb_osal_thread_t usb_osal_thread_create(const char *name, uint32_t stack_size, uint32_t prio, usb_thread_entry_t entry, void *args) { @@ -52,9 +54,9 @@ void usb_osal_sem_delete(usb_osal_sem_t sem) vSemaphoreDelete((SemaphoreHandle_t)sem); } -int usb_osal_sem_take(usb_osal_sem_t sem) +int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) { - return (xSemaphoreTake((SemaphoreHandle_t)sem, portMAX_DELAY) == pdPASS) ? 0 : -1; + return (xSemaphoreTake((SemaphoreHandle_t)sem, pdMS_TO_TICKS(timeout)) == pdPASS) ? 0 : -1; } int usb_osal_sem_give(usb_osal_sem_t sem) @@ -101,6 +103,34 @@ int usb_osal_mutex_give(usb_osal_mutex_t mutex) return (xSemaphoreGive((SemaphoreHandle_t)mutex) == pdPASS) ? 0 : -1; } +usb_osal_event_t usb_osal_event_create(void) +{ + return (usb_osal_event_t)xEventGroupCreate(); +} + +void usb_osal_event_delete(usb_osal_event_t event) +{ + vEventGroupDelete((EventGroupHandle_t)event); +} + +int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved) +{ + *recved = xEventGroupWaitBits((EventGroupHandle_t)event, set, pdTRUE, pdFALSE, portMAX_DELAY); + return 0; +} + +int usb_osal_event_send(usb_osal_event_t event, uint32_t set) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + int ret; + + ret = xEventGroupSetBitsFromISR((EventGroupHandle_t)event, set, &xHigherPriorityTaskWoken); + if (ret == pdPASS) { + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } + return (ret == pdPASS) ? 0 : -1; +} + uint32_t usb_osal_enter_critical_section(void) { taskENTER_CRITICAL(); @@ -115,9 +145,4 @@ void usb_osal_leave_critical_section(uint32_t flag) void usb_osal_msleep(uint32_t delay) { vTaskDelay(pdMS_TO_TICKS(delay)); -} - -uint32_t usb_osal_get_tick(void) -{ - return xTaskGetTickCount(); -} +} \ No newline at end of file diff --git a/osal/usb_osal_rtthread.c b/osal/usb_osal_rtthread.c index f9e911b2..bb3adefa 100644 --- a/osal/usb_osal_rtthread.c +++ b/osal/usb_osal_rtthread.c @@ -51,9 +51,9 @@ void usb_osal_sem_delete(usb_osal_sem_t sem) rt_sem_delete((rt_sem_t)sem); } -int usb_osal_sem_take(usb_osal_sem_t sem) +int usb_osal_sem_take(usb_osal_sem_t sem, uint32_t timeout) { - return (int)rt_sem_take((rt_sem_t)sem, RT_WAITING_FOREVER); + return (int)rt_sem_take((rt_sem_t)sem, rt_tick_from_millisecond(timeout)); } int usb_osal_sem_give(usb_osal_sem_t sem) @@ -66,6 +66,11 @@ usb_osal_mutex_t usb_osal_mutex_create(void) return (usb_osal_mutex_t)rt_mutex_create("usbh_mutex", RT_IPC_FLAG_FIFO); } +void usb_osal_mutex_delete(usb_osal_mutex_t mutex) +{ + rt_mutex_delete((rt_mutex_t)mutex); +} + int usb_osal_mutex_take(usb_osal_mutex_t mutex) { return (int)rt_mutex_take((rt_mutex_t)mutex, RT_WAITING_FOREVER); @@ -76,18 +81,37 @@ int usb_osal_mutex_give(usb_osal_mutex_t mutex) return (int)rt_mutex_release((rt_mutex_t)mutex); } +usb_osal_event_t usb_osal_event_create(void) +{ + return (usb_osal_event_t)rt_event_create("psc_event", RT_IPC_FLAG_FIFO); +} + +void usb_osal_event_delete(usb_osal_event_t event) +{ + rt_event_delete((rt_event_t)event); +} + +int usb_osal_event_recv(usb_osal_event_t event, uint32_t set, uint32_t *recved) +{ + rt_event_recv((rt_event_t)event, set, RT_EVENT_FLAG_OR, RT_WAITING_FOREVER, recved); +} + +int usb_osal_event_send(usb_osal_event_t event, uint32_t set) +{ + rt_event_send((rt_event_t)event, set); +} + uint32_t usb_osal_enter_critical_section(void) { - rt_enter_critical(); - return 1; + return rt_hw_interrupt_disable(); } void usb_osal_leave_critical_section(uint32_t flag) { - rt_exit_critical(); + rt_hw_interrupt_enable(flag); } void usb_osal_msleep(uint32_t delay) { - rt_thread_mdelay(delay); + rt_thread_mdelay(rt_tick_from_millisecond(delay)); } \ No newline at end of file diff --git a/osal/usb_workq.c b/osal/usb_workq.c index ab4279bd..f8c1feb2 100644 --- a/osal/usb_workq.c +++ b/osal/usb_workq.c @@ -1,3 +1,25 @@ +/** + * @file usb_workq.c + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ #include "usb_list.h" #include "usb_osal.h" #include "usb_workq.h" @@ -29,7 +51,7 @@ static void usbh_hpwork_thread(void *argument) int ret; struct usb_workqueue *queue = (struct usb_workqueue *)argument; while (1) { - ret = usb_osal_sem_take(queue->sem); + ret = usb_osal_sem_take(queue->sem, 0xffffffff); if (ret < 0) { continue; } @@ -52,7 +74,7 @@ static void usbh_lpwork_thread(void *argument) int ret; struct usb_workqueue *queue = (struct usb_workqueue *)argument; while (1) { - ret = usb_osal_sem_take(queue->sem); + ret = usb_osal_sem_take(queue->sem, 0xffffffff); if (ret < 0) { continue; } diff --git a/osal/usb_workq.h b/osal/usb_workq.h index 4e20d93f..6d54b167 100644 --- a/osal/usb_workq.h +++ b/osal/usb_workq.h @@ -1,3 +1,25 @@ +/** + * @file usb_workq.h + * @brief + * + * Copyright (c) 2022 sakumisu + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + */ #ifndef _USB_WORKQUEUE_H #define _USB_WORKQUEUE_H diff --git a/port/ehci/usb_ehci.c b/port/ehci/usb_ehci.c index 0da339ae..cbd61e12 100644 --- a/port/ehci/usb_ehci.c +++ b/port/ehci/usb_ehci.c @@ -127,28 +127,22 @@ struct usb_ehci_epinfo_s { uint16_t speed : 2; /* See USB_*_SPEED definitions in ehci.h */ int result; /* The result of the transfer */ uint32_t xfrd; /* On completion, will hold the number of bytes transferred */ - - usb_osal_sem_t iocsem; /* Semaphore used to wait for transfer completion */ + bool inuse; + usb_osal_sem_t iocsem; /* Semaphore used to wait for transfer completion */ + usb_osal_mutex_t exclsem; /* Support mutually exclusive access */ #ifdef CONFIG_USBHOST_ASYNCH usbh_asynch_callback_t callback; /* Transfer complete callback */ void *arg; /* Argument that accompanies the callback */ #endif struct usbh_hubport *hport; - usb_slist_t list; }; /* This structure retains the overall state of the USB host controller */ struct usb_ehci_s { - volatile bool connected; /* Connected to device */ - usb_osal_mutex_t exclsem; /* Support mutually exclusive access */ - struct usb_work work; - struct usb_ehci_list_s *qhfree; /* List of free Queue Head (QH) structures */ struct usb_ehci_list_s *qtdfree; /* List of free Queue Element Transfer Descriptor (qTD) */ - - struct usb_ehci_epinfo_s ep0[CONFIG_USBHOST_RHPORTS]; /* EP0 endpoint info */ - usb_slist_t epinfo_list; + struct usb_ehci_epinfo_s chan[CONFIG_USBHOST_PIPE_NUM]; }; /**************************************************************************** @@ -303,6 +297,32 @@ static inline uint32_t usb_ehci_getreg(volatile uint32_t *regaddr) return *regaddr; } +static int usb_ehci_chan_alloc(struct usb_ehci_s *priv) +{ + int chidx; + + /* Search the table of channels */ + + for (chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { + /* Is this channel available? */ + if (!priv->chan[chidx].inuse) { + /* Yes... make it "in use" and return the index */ + + priv->chan[chidx].inuse = true; + return chidx; + } + } + + /* All of the channels are "in-use" */ + + return -EBUSY; +} + +static void usb_ehci_chan_free(struct usb_ehci_epinfo_s *chan) +{ + /* Mark the channel available */ + chan->inuse = false; +} /**************************************************************************** * Name: usb_ehci_qh_alloc * @@ -1287,7 +1307,7 @@ static int usb_ehci_ioc_setup(struct usb_ehci_epinfo_s *epinfo) /* Is the device still connected? */ flags = usb_osal_enter_critical_section(); - if (g_ehci.connected) { + if (epinfo->hport->connected) { /* Then set iocwait to indicate that we expect to be informed when * either (1) the device is disconnected, or (2) the transfer * completed. @@ -1341,7 +1361,7 @@ static int usb_ehci_ioc_async_setup(struct usb_ehci_epinfo_s *epinfo, usbh_async /* Is the device still connected? */ flags = usb_osal_enter_critical_section(); - if (g_ehci.connected) { + if (epinfo->hport->connected) { /* Then set iocwait to indicate that we expect to be informed when * either (1) the device is disconnected, or (2) the transfer * completed. @@ -1437,34 +1457,21 @@ static void usb_ehci_asynch_completion(struct usb_ehci_epinfo_s *epinfo) * ****************************************************************************/ -static int usb_ehci_transfer_wait(struct usb_ehci_epinfo_s *epinfo) +static int usb_ehci_transfer_wait(struct usb_ehci_epinfo_s *epinfo, uint32_t timeout) { int ret = 0; - int ret2; - - /* Release the EHCI semaphore while we wait. Other threads need the - * opportunity to access the EHCI resources while we wait. */ - - usb_osal_mutex_give(g_ehci.exclsem); /* Wait for the IOC completion event */ if (epinfo->iocwait) { - ret = usb_osal_sem_take(epinfo->iocsem); - if (ret == 0) { - ret = epinfo->result; + ret = usb_osal_sem_take(epinfo->iocsem, timeout); + if (ret < 0) { + return ret; } } - /* Re-acquire the EHCI semaphore. The caller expects to be holding this upon return.*/ - ret2 = usb_osal_mutex_take(g_ehci.exclsem); - if (ret2 < 0) { - ret = ret2; - } - - /* Did epinfo->result or usb_osal_mutex_take() report an error? */ + ret = epinfo->result; if (ret < 0) { - epinfo->iocwait = false; return ret; } @@ -1831,30 +1838,18 @@ static inline void usb_ehci_portsc_bottomhalf(void) /* Handle port connection status change (CSC) events */ if ((portsc & EHCI_PORTSC_CSC) != 0) { - /* Debounce */ - usb_osal_msleep(25); - /* Check current connect status*/ - portsc = usb_ehci_getreg(&HCOR->portsc[rhpndx]); if ((portsc & EHCI_PORTSC_CCS) == EHCI_PORTSC_CCS) { /* Connected ... Did we just become connected? */ - if (!g_ehci.connected) { - g_ehci.connected = 1; - usbh_event_notify_handler(USBH_EVENT_ATTACHED, 1); - } + usbh_event_notify_handler(USBH_EVENT_CONNECTED, 1); } else { - if (g_ehci.connected) { - g_ehci.connected = 0; - usb_slist_t *i; - usb_slist_for_each(i, &g_ehci.epinfo_list) - { - struct usb_ehci_epinfo_s *epinfo = usb_slist_entry(i, struct usb_ehci_epinfo_s, list); - if (epinfo->iocwait) { - epinfo->iocwait = false; - usb_osal_sem_give(epinfo->iocsem); - } + for (uint8_t chidx = 0; chidx < CONFIG_USBHOST_PIPE_NUM; chidx++) { + struct usb_ehci_epinfo_s *epinfo = &g_ehci.chan[chidx]; + if (epinfo->iocwait) { + epinfo->iocwait = false; + usb_osal_sem_give(epinfo->iocsem); } - usbh_event_notify_handler(USBH_EVENT_REMOVED, 1); } + usbh_event_notify_handler(USBH_EVENT_DISCONNECTED, 1); } } @@ -2035,12 +2030,9 @@ int usb_hc_init(void) uintptr_t physaddr1; uintptr_t physaddr2; - g_ehci.connected = 0; g_ehci.qhfree = NULL; g_ehci.qtdfree = NULL; - usb_slist_init(&g_ehci.epinfo_list); - /* Initialize the list of free Queue Head (QH) structures */ for (uint8_t i = 0; i < CONFIG_USB_EHCI_QH_NUM; i++) { @@ -2106,8 +2098,6 @@ int usb_hc_init(void) usb_ehci_dcache_clean((uintptr_t)&g_intrhead.hw, sizeof(struct usb_ehci_qh_s)); usb_ehci_dcache_clean((uintptr_t)g_framelist, FRAME_LIST_SIZE * sizeof(uint32_t)); - g_ehci.exclsem = usb_osal_mutex_create(); - usb_hc_low_level_init(); /* Host Controller Initialization. Paragraph 4.1 */ @@ -2194,6 +2184,17 @@ int usb_hc_init(void) return ret; } +bool usbh_get_port_connect_status(const uint8_t port) +{ + uint32_t portsc; + portsc = usb_ehci_getreg(&HCOR->portsc[port - 1]); + if ((portsc & EHCI_PORTSC_CCS) == EHCI_PORTSC_CCS) { + return true; + } else { + return false; + } +} + int usbh_reset_port(const uint8_t port) { uint32_t timeout = 0; @@ -2249,7 +2250,7 @@ int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uin DEBUGASSERT(epinfo != NULL && ep_mps < 2048); - ret = usb_osal_mutex_take(g_ehci.exclsem); + ret = usb_osal_mutex_take(epinfo->exclsem); if (ret < 0) { return ret; } @@ -2258,7 +2259,7 @@ int usbh_ep0_reconfigure(usbh_epinfo_t ep, uint8_t dev_addr, uint8_t ep_mps, uin epinfo->speed = speed; epinfo->maxpacket = ep_mps; - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return ret; } @@ -2267,24 +2268,18 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) { struct usb_ehci_epinfo_s *epinfo; struct usbh_hubport *hport; + int chidx; DEBUGASSERT(ep_cfg != NULL && ep_cfg->hport != NULL); hport = ep_cfg->hport; - /* new roothub ep info */ - if (((ep_cfg->ep_type & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_CONTROL) && (hport->parent == NULL)) { - memset(&g_ehci.ep0, 0, sizeof(struct usb_ehci_epinfo_s)); - epinfo = &g_ehci.ep0[hport->port - 1]; - } else { - /* new exteranl hub ep info */ - epinfo = usb_malloc(sizeof(struct usb_ehci_epinfo_s)); - memset(epinfo, 0, sizeof(struct usb_ehci_epinfo_s)); - if (epinfo == NULL) { - return -1; - } - } + chidx = usb_ehci_chan_alloc(&g_ehci); + epinfo = &g_ehci.chan[chidx]; + memset(epinfo, 0, sizeof(struct usb_ehci_epinfo_s)); + + epinfo->inuse = true; epinfo->epno = ep_cfg->ep_addr & 0x7f; epinfo->dirin = (ep_cfg->ep_addr & 0x80) ? 1 : 0; epinfo->devaddr = hport->dev_addr; @@ -2297,9 +2292,9 @@ int usbh_ep_alloc(usbh_epinfo_t *ep, const struct usbh_endpoint_cfg *ep_cfg) epinfo->hport = hport; epinfo->iocsem = usb_osal_sem_create(0); - usb_slist_add_tail(&g_ehci.epinfo_list, &epinfo->list); + epinfo->exclsem = usb_osal_mutex_create(); - *ep = epinfo; + *ep = (usbh_epinfo_t)epinfo; return 0; } @@ -2309,8 +2304,8 @@ int usbh_ep_free(usbh_epinfo_t ep) struct usb_ehci_epinfo_s *epinfo = (struct usb_ehci_epinfo_s *)ep; usb_osal_sem_delete(epinfo->iocsem); - usb_slist_remove(&g_ehci.epinfo_list, &epinfo->list); - usb_free(epinfo); + usb_osal_mutex_delete(epinfo->exclsem); + usb_ehci_chan_free(epinfo); return 0; } @@ -2330,7 +2325,7 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint DEBUGASSERT(setup || buffer); - ret = usb_osal_mutex_take(g_ehci.exclsem); + ret = usb_osal_mutex_take(epinfo->exclsem); if (ret < 0) { return ret; } @@ -2347,18 +2342,22 @@ int usbh_control_transfer(usbh_epinfo_t ep, struct usb_setup_packet *setup, uint } /* And wait for the transfer to complete */ - nbytes = usb_ehci_transfer_wait(epinfo); - usb_osal_mutex_give(g_ehci.exclsem); - return nbytes >= 0 ? 0 : (int)nbytes; + nbytes = usb_ehci_transfer_wait(epinfo, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT); + if (nbytes < 0) { + goto errout_with_iocwait; + } + + usb_osal_mutex_give(epinfo->exclsem); + return nbytes; errout_with_iocwait: epinfo->iocwait = false; errout_with_sem: - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return ret; } -int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen) +int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) { int nbytes; int ret; @@ -2367,7 +2366,7 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen) DEBUGASSERT(epinfo && buffer && buflen > 0); - ret = usb_osal_mutex_take(g_ehci.exclsem); + ret = usb_osal_mutex_take(epinfo->exclsem); if (ret < 0) { return ret; } @@ -2383,18 +2382,21 @@ int usbh_ep_bulk_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen) } /* And wait for the transfer to complete */ - nbytes = usb_ehci_transfer_wait(epinfo); - usb_osal_mutex_give(g_ehci.exclsem); + nbytes = usb_ehci_transfer_wait(epinfo, timeout); + if (nbytes < 0) { + goto errout_with_iocwait; + } + usb_osal_mutex_give(epinfo->exclsem); return nbytes; errout_with_iocwait: epinfo->iocwait = false; errout_with_sem: - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return ret; } -int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen) +int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen, uint32_t timeout) { int nbytes; int ret; @@ -2403,14 +2405,13 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen) DEBUGASSERT(epinfo && buffer && buflen > 0); - ret = usb_osal_mutex_take(g_ehci.exclsem); + ret = usb_osal_mutex_take(epinfo->exclsem); if (ret < 0) { return ret; } ret = usb_ehci_ioc_setup(epinfo); - - if (ret != 0) { + if (ret < 0) { goto errout_with_sem; } @@ -2420,14 +2421,17 @@ int usbh_ep_intr_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t buflen) } /* And wait for the transfer to complete */ - nbytes = usb_ehci_transfer_wait(epinfo); - usb_osal_mutex_give(g_ehci.exclsem); + nbytes = usb_ehci_transfer_wait(epinfo, timeout); + if (nbytes < 0) { + goto errout_with_iocwait; + } + usb_osal_mutex_give(epinfo->exclsem); return nbytes; errout_with_iocwait: epinfo->iocwait = false; errout_with_sem: - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return ret; } #ifdef CONFIG_USBHOST_ASYNCH @@ -2439,7 +2443,7 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl DEBUGASSERT(epinfo && buffer && buflen > 0); - ret = usb_osal_mutex_take(g_ehci.exclsem); + ret = usb_osal_mutex_take(epinfo->exclsem); if (ret < 0) { return ret; } @@ -2457,14 +2461,14 @@ int usbh_ep_bulk_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl } /* The transfer is in progress */ - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return 0; errout_with_callback: epinfo->callback = NULL; epinfo->arg = NULL; errout_with_sem: - usb_osal_mutex_give(&g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return ret; } @@ -2476,7 +2480,7 @@ int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl DEBUGASSERT(epinfo && buffer && buflen > 0); - ret = usb_osal_mutex_take(g_ehci.exclsem); + ret = usb_osal_mutex_take(epinfo->exclsem); if (ret < 0) { return ret; } @@ -2494,14 +2498,14 @@ int usbh_ep_intr_async_transfer(usbh_epinfo_t ep, uint8_t *buffer, uint32_t bufl } /* The transfer is in progress */ - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return 0; errout_with_callback: epinfo->callback = NULL; epinfo->arg = NULL; errout_with_sem: - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return ret; } #endif @@ -2548,7 +2552,7 @@ int usb_ep_cancel(usbh_epinfo_t ep) * interrupt level. */ - ret = usb_osal_sem_take(g_ehci.exclsem); + ret = usb_osal_mutex_take(epinfo->exclsem); if (ret < 0) { return ret; } @@ -2688,21 +2692,14 @@ exit_terminate: #endif errout_with_sem: - usb_osal_mutex_give(g_ehci.exclsem); + usb_osal_mutex_give(epinfo->exclsem); return ret; } static void usb_ehci_bottomhalf(void *arg) { uint32_t pending = (uint32_t)arg; - /* We need to have exclusive access to the EHCI data structures. Waiting - * here is not a good thing to do on the worker thread, but there is no - * real option (other than to reschedule and delay). - */ - usb_osal_mutex_take(g_ehci.exclsem); - - /* Handle all unmasked interrupt sources */ /* USB Interrupt (USBINT) * * "The Host Controller sets this bit to 1 on the completion of a USB @@ -2785,14 +2782,6 @@ static void usb_ehci_bottomhalf(void *arg) if ((pending & EHCI_INT_AAINT) != 0) { } - /* Re-enable relevant EHCI interrupts. Interrupts should still be enabled - * at the level of the interrupt controller. - */ - - usb_ehci_putreg(EHCI_HANDLED_INTS, &HCOR->usbintr); - - /* We are done with the EHCI structures */ - usb_osal_mutex_give(g_ehci.exclsem); } void usb_ehci_interrupt(void) @@ -2810,23 +2799,18 @@ void usb_ehci_interrupt(void) pending = usbsts & regval; if (pending != 0) { - /* Schedule interrupt handling work for the high priority worker - * thread so that we are not pressed for time and so that we can - * interrupt with other USB threads gracefully. - * - * The worker should be available now because we implement a handshake - * by controlling the EHCI interrupts. - */ - - usb_workqueue_submit(&g_hpworkq, &g_ehci.work, usb_ehci_bottomhalf, (void *)pending, 0); - /* Disable further EHCI interrupts so that we do not overrun the work - * queue. - */ + /* Disable further EHCI interrupts so that we do not overrun the work queue.*/ usb_ehci_putreg(0, &HCOR->usbintr); - /* Clear all pending status bits by writing the value of the pending * interrupt bits back to the status register. */ usb_ehci_putreg(usbsts & EHCI_INT_ALLINTS, &HCOR->usbsts); + + usb_ehci_bottomhalf((void *)pending); + + /* Re-enable relevant EHCI interrupts. Interrupts should still be enabled + * at the level of the interrupt controller. + */ + usb_ehci_putreg(EHCI_HANDLED_INTS, &HCOR->usbintr); } } \ No newline at end of file diff --git a/usb_config.h b/usb_config.h index 6a1fc714..86c786cc 100644 --- a/usb_config.h +++ b/usb_config.h @@ -12,12 +12,24 @@ #define CONFIG_USBHOST_EHPORTS 4 #endif +#ifndef CONFIG_USBHOST_PIPE_NUM +#define CONFIG_USBHOST_PIPE_NUM 10 +#endif + #ifndef CONFIG_USBHOST_INTF_NUM #define CONFIG_USBHOST_INTF_NUM 6 #endif #ifndef CONFIG_USBHOST_EP_NUM -#define CONFIG_USBHOST_EP_NUM 2 +#define CONFIG_USBHOST_EP_NUM 4 +#endif + +#ifndef CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT +#define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 5000 +#endif + +#ifndef CONFIG_USBHOST_MSC_TIMEOUT +#define CONFIG_USBHOST_MSC_TIMEOUT 5000 #endif #ifndef CONFIG_USBHOST_HPWORKQ_PRIO @@ -38,7 +50,7 @@ #define CONFIG_USBHOST_PSC_PRIO 4 #endif #ifndef CONFIG_USBHOST_PSC_STACKSIZE -#define CONFIG_USBHOST_PSC_STACKSIZE 2048 +#define CONFIG_USBHOST_PSC_STACKSIZE 4096 #endif #ifndef CONFIG_USBHOST_DEV_NAMELEN @@ -54,7 +66,7 @@ #define CONFIG_USB_EHCI_QH_NUM (10) #define CONFIG_USB_EHCI_QTD_NUM (10) // #define CONFIG_USB_EHCI_INFO_ENABLE -// #define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE +#define CONFIG_USB_ECHI_HCOR_RESERVED_DISABLE // #define CONFIG_USB_EHCI_CONFIGFLAG #endif \ No newline at end of file