mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 18:10:57 +02:00
feat(usb): add CherryUSB support for multiple USB controllers selection
This commit is contained in:
@@ -1,5 +1,23 @@
|
||||
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
|
||||
bool "Enable usb cdc acm two channel"
|
||||
default n
|
||||
|
@@ -46,10 +46,13 @@ static TaskHandle_t s_task_handle = NULL;
|
||||
/*!< config descriptor size */
|
||||
#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
|
||||
#define CDC_MAX_MPS 512
|
||||
#define CDC_MAX_MPS CDC_HS_MAX_MPS
|
||||
#else
|
||||
#define CDC_MAX_MPS 64
|
||||
#define CDC_MAX_MPS CDC_FS_MAX_MPS
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
@@ -68,27 +71,43 @@ static ep_status_t s_ep_status[CDC_ACM_CHANNEL_NUM] = {
|
||||
#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
|
||||
#define READ_BUFFER_SIZE CDC_MAX_MPS
|
||||
#define READ_BUFFER_SIZE ALIGN_UP(CDC_MAX_MPS, CONFIG_USB_ALIGN_SIZE)
|
||||
#else
|
||||
#define READ_BUFFER_SIZE 2048
|
||||
#define READ_BUFFER_SIZE WRITE_BUFFER_SIZE
|
||||
#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 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
|
||||
static const uint8_t device_descriptor[] = {
|
||||
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),
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
#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[] = {
|
||||
///////////////////////////////////////
|
||||
/// 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)
|
||||
{
|
||||
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)
|
||||
@@ -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) {
|
||||
memcpy(write_buffer[i], read_buffer[i], 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]));
|
||||
#endif
|
||||
} else {
|
||||
ep_status->read_len = nbytes;
|
||||
ep_status->rx_busy_flag = false;
|
||||
}
|
||||
xTaskNotifyFromISR(s_task_handle, NOTIFY_EP_BIT, eSetBits, &HPTaskAwoken);
|
||||
} 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;
|
||||
}
|
||||
@@ -291,7 +325,7 @@ static void usbd_cdc_acm_bulk_in(uint8_t busid, uint8_t ep, uint32_t nbytes)
|
||||
{
|
||||
BaseType_t HPTaskAwoken = pdFALSE;
|
||||
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);
|
||||
} else {
|
||||
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_in_ep1);
|
||||
#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)
|
||||
@@ -389,7 +428,11 @@ void cdc_acm_task(void *arg)
|
||||
|
||||
ep_status->read_len = 0;
|
||||
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]));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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->read_len == 0) {
|
||||
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]));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,3 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
cherry-embedded/cherryusb: ~=1.5.0~4
|
||||
cherry-embedded/cherryusb: ~=1.5.1~8
|
||||
|
@@ -9,8 +9,8 @@ This example demonstrates how to use the CherryUSB host driver. Currently, this
|
||||
|
||||
## How to use example
|
||||
|
||||
If you need to enable support for FTDI, please enable the following configuration
|
||||
Run `idf.py menuconfig` and in `Component config → CherryUSB Configuration → Enable usb host mode → Enable usb ftdi driver` enable.
|
||||
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`, Uncheck the drivers you don’t need.
|
||||
|
||||
### Hardware Required
|
||||
* Development board with USB-OTG support
|
||||
|
@@ -1,5 +1,23 @@
|
||||
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
|
||||
bool "Use dev kit ESP32-S3-USB-OTG"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
|
@@ -346,8 +346,9 @@ static void usbh_hid_callback(void *arg, int nbytes)
|
||||
{
|
||||
struct usbh_hid *hid_class = (struct usbh_hid *)arg;
|
||||
hid_int_in_t *hid_intin = (hid_int_in_t *)hid_class->user_data;
|
||||
hid_intin->is_active = false;
|
||||
|
||||
if (nbytes <= 0) {
|
||||
hid_intin->is_active = false;
|
||||
return;
|
||||
}
|
||||
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);
|
||||
hid_intin->is_active = false;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//周期间隔,低速、全速单位为1ms,高速和超高速是125us
|
||||
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, USBH_GET_URB_INTERVAL(hid_class->intin->bInterval, hid_class->hport->speed));
|
||||
|
||||
esp_timer_start_periodic(hid_intin->timer, ret);
|
||||
return;
|
||||
error:
|
||||
if (hid_intin->buffer) {
|
||||
|
@@ -1,3 +1,3 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
cherry-embedded/cherryusb: ~=1.5.0~4
|
||||
cherry-embedded/cherryusb: ~=1.5.1~8
|
||||
|
@@ -43,7 +43,13 @@ void app_main(void)
|
||||
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
|
||||
reinit:
|
||||
#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");
|
||||
|
||||
#if CONFIG_EXAMPLE_CHERRYUSB_INIT_DEINIT_LOOP
|
||||
|
@@ -10,6 +10,7 @@ CONFIG_CHERRYUSB_HOST_DWC2_ESP=y
|
||||
CONFIG_CHERRYUSB_HOST_CDC_ACM=y
|
||||
CONFIG_CHERRYUSB_HOST_HID=y
|
||||
CONFIG_CHERRYUSB_HOST_MSC=y
|
||||
CONFIG_CHERRYUSB_HOST_FTDI=y
|
||||
CONFIG_CHERRYUSB_HOST_CH34X=y
|
||||
CONFIG_CHERRYUSB_HOST_CP210X=y
|
||||
CONFIG_CHERRYUSB_HOST_PL2303=y
|
||||
|
Reference in New Issue
Block a user