feat(usb): add CherryUSB support for multiple USB controllers selection

This commit is contained in:
LiPeng
2025-07-28 11:33:10 +08:00
committed by Li Peng
parent 0ac445cbd6
commit 8f9eeedae1
9 changed files with 111 additions and 22 deletions

View File

@@ -1,5 +1,23 @@
menu "Example Configuration" menu "Example Configuration"
choice EXAMPLE_USB_DEVICE_RHPORT
prompt "USB Device Peripheral"
default EXAMPLE_USB_DEVICE_RHPORT_HS if IDF_TARGET_ESP32P4
default EXAMPLE_USB_DEVICE_RHPORT_FS
help
Allows set the USB Peripheral Controller for USB device.
- High-speed (USB OTG2.0 Peripheral for High-, Full- and Low-speed)
- Full-speed (USB OTG1.1 Peripheral for Full- and Low-speed)
config EXAMPLE_USB_DEVICE_RHPORT_HS
bool "OTG2.0"
depends on IDF_TARGET_ESP32P4
config EXAMPLE_USB_DEVICE_RHPORT_FS
bool "OTG1.1"
endchoice
config EXAMPLE_CHERRYUSB_CDC_ACM_TWO_CHANNEL config EXAMPLE_CHERRYUSB_CDC_ACM_TWO_CHANNEL
bool "Enable usb cdc acm two channel" bool "Enable usb cdc acm two channel"
default n default n

View File

@@ -46,10 +46,13 @@ static TaskHandle_t s_task_handle = NULL;
/*!< config descriptor size */ /*!< config descriptor size */
#define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * 4) #define USB_CONFIG_SIZE (9 + CDC_ACM_DESCRIPTOR_LEN * 4)
#define CDC_FS_MAX_MPS 64
#define CDC_HS_MAX_MPS 512
#ifdef CONFIG_USB_HS #ifdef CONFIG_USB_HS
#define CDC_MAX_MPS 512 #define CDC_MAX_MPS CDC_HS_MAX_MPS
#else #else
#define CDC_MAX_MPS 64 #define CDC_MAX_MPS CDC_FS_MAX_MPS
#endif #endif
typedef struct { typedef struct {
@@ -68,27 +71,43 @@ static ep_status_t s_ep_status[CDC_ACM_CHANNEL_NUM] = {
#endif #endif
}; };
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
#define WRITE_BUFFER_SIZE ALIGN_UP(ALIGN_UP(2048, CDC_MAX_MPS), CONFIG_USB_ALIGN_SIZE)
#if CONFIG_EXAMPLE_CHERRYUSB_SET_READ_BUFFER_SIZE_MPS #if CONFIG_EXAMPLE_CHERRYUSB_SET_READ_BUFFER_SIZE_MPS
#define READ_BUFFER_SIZE CDC_MAX_MPS #define READ_BUFFER_SIZE ALIGN_UP(CDC_MAX_MPS, CONFIG_USB_ALIGN_SIZE)
#else #else
#define READ_BUFFER_SIZE 2048 #define READ_BUFFER_SIZE WRITE_BUFFER_SIZE
#endif #endif
static uint32_t s_mps = CDC_MAX_MPS;
static DRAM_DMA_ALIGNED_ATTR uint8_t read_buffer[CDC_ACM_CHANNEL_NUM][READ_BUFFER_SIZE]; static DRAM_DMA_ALIGNED_ATTR uint8_t read_buffer[CDC_ACM_CHANNEL_NUM][READ_BUFFER_SIZE];
static DRAM_DMA_ALIGNED_ATTR uint8_t write_buffer[CDC_ACM_CHANNEL_NUM][2048]; static DRAM_DMA_ALIGNED_ATTR uint8_t write_buffer[CDC_ACM_CHANNEL_NUM][WRITE_BUFFER_SIZE];
#ifdef CONFIG_USBDEV_ADVANCE_DESC #ifdef CONFIG_USBDEV_ADVANCE_DESC
static const uint8_t device_descriptor[] = { static const uint8_t device_descriptor[] = {
USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01) USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0100, 0x01)
}; };
static const uint8_t config_descriptor[] = { static const uint8_t config_descriptor_fs[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTERFACES_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTERFACES_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_FS_MAX_MPS, 0x02),
#ifdef CONFIG_EXAMPLE_CHERRYUSB_CDC_ACM_TWO_CHANNEL #ifdef CONFIG_EXAMPLE_CHERRYUSB_CDC_ACM_TWO_CHANNEL
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP1, CDC_OUT_EP1, CDC_IN_EP1, CDC_MAX_MPS, 0x02), CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP1, CDC_OUT_EP1, CDC_IN_EP1, CDC_FS_MAX_MPS, 0x02),
#endif #endif
}; };
#ifdef CONFIG_USB_HS
static const uint8_t config_descriptor_hs[] = {
USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, INTERFACES_NUM, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_HS_MAX_MPS, 0x02),
#ifdef CONFIG_EXAMPLE_CHERRYUSB_CDC_ACM_TWO_CHANNEL
CDC_ACM_DESCRIPTOR_INIT(0x02, CDC_INT_EP1, CDC_OUT_EP1, CDC_IN_EP1, CDC_HS_MAX_MPS, 0x02),
#endif
};
#endif
static const uint8_t device_quality_descriptor[] = { static const uint8_t device_quality_descriptor[] = {
/////////////////////////////////////// ///////////////////////////////////////
/// device qualifier descriptor /// device qualifier descriptor
@@ -122,7 +141,14 @@ static const uint8_t *device_descriptor_callback(uint8_t speed)
static const uint8_t *config_descriptor_callback(uint8_t speed) static const uint8_t *config_descriptor_callback(uint8_t speed)
{ {
return config_descriptor; #ifdef CONFIG_USB_HS
if (speed >= USB_SPEED_HIGH) {
s_mps = CDC_HS_MAX_MPS;
return config_descriptor_hs;
}
s_mps = CDC_FS_MAX_MPS;
#endif
return config_descriptor_fs;
} }
static const uint8_t *device_quality_descriptor_callback(uint8_t speed) static const uint8_t *device_quality_descriptor_callback(uint8_t speed)
@@ -270,14 +296,22 @@ static void usbd_cdc_acm_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
if (ep_status->write_len == 0) { if (ep_status->write_len == 0) {
memcpy(write_buffer[i], read_buffer[i], nbytes); memcpy(write_buffer[i], read_buffer[i], nbytes);
ep_status->write_len = nbytes; ep_status->write_len = nbytes;
#if CONFIG_EXAMPLE_CHERRYUSB_SET_READ_BUFFER_SIZE_MPS
usbd_ep_start_read(0, ep, read_buffer[i], s_mps);
#else
usbd_ep_start_read(0, ep, read_buffer[i], sizeof(read_buffer[0])); usbd_ep_start_read(0, ep, read_buffer[i], sizeof(read_buffer[0]));
#endif
} else { } else {
ep_status->read_len = nbytes; ep_status->read_len = nbytes;
ep_status->rx_busy_flag = false; ep_status->rx_busy_flag = false;
} }
xTaskNotifyFromISR(s_task_handle, NOTIFY_EP_BIT, eSetBits, &HPTaskAwoken); xTaskNotifyFromISR(s_task_handle, NOTIFY_EP_BIT, eSetBits, &HPTaskAwoken);
} else { } else {
usbd_ep_start_read(0, ep_status->rx_addr, read_buffer[i], sizeof(read_buffer[i])); #if CONFIG_EXAMPLE_CHERRYUSB_SET_READ_BUFFER_SIZE_MPS
usbd_ep_start_read(0, ep, read_buffer[i], s_mps);
#else
usbd_ep_start_read(0, ep, read_buffer[i], sizeof(read_buffer[i]));
#endif
} }
break; break;
} }
@@ -291,7 +325,7 @@ static void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
{ {
BaseType_t HPTaskAwoken = pdFALSE; BaseType_t HPTaskAwoken = pdFALSE;
ESP_EARLY_LOGI(TAG, "ep 0x%02X actual in len:%d", ep, nbytes); ESP_EARLY_LOGI(TAG, "ep 0x%02X actual in len:%d", ep, nbytes);
if ((nbytes % CDC_MAX_MPS) == 0 && nbytes) { if ((nbytes % s_mps) == 0 && nbytes) {
usbd_ep_start_write(0, ep, NULL, 0); usbd_ep_start_write(0, ep, NULL, 0);
} else { } else {
for (size_t i = 0; i < CDC_ACM_CHANNEL_NUM; i++) { for (size_t i = 0; i < CDC_ACM_CHANNEL_NUM; i++) {
@@ -354,7 +388,12 @@ static void cdc_acm_init(void)
usbd_add_endpoint(0, &cdc_out_ep1); usbd_add_endpoint(0, &cdc_out_ep1);
usbd_add_endpoint(0, &cdc_in_ep1); usbd_add_endpoint(0, &cdc_in_ep1);
#endif #endif
usbd_initialize(0, ESP_USBD_BASE, usbd_event_handler);
#if CONFIG_EXAMPLE_USB_DEVICE_RHPORT_HS
usbd_initialize(0, ESP_USB_HS0_BASE, usbd_event_handler);
#else
usbd_initialize(0, ESP_USB_FS0_BASE, usbd_event_handler);
#endif
} }
void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr) void usbd_cdc_acm_set_dtr(uint8_t busid, uint8_t intf, bool dtr)
@@ -389,7 +428,11 @@ void cdc_acm_task(void *arg)
ep_status->read_len = 0; ep_status->read_len = 0;
ep_status->rx_busy_flag = true; ep_status->rx_busy_flag = true;
#if CONFIG_EXAMPLE_CHERRYUSB_SET_READ_BUFFER_SIZE_MPS
usbd_ep_start_read(0, ep_status->rx_addr, read_buffer[i], s_mps);
#else
usbd_ep_start_read(0, ep_status->rx_addr, read_buffer[i], sizeof(read_buffer[0])); usbd_ep_start_read(0, ep_status->rx_addr, read_buffer[i], sizeof(read_buffer[0]));
#endif
} }
} }
for (size_t i = 0; i < sizeof(s_ep_status) / sizeof(s_ep_status[0]); i++) { for (size_t i = 0; i < sizeof(s_ep_status) / sizeof(s_ep_status[0]); i++) {
@@ -408,7 +451,11 @@ void cdc_acm_task(void *arg)
if (ep_status->rx_busy_flag == false) { if (ep_status->rx_busy_flag == false) {
if (ep_status->read_len == 0) { if (ep_status->read_len == 0) {
ep_status->rx_busy_flag = true; ep_status->rx_busy_flag = true;
#if CONFIG_EXAMPLE_CHERRYUSB_SET_READ_BUFFER_SIZE_MPS
usbd_ep_start_read(0, ep_status->rx_addr, read_buffer[i], s_mps);
#else
usbd_ep_start_read(0, ep_status->rx_addr, read_buffer[i], sizeof(read_buffer[i])); usbd_ep_start_read(0, ep_status->rx_addr, read_buffer[i], sizeof(read_buffer[i]));
#endif
} }
} }
} }

View File

@@ -1,3 +1,3 @@
## IDF Component Manager Manifest File ## IDF Component Manager Manifest File
dependencies: dependencies:
cherry-embedded/cherryusb: ~=1.5.0~4 cherry-embedded/cherryusb: ~=1.5.1~8

View File

@@ -9,8 +9,8 @@ This example demonstrates how to use the CherryUSB host driver. Currently, this
## How to use example ## How to use example
If you need to enable support for FTDI, please enable the following configuration By default, all drivers supported by the routine are enabled. If you need to trim or disable unnecessary drivers, please disable the corresponding driver configuration.
Run `idf.py menuconfig` and in `Component config → CherryUSB Configuration → Enable usb host mode → Enable usb ftdi driver` enable. Run `idf.py menuconfig` and in `Component config → CherryUSB Configuration → Enable usb host mode`, Uncheck the drivers you dont need.
### Hardware Required ### Hardware Required
* Development board with USB-OTG support * Development board with USB-OTG support

View File

@@ -1,5 +1,23 @@
menu "Example Configuration" menu "Example Configuration"
choice EXAMPLE_USB_HOST_RHPORT
prompt "USB Host Peripheral"
default EXAMPLE_USB_HOST_RHPORT_HS if IDF_TARGET_ESP32P4
default EXAMPLE_USB_HOST_RHPORT_FS
help
Allows set the USB Peripheral Controller for USB host.
- High-speed (USB OTG2.0 Peripheral for High-, Full- and Low-speed)
- Full-speed (USB OTG1.1 Peripheral for Full- and Low-speed)
config EXAMPLE_USB_HOST_RHPORT_HS
bool "OTG2.0"
depends on IDF_TARGET_ESP32P4
config EXAMPLE_USB_HOST_RHPORT_FS
bool "OTG1.1"
endchoice
config EXAMPLE_HAL_USE_ESP32_S3_USB_OTG config EXAMPLE_HAL_USE_ESP32_S3_USB_OTG
bool "Use dev kit ESP32-S3-USB-OTG" bool "Use dev kit ESP32-S3-USB-OTG"
depends on IDF_TARGET_ESP32S3 depends on IDF_TARGET_ESP32S3

View File

@@ -346,8 +346,9 @@ static void usbh_hid_callback(void *arg, int nbytes)
{ {
struct usbh_hid *hid_class = (struct usbh_hid *)arg; struct usbh_hid *hid_class = (struct usbh_hid *)arg;
hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data; hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data;
hid_intin->is_active = false;
if (nbytes <= 0) { if (nbytes <= 0) {
hid_intin->is_active = false;
return; return;
} }
uint8_t sub_class = hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceSubClass; uint8_t sub_class = hid_class->hport->config.intf[hid_class->intf].altsetting[0].intf_desc.bInterfaceSubClass;
@@ -362,6 +363,7 @@ static void usbh_hid_callback(void *arg, int nbytes)
} }
} }
complete_cb(hid_intin->buffer, nbytes); complete_cb(hid_intin->buffer, nbytes);
hid_intin->is_active = false;
} }
static void intin_timer_cb(void *arg) static void intin_timer_cb(void *arg)
@@ -437,11 +439,8 @@ void usbh_hid_run(struct usbh_hid *hid_class)
hid_class->user_data = hid_intin; hid_class->user_data = hid_intin;
//周期间隔低速、全速单位为1ms高速和超高速是125us esp_timer_start_periodic(hid_intin->timer, USBH_GET_URB_INTERVAL(hid_class->intin->bInterval, hid_class->hport->speed));
ret = USBH_GET_URB_INTERVAL(hid_class->intin->bInterval, hid_class->hport->speed);
ret = (hid_class->hport->speed < USB_SPEED_HIGH) ? (ret * 1000) : (ret * 125);
esp_timer_start_periodic(hid_intin->timer, ret);
return; return;
error: error:
if (hid_intin->buffer) { if (hid_intin->buffer) {

View File

@@ -1,3 +1,3 @@
## IDF Component Manager Manifest File ## IDF Component Manager Manifest File
dependencies: dependencies:
cherry-embedded/cherryusb: ~=1.5.0~4 cherry-embedded/cherryusb: ~=1.5.1~8

View File

@@ -43,7 +43,13 @@ void app_main(void)
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP #if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
reinit: reinit:
#endif #endif
usbh_initialize(0, ESP_USBH_BASE);
#if CONFIG_EXAMPLE_USB_HOST_RHPORT_HS
usbh_initialize(0, ESP_USB_HS0_BASE);
#else
usbh_initialize(0, ESP_USB_FS0_BASE);
#endif
ESP_LOGI(TAG, "Init usb"); ESP_LOGI(TAG, "Init usb");
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP #if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP

View File

@@ -10,6 +10,7 @@ CONFIG_CHERRYUSB_HOST_DWC2_ESP=y
CONFIG_CHERRYUSB_HOST_CDC_ACM=y CONFIG_CHERRYUSB_HOST_CDC_ACM=y
CONFIG_CHERRYUSB_HOST_HID=y CONFIG_CHERRYUSB_HOST_HID=y
CONFIG_CHERRYUSB_HOST_MSC=y CONFIG_CHERRYUSB_HOST_MSC=y
CONFIG_CHERRYUSB_HOST_FTDI=y
CONFIG_CHERRYUSB_HOST_CH34X=y CONFIG_CHERRYUSB_HOST_CH34X=y
CONFIG_CHERRYUSB_HOST_CP210X=y CONFIG_CHERRYUSB_HOST_CP210X=y
CONFIG_CHERRYUSB_HOST_PL2303=y CONFIG_CHERRYUSB_HOST_PL2303=y