ソースを参照

feat(core/usbd_core): add ep0 setup handler into thread feature

sakumisu 11 ヶ月 前
コミット
e592a548e9
3 ファイル変更128 行追加7 行削除
  1. 11 0
      cherryusb_config_template.h
  2. 101 5
      core/usbd_core.c
  3. 16 2
      osal/idf/usb_config.h

+ 11 - 0
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

+ 101 - 5
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;
 }

+ 16 - 2
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