diff --git a/cherryusb_config_template.h b/cherryusb_config_template.h index 3a38e994..ba334362 100644 --- a/cherryusb_config_template.h +++ b/cherryusb_config_template.h @@ -48,6 +48,17 @@ /* Enable test mode */ // #define CONFIG_USBDEV_TEST_MODE +/* move ep0 setup handler from isr to thread */ +// #define CONFIG_USBDEV_EP0_THREAD + +#ifndef CONFIG_USBDEV_EP0_PRIO +#define CONFIG_USBDEV_EP0_PRIO 4 +#endif + +#ifndef CONFIG_USBDEV_EP0_STACKSIZE +#define CONFIG_USBDEV_EP0_STACKSIZE 2048 +#endif + #ifndef CONFIG_USBDEV_MSC_MAX_LUN #define CONFIG_USBDEV_MSC_MAX_LUN 1 #endif diff --git a/core/usbd_core.c b/core/usbd_core.c index d7fb3517..f95ee753 100644 --- a/core/usbd_core.c +++ b/core/usbd_core.c @@ -4,6 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "usbd_core.h" +#ifdef CONFIG_USBDEV_EP0_THREAD +#include "usb_osal.h" + +#define USB_EP0_STATE_SETUP 0 +#define USB_EP0_STATE_IN 1 +#define USB_EP0_STATE_OUT 2 +#endif + +#undef USB_DBG_TAG +#define USB_DBG_TAG "usbd_core" +#include "usb_log.h" /* general descriptor field offsets */ #define DESC_bLength 0 /** Length offset */ @@ -62,6 +73,10 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv { #endif #ifdef CONFIG_USBDEV_TEST_MODE bool test_req; +#endif +#ifdef CONFIG_USBDEV_EP0_THREAD + usb_osal_mq_t usbd_ep0_mq; + usb_osal_thread_t usbd_ep0_thread; #endif struct usbd_interface *intf[16]; uint8_t intf_altsetting[16]; @@ -1125,12 +1140,10 @@ void usbd_event_reset_handler(uint8_t busid) g_usbd_core[busid].event_handler(busid, USBD_EVENT_RESET); } -void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup) +static void __usbd_event_ep0_setup_complete_handler(uint8_t busid, struct usb_setup_packet *setup) { - struct usb_setup_packet *setup = &g_usbd_core[busid].setup; uint8_t *buf; - memcpy(setup, psetup, 8); #ifdef CONFIG_USBDEV_SETUP_LOG_PRINT usbd_print_setup(setup); #endif @@ -1195,7 +1208,20 @@ void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup) } } -void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes) +void usbd_event_ep0_setup_complete_handler(uint8_t busid, uint8_t *psetup) +{ + struct usb_setup_packet *setup = &g_usbd_core[busid].setup; + + memcpy(setup, psetup, 8); + +#ifdef CONFIG_USBDEV_EP0_THREAD + usb_osal_mq_send(g_usbd_core[busid].usbd_ep0_mq, USB_EP0_STATE_SETUP); +#else + __usbd_event_ep0_setup_complete_handler(busid, setup); +#endif +} + +static void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes) { struct usb_setup_packet *setup = &g_usbd_core[busid].setup; @@ -1236,11 +1262,12 @@ void usbd_event_ep0_in_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbyt } } -void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes) +static void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nbytes) { struct usb_setup_packet *setup = &g_usbd_core[busid].setup; (void)ep; + (void)setup; if (nbytes > 0) { g_usbd_core[busid].ep0_data_buf += nbytes; @@ -1249,6 +1276,9 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby USB_LOG_DBG("EP0 recv %d bytes, %d remained\r\n", nbytes, g_usbd_core[busid].ep0_data_buf_residue); if (g_usbd_core[busid].ep0_data_buf_residue == 0) { +#ifdef CONFIG_USBDEV_EP0_THREAD + usb_osal_mq_send(g_usbd_core[busid].usbd_ep0_mq, USB_EP0_STATE_OUT); +#else /* Received all, send data to handler */ g_usbd_core[busid].ep0_data_buf = g_usbd_core[busid].req_data; if (!usbd_setup_request_handler(busid, setup, &g_usbd_core[busid].ep0_data_buf, &g_usbd_core[busid].ep0_data_buf_len)) { @@ -1258,6 +1288,7 @@ void usbd_event_ep0_out_complete_handler(uint8_t busid, uint8_t ep, uint32_t nby /*Send status to host*/ usbd_ep_start_write(busid, USB_CONTROL_IN_EP0, NULL, 0); +#endif } else { /* Start reading the remain data */ usbd_ep_start_read(busid, USB_CONTROL_OUT_EP0, g_usbd_core[busid].ep0_data_buf, g_usbd_core[busid].ep0_data_buf_residue); @@ -1396,6 +1427,47 @@ int usbd_send_remote_wakeup(uint8_t busid) } } +#ifdef CONFIG_USBDEV_EP0_THREAD +static void usbdev_ep0_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV) +{ + uintptr_t event; + int ret; + uint8_t busid = (uint8_t)CONFIG_USB_OSAL_THREAD_GET_ARGV; + struct usb_setup_packet *setup = &g_usbd_core[busid].setup; + + while (1) { + ret = usb_osal_mq_recv(g_usbd_core[busid].usbd_ep0_mq, (uintptr_t *)&event, USB_OSAL_WAITING_FOREVER); + if (ret < 0) { + continue; + } + USB_LOG_DBG("event:%d\r\n", event); + + switch (event) { + case USB_EP0_STATE_SETUP: + __usbd_event_ep0_setup_complete_handler(busid, setup); + break; + case USB_EP0_STATE_IN: + // do nothing + break; + case USB_EP0_STATE_OUT: + /* Received all, send data to handler */ + g_usbd_core[busid].ep0_data_buf = g_usbd_core[busid].req_data; + if (!usbd_setup_request_handler(busid, setup, &g_usbd_core[busid].ep0_data_buf, &g_usbd_core[busid].ep0_data_buf_len)) { + usbd_ep_set_stall(busid, USB_CONTROL_IN_EP0); + return; + } + + /*Send status to host*/ + usbd_ep_start_write(busid, USB_CONTROL_IN_EP0, NULL, 0); + break; + + default: + break; + } + } +} +#endif + int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uint8_t busid, uint8_t event)) { int ret; @@ -1410,6 +1482,21 @@ int usbd_initialize(uint8_t busid, uintptr_t reg_base, void (*event_handler)(uin bus = &g_usbdev_bus[busid]; bus->reg_base = reg_base; +#ifdef CONFIG_USBDEV_EP0_THREAD + g_usbd_core[busid].usbd_ep0_mq = usb_osal_mq_create(1); + if (g_usbd_core[busid].usbd_ep0_mq == NULL) { + USB_LOG_ERR("No memory to alloc for g_usbd_core[busid].usbd_ep0_mq\r\n"); + while (1) { + } + } + g_usbd_core[busid].usbd_ep0_thread = usb_osal_thread_create("usbd_ep0", CONFIG_USBDEV_EP0_STACKSIZE, CONFIG_USBDEV_EP0_PRIO, usbdev_ep0_thread, (void *)(uint32_t)busid); + if (g_usbd_core[busid].usbd_ep0_thread == NULL) { + USB_LOG_ERR("No memory to alloc for g_usbd_core[busid].usbd_ep0_thread\r\n"); + while (1) { + } + } +#endif + g_usbd_core[busid].event_handler = event_handler; ret = usb_dc_init(busid); usbd_class_event_notify_handler(busid, USBD_EVENT_INIT, NULL); @@ -1429,5 +1516,14 @@ int usbd_deinitialize(uint8_t busid) usbd_class_event_notify_handler(busid, USBD_EVENT_DEINIT, NULL); usb_dc_deinit(busid); g_usbd_core[busid].intf_offset = 0; +#ifdef CONFIG_USBDEV_EP0_THREAD + if (g_usbd_core[busid].usbd_ep0_mq) { + usb_osal_mq_delete(g_usbd_core[busid].usbd_ep0_mq); + } + if (g_usbd_core[busid].usbd_ep0_thread) { + usb_osal_thread_delete(g_usbd_core[busid].usbd_ep0_thread); + } +#endif + return 0; } diff --git a/osal/idf/usb_config.h b/osal/idf/usb_config.h index f2cf940a..02e90a71 100644 --- a/osal/idf/usb_config.h +++ b/osal/idf/usb_config.h @@ -20,7 +20,7 @@ /* Enable print with color */ #define CONFIG_USB_PRINTF_COLOR_ENABLE -/* data align size when use dma */ +/* data align size when use dma or use dcache */ #ifndef CONFIG_USB_ALIGN_SIZE #define CONFIG_USB_ALIGN_SIZE 4 #endif @@ -29,7 +29,6 @@ #define USB_NOCACHE_RAM_SECTION /* ================= USB Device Stack Configuration ================ */ -// NOTE: Below configurations are removed to Kconfig, `idf.py menuconfig` to config them /* Ep0 in and out transfer buffer */ #ifndef CONFIG_USBDEV_REQUEST_BUFFER_LEN @@ -50,6 +49,17 @@ /* Enable test mode */ // #define CONFIG_USBDEV_TEST_MODE +/* move ep0 setup handler from isr to thread */ +// #define CONFIG_USBDEV_EP0_THREAD + +#ifndef CONFIG_USBDEV_EP0_PRIO +#define CONFIG_USBDEV_EP0_PRIO 4 +#endif + +#ifndef CONFIG_USBDEV_EP0_STACKSIZE +#define CONFIG_USBDEV_EP0_STACKSIZE 2048 +#endif + #ifndef CONFIG_USBDEV_MSC_MAX_LUN #define CONFIG_USBDEV_MSC_MAX_LUN 1 #endif @@ -70,6 +80,10 @@ #define CONFIG_USBDEV_MSC_VERSION_STRING "0.01" #endif +/* move msc read & write from isr to while(1), you should call usbd_msc_polling in while(1) */ +// #define CONFIG_USBDEV_MSC_POLLING + +/* move msc read & write from isr to thread */ // #define CONFIG_USBDEV_MSC_THREAD #ifndef CONFIG_USBDEV_MSC_PRIO