### GCC Linker Script Example with USBH Class Info Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/transplant.md An example of a GCC linker script that includes the definition for the USB host class information section within the .text section. ```c /* The program code and other data into "FLASH" Rom type memory */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); __usbh_class_info_start__ = .; KEEP(*(.usbh_class_info)) __usbh_class_info_end__ = .; . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } > FLASH ``` -------------------------------- ### Audio Open Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Starts audio data transmission. This is a callback function invoked when the host sends a start command. ```APIDOC ## usbd_audio_open ### Description Used to start audio data transmission. This is a callback function invoked when the host sends a start command. ### Function Signature ```C void usbd_audio_open(uint8_t intf); ``` ### Parameters - **intf** (uint8_t) - Interface number to open ``` -------------------------------- ### Start USB Host Thread Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/demo.md Start the thread for USB host operations. ```c /* Start thread */ ``` -------------------------------- ### Initialize USB Device Stack (C) Source: https://context7.com/cherry-embedded/cherryusb/llms.txt Initializes the USB device stack, registers callbacks, and starts enumeration. Must be called after descriptor registration and interface/endpoint additions. ```c #include "usbd_core.h" #include "usbd_cdc_acm.h" #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x02 #define CDC_INT_EP 0x83 #define CDC_MAX_MPS 64 /* 512 for HS */ /* USB descriptors */ static const uint8_t device_descriptor[] = { USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, 0xFFFF, 0xFFFF, 0x0100, 0x01) }; static const uint8_t config_descriptor[] = { USB_CONFIG_DESCRIPTOR_INIT(9 + CDC_ACM_DESCRIPTOR_LEN, 0x02, 0x01, USB_CONFIG_BUS_POWERED, 100), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02) }; static const char *string_descriptors[] = { (const char[]){ 0x09, 0x04 }, /* LangID: English */ "MyCompany", /* Manufacturer */ "CDC ACM Device", /* Product */ "000001", /* Serial */ }; static const uint8_t *dev_desc_cb(uint8_t speed) { return device_descriptor; } static const uint8_t *cfg_desc_cb(uint8_t speed) { return config_descriptor; } static const uint8_t *qual_desc_cb(uint8_t speed) { return NULL; } static const char *str_desc_cb(uint8_t speed, uint8_t idx) { if (idx >= sizeof(string_descriptors) / sizeof(char *)) return NULL; return string_descriptors[idx]; } const struct usb_descriptor cdc_desc = { .device_descriptor_callback = dev_desc_cb, .config_descriptor_callback = cfg_desc_cb, .device_quality_descriptor_callback = qual_desc_cb, .string_descriptor_callback = str_desc_cb }; static struct usbd_interface intf0, intf1; static void usbd_event_handler(uint8_t busid, uint8_t event) { if (event == USBD_EVENT_CONFIGURED) usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, sizeof(read_buffer)); } /* Call once at startup, passing the hardware register base address */ void app_usb_init(void) { usbd_desc_register(0, &cdc_desc); usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf0)); usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf1)); usbd_add_endpoint(0, &(struct usbd_endpoint){ .ep_addr = CDC_OUT_EP, .ep_cb = cdc_bulk_out }); usbd_add_endpoint(0, &(struct usbd_endpoint){ .ep_addr = CDC_IN_EP, .ep_cb = cdc_bulk_in }); int ret = usbd_initialize(0, USB_BASE /* reg base */, usbd_event_handler); /* ret == 0 on success */ } ``` -------------------------------- ### usbd_video_open Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Starts the video data transmission for a specified interface. ```APIDOC ## usbd_video_open ### Description Used to start video data transmission. ### Function Signature ```c void usbd_video_open(uint8_t intf); ``` ### Parameters - **intf** (uint8_t) - Interface number to open. ``` -------------------------------- ### Initialize USB Audio Interface Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Initializes the USB Audio Class (UAC) interface. It handles setup requests and provides callbacks for audio events. ```C struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface *intf, uint16_t uac_version, struct audio_entity_info *table, uint8_t num); ``` -------------------------------- ### Open USB Audio Stream Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Starts audio data transmission for a specified interface. This is typically called when the host sends a start command. ```C void usbd_audio_open(uint8_t intf); ``` -------------------------------- ### Initialize USB Video Class Interface Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Initialize the USB Video class interface and set up handlers for setup requests and other interrupt callbacks. Configure frame interval, max video frame size, and max payload transfer size. ```c struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize); ``` -------------------------------- ### WinUSB Interface Descriptor Setup Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbd_winusb.md Defines the interface and endpoint descriptors for a WinUSB device. This includes setting the interface class to FF (Vendor Specific) and defining bulk endpoints. ```c /* Interface 0 */ USB_INTERFACE_DESCRIPTOR_INIT(0x00, 0x00, 0x02, 0xFF, 0x00, 0x00, 0x02), /* Endpoint OUT 2 */ USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_OUT_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00), /* Endpoint IN 1 */ USB_ENDPOINT_DESCRIPTOR_INIT(WINUSB_IN_EP, USB_ENDPOINT_TYPE_BULK, WINUSB_EP_MPS, 0x00), ``` -------------------------------- ### Start USB Endpoint Read (DCD) Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_port.md Starts endpoint reception asynchronously. A callback is triggered upon completion. This function is open to users. Recommended data length is within 16K bytes and preferably a multiple of the maximum packet size. ```C int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len); ``` -------------------------------- ### Initialize USB Host Low-Level Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/demo.md Copy the content of HAL_HCD_MspInit function to usb_hc_low_level_init. Disable ST generated USB initialization. This step is no longer needed starting from V1.5.0. ```c /* Copy the content of HAL_HCD_MspInit function in xxx_msp.c to usb_hc_low_level_init function, disable ST generated USB initialization */ ``` -------------------------------- ### Start USB Endpoint Write (DCD) Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_port.md Starts endpoint transmission asynchronously. A callback is triggered upon completion. This function is open to users. Recommended data length is within 16K bytes. ```C int usbd_ep_start_write(const uint8_t ep, const uint8_t *data, uint32_t data_len); ``` -------------------------------- ### Implement USB Host Transfer APIs Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbh_vendor.md Design synchronous or asynchronous send/receive APIs. This example shows synchronous IN and OUT transfers using URBs. ```C int usbh_xxx_in_transfer(struct usbh_xxx *xxx_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) { int ret; struct usbh_urb *urb = &xxx_class->xxxin_urb; usbh_xxx_urb_fill(urb, xxx_class->hport, xxx_class->xxxin, buffer, buflen, timeout, NULL, NULL); ret = usbh_submit_urb(urb); if (ret == 0) { ret = urb->actual_length; } return ret; } int usbh_xxx_out_transfer(struct usbh_xxx *xxx_class, uint8_t *buffer, uint32_t buflen, uint32_t timeout) { int ret; struct usbh_urb *urb = &xxx_class->xxxout_urb; usbh_xxx_urb_fill(urb, xxx_class->hport, xxx_class->xxxout, buffer, buflen, timeout, NULL, NULL); ret = usbh_submit_urb(urb); if (ret == 0) { ret = urb->actual_length; } return ret; } ``` -------------------------------- ### Initialize USB Device Low-Level Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/demo.md Copy the content of HAL_PCD_MspInit function to usb_dc_low_level_init. Disable ST generated USB initialization. This step is no longer needed starting from V1.5.0. ```c /* Copy the content of HAL_PCD_MspInit function in xxx_msp.c to usb_dc_low_level_init function, disable ST generated USB initialization */ ``` -------------------------------- ### ICF Linker Script for Non-Cache RAM Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/transplant.md An ICF linker script example that defines a region for non-cacheable RAM and places specific sections within it. ```c define region NONCACHEABLE_RAM = [from 0x1140000 size 256K]; place in NONCACHEABLE_RAM { section .noncacheable, section .noncacheable.init, section .noncacheable.bss }; // Noncacheable ``` -------------------------------- ### GCC Linker Script for Non-Cache RAM Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/transplant.md This GCC linker script example defines a non-cache RAM region and a section for non-cacheable data. ```c MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 256K - 64K RAM_nocache (xrw) : ORIGIN = 0x20030000, LENGTH = 64K FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K } ._nocache_ram : { . = ALIGN(4); *(.noncacheable) } >RAM_nocache ``` -------------------------------- ### SCT Linker Script for Non-Cache RAM Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/transplant.md An SCT linker script example that defines a specific memory region for non-cacheable USB data. ```c LR_IROM1 0x08000000 0x00200000 { ; load region size_region ER_IROM1 0x08000000 0x00200000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } RW_IRAM2 0x24000000 0x00070000 { ; RW data .ANY (+RW +ZI) } USB_NOCACHERAM 0x24070000 0x00010000 { ; RW data *(.noncacheable) } } ``` -------------------------------- ### Initialize USB Device Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/demo.md Call the template content initialization and fill in the bus ID and USB IP's register base. Bus ID starts from 0 and cannot exceed CONFIG_USBDEV_MAX_BUS. ```c /* Call template content initialization and fill in busid and USB IP’s reg base. busid starts from 0 and cannot exceed CONFIG_USBDEV_MAX_BUS */ ``` -------------------------------- ### Start Writing Video Data Stream Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Initiate the transmission of a single video frame. This function must be used in conjunction with `usbd_video_stream_split_transfer`. The `do_copy` parameter should be false only if the source buffer is in a non-cached area and DCACHE is enabled. ```c int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf, uint8_t *stream_buf, uint32_t stream_len, bool do_copy); ``` -------------------------------- ### USB Network Card Connection and Initialization Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbh_net.md This function is automatically called after USB network card enumeration. It registers the netif driver, starts the DHCP client, and initializes the IP acquisition timer. ```C void usbh_cdc_ecm_run(struct usbh_cdc_ecm *cdc_ecm_class) { struct netif *netif = &g_cdc_ecm_netif; netif->hwaddr_len = 6; memcpy(netif->hwaddr, cdc_ecm_class->mac, 6); IP4_ADDR(&g_ipaddr, 0, 0, 0, 0); IP4_ADDR(&g_netmask, 0, 0, 0, 0); IP4_ADDR(&g_gateway, 0, 0, 0, 0); netif = netif_add(netif, &g_ipaddr, &g_netmask, &g_gateway, NULL, usbh_cdc_ecm_if_init, tcpip_input); netif_set_default(netif); while (!netif_is_up(netif)) { } dhcp_handle = usb_osal_timer_create("dhcp", 200, dhcp_timeout, netif, true); if (dhcp_handle == NULL) { USB_LOG_ERR("timer creation failed! \r\n"); while (1) { } } usb_osal_thread_create("usbh_cdc_ecm_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_cdc_ecm_rx_thread, NULL); #if LWIP_DHCP dhcp_start(netif); usb_osal_timer_start(dhcp_handle); #endif } ``` -------------------------------- ### Initialize USB Host Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/demo.md Call usbh_initialize and fill in the bus ID, USB IP's register base, and event handler (can be omitted as NULL). Bus ID starts from 0 and cannot exceed CONFIG_USBHOST_MAX_BUS. ```c /* Call usbh_initialize and fill in busid and USB IP’s reg base and event_handler (can be omitted as NULL). busid starts from 0 and cannot exceed CONFIG_USBHOST_MAX_BUS */ ``` -------------------------------- ### Initialize Composite USB Device (CDC+MSC+HID) Source: https://context7.com/cherry-embedded/cherryusb/llms.txt Demonstrates adding multiple interfaces (CDC, MSC, HID) to a single USB port before initializing the device. Ensure endpoints and interfaces are registered correctly. ```c #include "usbd_core.h" #include "usbd_cdc_acm.h" #include "usbd_msc.h" #include "usbd_hid.h" #define CDC_INT_EP 0x83 #define CDC_OUT_EP 0x02 #define CDC_IN_EP 0x81 #define MSC_OUT_EP 0x05 #define MSC_IN_EP 0x84 #define HID_INT_EP 0x86 static struct usbd_interface cdc_comm, cdc_data, msc_intf, hid_intf; static const uint8_t config_descriptor[] = { USB_CONFIG_DESCRIPTOR_INIT(USB_CONFIG_SIZE, 0x04, 0x01, USB_CONFIG_BUS_POWERED, 100), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, 64, 0x02), MSC_DESCRIPTOR_INIT(0x02, MSC_OUT_EP, MSC_IN_EP, 64, 0x02), HID_MOUSE_DESCRIPTOR_INIT(0x03, 0x01, HID_MOUSE_REPORT_DESC_SIZE, HID_INT_EP, 4, 10), }; void composite_init(uint8_t busid, uintptr_t reg_base) { usbd_desc_register(busid, &composite_descriptor); /* CDC ACM (needs 2 interfaces: comm + data) */ usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &cdc_comm)); usbd_add_interface(busid, usbd_cdc_acm_init_intf(busid, &cdc_data)); usbd_add_endpoint(busid, &cdc_out_ep); usbd_add_endpoint(busid, &cdc_in_ep); /* MSC */ usbd_add_interface(busid, usbd_msc_init_intf(busid, &msc_intf, MSC_OUT_EP, MSC_IN_EP)); /* HID mouse */ usbd_add_interface(busid, usbd_hid_init_intf(busid, &hid_intf, hid_mouse_report_desc, HID_MOUSE_REPORT_DESC_SIZE)); usbd_add_endpoint(busid, &hid_ep); usbd_initialize(busid, reg_base, usbd_event_handler); } ``` -------------------------------- ### Initialize ADB Device Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbd_adb.md Call this function to initialize the ADB device. Ensure the correct parameters are provided based on your platform. ```c cherryadb_init(0, xxxxx); ``` -------------------------------- ### Audio Initialization Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Initializes the USB Audio class interface and sets up handlers for class-specific requests and notifications. ```APIDOC ## usbd_audio_init_intf ### Description Initializes the USB Audio class interface and implements related functions for this interface. - `audio_class_interface_request_handler` handles USB Audio Setup interface recipient interrupt requests. - `audio_class_endpoint_request_handler` handles USB Audio Setup endpoint recipient interrupt requests. - `audio_notify_handler` implements other USB Audio interrupt callback functions. ### Function Signature ```C struct usbd_interface *usbd_audio_init_intf(uint8_t busid, struct usbd_interface *intf, uint16_t uac_version, struct audio_entity_info *table, uint8_t num); ``` ### Parameters - **busid** (uint8_t) - USB bus ID - **intf** (struct usbd_interface *) - Interface handle - **uac_version** (uint16_t) - Audio class version, UAC1.0 or UAC2.0 - **table** (struct audio_entity_info *) - Audio entity information table - **num** (uint8_t) - Audio entity information table length ``` -------------------------------- ### Initialize USB Host Stack and Event Handler Source: https://context7.com/cherry-embedded/cherryusb/llms.txt Initializes the USB host stack and sets up an event handler for device connection/disconnection and interface events. Class drivers are loaded automatically upon device connection. ```c #include "usbh_core.h" #include "usbh_msc.h" #include "usbh_hid.h" #include "usbh_serial.h" /* Event handler fires for device connect/disconnect and interface events */ void usbh_event_handler(uint8_t busid, uint8_t hub_index, uint8_t hub_port, uint8_t intf, uint8_t event) { switch (event) { case USBH_EVENT_DEVICE_CONNECTED: USB_LOG_INFO("Device connected on bus %d hub %d port %d\r\n", busid, hub_index, hub_port); break; case USBH_EVENT_DEVICE_DISCONNECTED: USB_LOG_INFO("Device disconnected\r\n"); break; case USBH_EVENT_INTERFACE_START: USB_LOG_INFO("Interface %d driver started\r\n", intf); break; default: break; } } void app_host_init(void) { int ret = usbh_initialize(0, USB_HOST_BASE /* reg base */, usbh_event_handler); /* ret == 0 on success */ /* Hub thread now running; devices can be connected */ } ``` -------------------------------- ### Register CherryUSB Host Component Source: https://github.com/cherry-embedded/cherryusb/blob/master/tests/espressif/host/main/CMakeLists.txt Use this command to register the CherryUSB host component, specifying source files, include directories, and build options. Ensure 'main.c' is listed as a source file and '.' is added to include directories. ```cmake idf_component_register(SRCS "main.c" INCLUDE_DIRS "." WHOLE_ARCHIVE) ``` -------------------------------- ### MSC Sector Write Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Writes data to the storage device starting at a specified sector address. ```APIDOC ## usbd_msc_sector_write ### Description Writes data to a storage device starting at a specific sector. Users must implement this function. ### Function Signature ```C int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length); ``` ### Parameters - **busid** (uint8_t) - USB bus ID - **lun** (uint8_t) - Storage logical unit, currently unused, defaults to supporting one - **sector** (uint32_t) - Sector offset - **buffer** (uint8_t *) - Write data pointer - **length** (uint32_t) - Write length ### Return Value Returns 0 on success, non-zero on failure. ``` -------------------------------- ### MSC Sector Read Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Reads data from the storage device starting at a specified sector address. ```APIDOC ## usbd_msc_sector_read ### Description Reads data from a storage device starting at a specific sector address. Users must implement this function. ### Function Signature ```C int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length); ``` ### Parameters - **busid** (uint8_t) - USB bus ID - **lun** (uint8_t) - Storage logical unit, currently unused, defaults to supporting one - **sector** (uint32_t) - Sector offset - **buffer** (uint8_t *) - Pointer to store read data - **length** (uint32_t) - Read length ### Return Value Returns 0 on success, non-zero on failure. ``` -------------------------------- ### Write Sector to MSC Device Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Writes data to the storage device starting at a specified sector. This function must be implemented by the user. ```C int usbd_msc_sector_write(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length); ``` -------------------------------- ### HID Initialization Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Initializes the USB HID class interface and sets up handlers for class requests and notifications. ```APIDOC ## usbd_hid_init_intf ### Description Initializes the USB HID class interface and implements related functions for this interface. - `hid_class_interface_request_handler` handles USB HID class Setup requests. - `hid_notify_handler` handles other USB HID interrupt callback functions. ### Function Signature ```C struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len); ``` ### Parameters - **busid** (uint8_t) - USB bus ID - **intf** (struct usbd_interface *) - Interface handle - **desc** (const uint8_t *) - Report descriptor - **desc_len** (uint32_t) - Report descriptor length ``` -------------------------------- ### Read Sector from MSC Device Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Reads data from the storage device starting at a specified sector. This function must be implemented by the user. ```C int usbd_msc_sector_read(uint8_t busid, uint8_t lun, uint32_t sector, uint8_t *buffer, uint32_t length); ``` -------------------------------- ### Handle USB Host Interrupt Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/demo.md Call USBH_IRQHandler in the interrupt function and pass in the bus ID. This step is no longer needed starting from V1.5.0. ```c /* Call USBH_IRQHandler in interrupt function and pass in busid */ ``` -------------------------------- ### usbd_initialize — Initialize the USB device stack Source: https://context7.com/cherry-embedded/cherryusb/llms.txt Initializes the USB device stack by registering IRQ callbacks, configuring the device controller hardware, and initiating the enumeration process. This function must be called after all necessary descriptors, interfaces, and endpoints have been registered. ```APIDOC ## usbd_initialize — Initialize the USB device stack ### Description Registers IRQ callbacks, initializes the device controller hardware, and starts enumeration processing. Must be called after `usbd_desc_register`, `usbd_add_interface`, and `usbd_add_endpoint`. ### Method ```c int usbd_initialize(uint8_t busid, uint32_t reg_base, usbd_event_handler_t handler) ``` ### Parameters #### Path Parameters - **busid** (uint8_t) - The bus identifier for the USB device. - **reg_base** (uint32_t) - The base address of the USB device controller hardware registers. - **handler** (usbd_event_handler_t) - A callback function to handle USB events. ### Request Example ```c #include "usbd_core.h" #include "usbd_cdc_acm.h" #define CDC_IN_EP 0x81 #define CDC_OUT_EP 0x02 #define CDC_INT_EP 0x83 #define CDC_MAX_MPS 64 /* 512 for HS */ /* USB descriptors */ static const uint8_t device_descriptor[] = { USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, 0xFFFF, 0xFFFF, 0x0100, 0x01) }; static const uint8_t config_descriptor[] = { USB_CONFIG_DESCRIPTOR_INIT(9 + CDC_ACM_DESCRIPTOR_LEN, 0x02, 0x01, USB_CONFIG_BUS_POWERED, 100), CDC_ACM_DESCRIPTOR_INIT(0x00, CDC_INT_EP, CDC_OUT_EP, CDC_IN_EP, CDC_MAX_MPS, 0x02) }; static const char *string_descriptors[] = { (const char[]){ 0x09, 0x04 }, /* LangID: English */ "MyCompany", /* Manufacturer */ "CDC ACM Device", /* Product */ "000001", /* Serial */ }; static const uint8_t *dev_desc_cb(uint8_t speed) { return device_descriptor; } static const uint8_t *cfg_desc_cb(uint8_t speed) { return config_descriptor; } static const uint8_t *qual_desc_cb(uint8_t speed) { return NULL; } static const char *str_desc_cb(uint8_t speed, uint8_t idx) { if (idx >= sizeof(string_descriptors) / sizeof(char *)) return NULL; return string_descriptors[idx]; } const struct usb_descriptor cdc_desc = { .device_descriptor_callback = dev_desc_cb, .config_descriptor_callback = cfg_desc_cb, .device_quality_descriptor_callback = qual_desc_cb, .string_descriptor_callback = str_desc_cb }; static struct usbd_interface intf0, intf1; static void usbd_event_handler(uint8_t busid, uint8_t event) { if (event == USBD_EVENT_CONFIGURED) usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, sizeof(read_buffer)); } /* Call once at startup, passing the hardware register base address */ void app_usb_init(void) { usbd_desc_register(0, &cdc_desc); usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf0)); usbd_add_interface(0, usbd_cdc_acm_init_intf(0, &intf1)); usbd_add_endpoint(0, &(struct usbd_endpoint){ .ep_addr = CDC_OUT_EP, .ep_cb = cdc_bulk_out }); usbd_add_endpoint(0, &(struct usbd_endpoint){ .ep_addr = CDC_IN_EP, .ep_cb = cdc_bulk_in }); int ret = usbd_initialize(0, USB_BASE /* reg base */, usbd_event_handler); /* ret == 0 on success */ } ``` ### Response #### Success Response (0) Returns 0 on successful initialization. #### Error Response (-1) Returns -1 on failure. ``` -------------------------------- ### Handle USB Device Interrupt Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/demo.md Call USBD_IRQHandler in the interrupt function and pass in the bus ID. This step is no longer needed starting from V1.5.0. ```c /* Call USBD_IRQHandler in interrupt function and pass in busid */ ``` -------------------------------- ### Initialize USB Host Protocol Stack Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_host.md Initializes the USB host protocol stack. Requires bus ID, register base address, and an optional event handler. ```c int usbh_initialize(uint8_t busid, uint32_t reg_base, usbh_event_handler_t event_handler); ``` -------------------------------- ### Initialize and Stream UVC Device Source: https://context7.com/cherry-embedded/cherryusb/llms.txt Initializes a UVC device and sets up a loop to continuously capture and stream video frames. Ensure `capture_frame` is implemented and `streaming` and `frame_done` logic is handled correctly. ```c #include "usbd_core.h" #include "usbd_video.h" #define VIDEO_IN_EP 0x81 #define WIDTH 640 #define HEIGHT 480 #define CAM_FPS 30 #define INTERVAL (10000000 / CAM_FPS) /* 100-ns units */ #define MAX_FRAME_SIZE (WIDTH * HEIGHT * 2) #define MAX_PAYLOAD_SIZE 1024 /* must match descriptor */ struct usbd_interface vc_intf, vs_intf; volatile bool streaming = false; volatile bool frame_done = true; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buf[MAX_PAYLOAD_SIZE]; USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t frame_buf[MAX_FRAME_SIZE]; /* Callbacks called by the device class */ void usbd_video_open(uint8_t busid, uint8_t intf) { streaming = true; } void usbd_video_close(uint8_t busid, uint8_t intf) { streaming = false; } void usbd_video_iso_cb(uint8_t busid, uint8_t ep, uint32_t nbytes) { if (usbd_video_stream_split_transfer(busid, ep)) frame_done = true; /* whole frame sent */ } static struct usbd_endpoint video_ep = { .ep_addr = VIDEO_IN_EP, .ep_cb = usbd_video_iso_cb }; void video_init(uint8_t busid, uintptr_t reg_base) { usbd_desc_register(busid, &video_descriptor); usbd_add_interface(busid, usbd_video_init_intf(busid, &vc_intf, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE)); usbd_add_interface(busid, usbd_video_init_intf(busid, &vs_intf, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE)); usbd_add_endpoint(busid, &video_ep); usbd_initialize(busid, reg_base, usbd_event_handler); } void video_loop(uint8_t busid) { while (1) { if (streaming && frame_done) { capture_frame(frame_buf, sizeof(frame_buf)); /* user-provided */ frame_done = false; /* do_copy=false → zero-copy; frame_buf must stay valid until frame_done */ usbd_video_stream_start_write(busid, VIDEO_IN_EP, packet_buf, frame_buf, MAX_FRAME_SIZE, false); } } } ``` -------------------------------- ### CherryUSB Stack-Wide Configuration Options Source: https://context7.com/cherry-embedded/cherryusb/llms.txt Copy `cherryusb_config_template.h` to `usb_config.h` and adjust these settings for your specific platform. Options cover common, device, host, and EHCI configurations. ```c /* usb_config.h — typical project configuration */ #ifndef USB_CONFIG_H #define USB_CONFIG_H /* ---- Common ---- */ #define CONFIG_USB_PRINTF(...) printf(__VA_ARGS__) #define CONFIG_USB_DBG_LEVEL USB_DBG_INFO /* ERROR/WARNING/INFO/LOG */ #define CONFIG_USB_PRINTF_COLOR_ENABLE /* ANSI colors in log output */ // #define CONFIG_USB_DCACHE_ENABLE /* Enable D-cache invalidation */ #define CONFIG_USB_ALIGN_SIZE 4 /* 32 or 64 when dcache enabled */ #define USB_NOCACHE_RAM_SECTION __attribute__((section(".noncacheable"))) /* ---- Device ---- */ #define CONFIG_USBDEV_MAX_BUS 1 #define CONFIG_USBDEV_REQUEST_BUFFER_LEN 512 #define CONFIG_USBDEV_MSC_MAX_LUN 1 #define CONFIG_USBDEV_MSC_MAX_BUFSIZE 512 // #define CONFIG_USBDEV_MSC_POLLING /* Move MSC I/O to while(1) */ // #define CONFIG_USB_DWC2_DMA_ENABLE /* DWC2 buffer DMA mode */ /* ---- Host ---- */ #define CONFIG_USBHOST_MAX_BUS 1 #define CONFIG_USBHOST_MAX_RHPORTS 1 #define CONFIG_USBHOST_MAX_EXTHUBS 1 #define CONFIG_USBHOST_MAX_EHPORTS 4 #define CONFIG_USBHOST_MAX_INTERFACES 8 #define CONFIG_USBHOST_MAX_ENDPOINTS 4 #define CONFIG_USBHOST_MAX_MSC_CLASS 2 #define CONFIG_USBHOST_MAX_HID_CLASS 4 #define CONFIG_USBHOST_MAX_SERIAL_CLASS 4 #define CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT 500 /* ms */ #define CONFIG_USBHOST_MSC_TIMEOUT 5000 /* ms */ #define CONFIG_USBHOST_PSC_PRIO 0 #define CONFIG_USBHOST_PSC_STACKSIZE 2048 /* ---- EHCI (host) ---- */ #define CONFIG_USB_EHCI_FRAME_LIST_SIZE 1024 #define CONFIG_USB_EHCI_QH_NUM 10 #define CONFIG_USB_EHCI_QTD_NUM 30 #endif /* USB_CONFIG_H */ ``` -------------------------------- ### usbd_video_init_intf Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Initializes the USB Video class interface and sets up handlers for related functions. ```APIDOC ## usbd_video_init_intf ### Description Used to initialize USB Video class interface and implement related functions for this interface. - `video_class_interface_request_handler` is used to handle USB Video Setup interrupt requests. - `video_notify_handler` is used to implement other USB Video interrupt callback functions. ### Function Signature ```c struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize); ``` ### Parameters - **busid** (uint8_t) - USB bus ID. - **intf** (struct usbd_interface *) - Interface handle. - **dwFrameInterval** (uint32_t) - Video frame interval, unit 100ns. - **dwMaxVideoFrameSize** (uint32_t) - Maximum video frame size. - **dwMaxPayloadTransferSize** (uint32_t) - Maximum payload transfer size. ``` -------------------------------- ### Initialize Endpoints Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbh_vendor.md Iterate through the interface's endpoints to initialize input and output endpoints using the USBH_EP_INIT macro. ```C for (uint8_t i = 0; i < hport->config.intf[intf].altsetting[0].intf_desc.bNumEndpoints; i++) { ep_desc = &hport->config.intf[intf].altsetting[0].ep[i].ep_desc; if (ep_desc->bEndpointAddress & 0x80) { USBH_EP_INIT(xxx_class->intin, ep_desc); } else { USBH_EP_INIT(xxx_class->intout, ep_desc); } } ``` -------------------------------- ### Get Audio Sampling Frequency Table Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Retrieve the list of supported sampling rates for the audio module. This function is specific to UAC2. If not implemented, a default list is used. ```c void usbd_audio_get_sampling_freq_table(uint8_t busid, uint8_t ep, uint8_t **sampling_freq_table); ``` -------------------------------- ### Configure CherryUSB for Bouffalo SDK Source: https://github.com/cherry-embedded/cherryusb/blob/master/CMakeLists.txt Enables various CherryUSB device and host functionalities when building for the Bouffalo SDK. Includes setting up OSAL and including the main CherryUSB CMake file. ```cmake if(BL_SDK_BASE) message(STATUS "enable cherryusb in bouffalo_sdk") set(CONFIG_CHERRYUSB_DEVICE_CDC_ACM 1) set(CONFIG_CHERRYUSB_DEVICE_HID 1) set(CONFIG_CHERRYUSB_DEVICE_MSC 1) set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1) set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1) set(CONFIG_CHERRYUSB_DEVICE_DFU 1) set(CONFIG_CHERRYUSB_DEVICE_GAMEPAD 1) set(CONFIG_CHERRYUSB_HOST_CDC_ACM 1) set(CONFIG_CHERRYUSB_HOST_CDC_ECM 1) set(CONFIG_CHERRYUSB_HOST_CDC_NCM 1) set(CONFIG_CHERRYUSB_HOST_HID 1) set(CONFIG_CHERRYUSB_HOST_MSC 1) set(CONFIG_CHERRYUSB_HOST_VIDEO 1) set(CONFIG_CHERRYUSB_HOST_AUDIO 1) set(CONFIG_CHERRYUSB_HOST_CDC_RNDIS 1) # set(CONFIG_CHERRYUSB_HOST_BLUETOOTH 1) set(CONFIG_CHERRYUSB_HOST_ASIX 1) set(CONFIG_CHERRYUSB_HOST_RTL8152 1) set(CONFIG_CHERRYUSB_HOST_CH34X 1) set(CONFIG_CHERRYUSB_HOST_CP210X 1) set(CONFIG_CHERRYUSB_HOST_FTDI 1) set(CONFIG_CHERRYUSB_HOST_PL2303 1) set(CONFIG_CHERRYUSB_HOST_GSM 1) set(CONFIG_CHERRYUSB_DEVICE_BL 1) set(CONFIG_CHERRYUSB_HOST_EHCI_BL 1) set(CONFIG_CHERRYUSB_OSAL "freertos") include(${CMAKE_CURRENT_LIST_DIR}/cherryusb.cmake) list(REMOVE_DUPLICATES cherryusb_srcs) list(REMOVE_DUPLICATES cherryusb_incs) sdk_generate_library(cherryusb) sdk_add_include_directories(${cherryusb_incs}) sdk_library_add_sources(${cherryusb_srcs}) ``` -------------------------------- ### Initialize USB HID Interface Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Initializes the USB HID class interface. Requires a report descriptor to define the HID device's capabilities. ```C struct usbd_interface *usbd_hid_init_intf(uint8_t busid, struct usbd_interface *intf, const uint8_t *desc, uint32_t desc_len); ``` -------------------------------- ### Get CDC ACM Serial Port Settings Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Retrieves the current serial port configuration for the CDC ACM interface. This function can be omitted if not using a serial port. ```C void usbd_cdc_acm_get_line_coding(uint8_t busid, uint8_t intf, struct cdc_line_coding *line_coding); ``` -------------------------------- ### LWIP Configuration Macro Checks Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbh_net.md Verifies essential LWIP configuration macros to ensure optimal performance and prevent issues like stack overflow or buffer problems when using the USB network card driver. ```C #if LWIP_TCPIP_CORE_LOCKING_INPUT != 1 #warning suggest you to set LWIP_TCPIP_CORE_LOCKING_INPUT to 1, usb handles eth input with own thread #endif #if LWIP_TCPIP_CORE_LOCKING != 1 #error must set LWIP_TCPIP_CORE_LOCKING to 1 #endif #if PBUF_POOL_BUFSIZE < 1600 #error PBUF_POOL_BUFSIZE must be larger than 1600 #endif #if TCPIP_THREAD_STACKSIZE < 1024 #error TCPIP_THREAD_STACKSIZE must be >= 1024 #endif ``` -------------------------------- ### DWC2 User Parameters Configuration Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/quick_start/migration.md Implement custom configurations for multiple DWC2 ports starting from v1.5.1. This function replaces older configuration functions and allows for custom FIFO settings. ```c #ifndef CONFIG_USB_DWC2_CUSTOM_PARAM void dwc2_get_user_params(uint32_t reg_base, struct dwc2_user_params *params) { memcpy(params, ¶m_common, sizeof(struct dwc2_user_params)); #ifdef CONFIG_USB_DWC2_CUSTOM_FIFO struct usb_dwc2_user_fifo_config s_dwc2_fifo_config; dwc2_get_user_fifo_config(reg_base, &s_dwc2_fifo_config); params->device_rx_fifo_size = s_dwc2_fifo_config.device_rx_fifo_size; for (uint8_t i = 0; i < MAX_EPS_CHANNELS; i++) { params->device_tx_fifo_size[i] = s_dwc2_fifo_config.device_tx_fifo_size[i]; } #endif } #endif ``` -------------------------------- ### Define USB Host Class Driver and Info Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbh_vendor.md Define the class driver structure and its information using CLASS_INFO_DEFINE. This allows the protocol stack to find the driver automatically after enumeration. ```C static const struct usbh_class_driver xxx_class_driver = { .driver_name = "xxx", .connect = usbh_xxx_connect, .disconnect = usbh_xxx_disconnect }; CLASS_INFO_DEFINE const struct usbh_class_info xxx_class_info = { .match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL, .bInterfaceClass = 0, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, .id_table = NULL, .class_driver = &xxx_class_driver }; ``` -------------------------------- ### USBD Event Handler for CDC ACM Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbd_cdc_acm.md Handles USB device events. Initiates the first out endpoint read transfer after the device is configured. Ensure `ep_tx_busy_flag` is reset before starting the read. ```c static void usbd_event_handler(uint8_t busid, uint8_t event) { switch (event) { case USBD_EVENT_RESET: break; case USBD_EVENT_CONNECTED: break; case USBD_EVENT_DISCONNECTED: break; case USBD_EVENT_RESUME: break; case USBD_EVENT_SUSPEND: break; case USBD_EVENT_CONFIGURED: ep_tx_busy_flag = false; /* setup first out ep read transfer */ usbd_ep_start_read(busid, CDC_OUT_EP, read_buffer, 2048); break; case USBD_EVENT_SET_REMOTE_WAKEUP: break; case USBD_EVENT_CLR_REMOTE_WAKEUP: break; default: break; } } ``` -------------------------------- ### USB Host MSC SCSI Initialize Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_host.md `usbh_msc_scsi_init` initializes the MSC SCSI device, retrieving status and capacity information. ```APIDOC ## usbh_msc_scsi_init ### Description Initializes the MSC SCSI device. Gets MSC status and capacity information. ### Signature ```C int usbh_msc_scsi_init(struct usbh_msc *msc_class); ``` ### Parameters - **msc_class** (struct usbh_msc *) - msc structure handle ### Return Value - (int) 0 indicates normal, other values indicate error ``` -------------------------------- ### Get MSC Device Capabilities Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_device.md Retrieves the Logical Unit Number (LUN), total number of sectors, and sector size for the connected storage device. This function must be implemented by the user. ```C void usbd_msc_get_cap(uint8_t busid, uint8_t lun, uint32_t *block_num, uint16_t *block_size); ``` -------------------------------- ### usbh_initialize Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_host.md Initializes the USB host protocol stack, including the host controller, roothub device, and hub detection thread. ```APIDOC ## usbh_initialize ### Description Initializes the USB host protocol stack, including: initializing the USB host controller, creating roothub device, creating hub detection thread. ### Function Signature ```c int usbh_initialize(uint8_t busid, uint32_t reg_base, usbh_event_handler_t event_handler); ``` ### Parameters - **busid** (uint8_t) - Required - bus id, starting from 0, cannot exceed CONFIG_USBHOST_MAX_BUS - **reg_base** (uint32_t) - Required - hcd register base address - **event_handler** (usbh_event_handler_t) - Optional - host event callback function, can be NULL ### Return Value - **int** - 0 indicates normal, other values indicate error ``` -------------------------------- ### usbd_ep_start_read Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/api/api_port.md `usbd_ep_start_read` starts endpoint reception. After reception completion, it will call the registered OUT endpoint transfer completion interrupt callback function. This function performs asynchronous reception. This function is open to users. ```APIDOC ## usbd_ep_start_read ### Description Starts an OUT endpoint reception asynchronously. A callback function is invoked upon completion. ### Method `int usbd_ep_start_read(const uint8_t ep, uint8_t *data, uint32_t data_len)` ### Parameters #### Path Parameters - **ep** (uint8_t) - Required - OUT endpoint address - **data** (uint8_t *) - Required - Buffer to store received data - **data_len** (uint32_t) - Required - Length of data to receive. Recommended within 16K bytes and preferably a multiple of the maximum packet size. ### Return Value - Returns 0 for success, other values indicate error ### Notes Transfer completion interrupt is triggered when the last packet is a short packet or the total received length equals `data_len`. ``` -------------------------------- ### Implement Connect and Disconnect Functions Source: https://github.com/cherry-embedded/cherryusb/blob/master/docs/en/demo/usbh_vendor.md Implement the connect function to allocate the class structure and the disconnect function to release resources like URBs and the class structure. ```C struct usbh_xxx { struct usbh_hubport *hport; struct usb_endpoint_descriptor *xxxin; struct usb_endpoint_descriptor *xxxout; struct usbh_urb xxxin_urb; struct usbh_urb xxxout_urb; uint8_t intf; /* interface number */ uint8_t minor; void *user_data; }; static int usbh_xxx_connect(struct usbh_hubport *hport, uint8_t intf) { struct usb_endpoint_descriptor *ep_desc; int ret; struct usbh_xxx *xxx_class = usbh_xxx_class_alloc(); if (xxx_class == NULL) { USB_LOG_ERR("Fail to alloc xxx_class\r\n"); return -USB_ERR_NOMEM; } return ret; } static int usbh_xxx_disconnect(struct usbh_hubport *hport, uint8_t intf) { int ret = 0; struct usbh_xxx *xxx_class = (struct usbh_xxx *)hport->config.intf[intf].priv; if (xxx_class) { if (xxx_class->xxxin) { usbh_kill_urb(&xxx_class->xxxin_urb); } if (xxx_class->xxxout) { usbh_kill_urb(&xxx_class->xxxout_urb); } if (hport->config.intf[intf].devname[0] != '\0') { USB_LOG_INFO("Unregister xxx Class:%s\r\n", hport->config.intf[intf].devname); usbh_xxx_stop(xxx_class); } usbh_xxx_class_free(xxx_class); } return ret; } ```