From ce70f2466f775b5975161b7ebc79771a059a6090 Mon Sep 17 00:00:00 2001 From: "igor.masar" Date: Fri, 5 Sep 2025 13:51:15 +0200 Subject: [PATCH] feat(usb): Add ESP32-H4 support in tinyusb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add ESP32-H4 as a supported MCU in TinyUSB and wire it into build/runtime: - CMakeLists: map IDF target esp32h4 → OPT_MCU_ESP32H4, family=esp32sx - tusb_option.h: define OPT_MCU_ESP32H4 - tusb_mcu.h: enable DWC2 USBIP for H4 - dcd_dwc2.c: add H4 USB_WRAP field aliases (wrap_* → legacy names) - dwc2_esp32.h: add H4 controller entry (FS base/IRQ, ep caps) - family.c: include H4 in USB init/PHY setup - idf_component.yml: add esp32h4 target This enables TinyUSB examples to build for ESP32-H4. --- CMakeLists.txt | 3 +++ README.rst | 2 ++ hw/bsp/espressif/boards/family.c | 6 +++--- idf_component.yml | 1 + src/common/tusb_mcu.h | 2 +- src/portable/synopsys/dwc2/dwc2_esp32.h | 17 +++++++++++++++++ src/tusb_option.h | 1 + 7 files changed, 28 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a8599ef6dd..9ac96367fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,9 @@ elseif(${target} STREQUAL "esp32s2") elseif(${target} STREQUAL "esp32p4") set(tusb_mcu "OPT_MCU_ESP32P4") set(tusb_family "esp32px") +elseif(${target} STREQUAL "esp32h4") + set(tusb_mcu "OPT_MCU_ESP32H4") + set(tusb_family "esp32sx") endif() set(compile_options diff --git a/README.rst b/README.rst index efbfa354ba..40b9956267 100644 --- a/README.rst +++ b/README.rst @@ -118,6 +118,8 @@ Supported CPUs | Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 or esp32sx | | | ESP32 +-----------------------------+--------+------+-----------+------------------------+-------------------+ | | P4 | ✔ | ✔ | ✔ | dwc2 | | +| +-----------------------------+--------+------+-----------+------------------------+-------------------+ +| | H4 | ✔ | ✔ | ✖ | dwc2 | | +--------------+----+------------------------+--------+------+-----------+------------------------+-------------------+ | GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | | +--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+ diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 7049c04157..993212bf79 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -88,7 +88,7 @@ void board_init(void) { gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT); gpio_set_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN_ONLY : GPIO_PULLUP_ONLY); -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4, OPT_MCU_ESP32P4) usb_init(); #endif @@ -103,7 +103,7 @@ void board_init(void) { #endif } -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4) #endif @@ -158,7 +158,7 @@ int board_getchar(void) { // PHY Init //-------------------------------------------------------------------- -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32P4) +#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4, OPT_MCU_ESP32P4) #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) #include "esp_private/usb_phy.h" diff --git a/idf_component.yml b/idf_component.yml index b038f9b71d..91ff2d29d9 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -9,3 +9,4 @@ targets: - esp32s2 - esp32s3 - esp32p4 + - esp32h4 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index a0175d664a..cdb23aa792 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -363,7 +363,7 @@ //--------------------------------------------------------------------+ // Espressif //--------------------------------------------------------------------+ -#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) +#elif TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3, OPT_MCU_ESP32H4) #define TUP_USBIP_DWC2 #define TUP_USBIP_DWC2_ESP32 #define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index 3309760ffe..8344080b4c 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -47,6 +47,23 @@ static const dwc2_controller_t _dwc2_controller[] = { { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 } }; +#elif TU_CHECK_MCU(OPT_MCU_ESP32H4) +// H4's USB_WRAP register block uses "wrap_*" field names. Map them to the +// names used by TinyUSB's DWC2 port to keep the source unchanged. +#define otg_conf wrap_otg_conf +#define pad_pull_override wrap_pad_pull_override +#define dp_pullup wrap_dp_pullup +#define dp_pulldown wrap_dp_pulldown +#define dm_pullup wrap_dm_pullup +#define dm_pulldown wrap_dm_pulldown + +#define DWC2_FS_REG_BASE 0x60040000UL +#define DWC2_EP_MAX 7 + +static const dwc2_controller_t _dwc2_controller[] = { + { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_OTG11_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 } +}; + #elif TU_CHECK_MCU(OPT_MCU_ESP32P4) #define DWC2_FS_REG_BASE 0x50040000UL #define DWC2_HS_REG_BASE 0x50000000UL diff --git a/src/tusb_option.h b/src/tusb_option.h index 29fdcb0d65..e8653ceafa 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -127,6 +127,7 @@ #define OPT_MCU_ESP32C2 905 ///< Espressif ESP32-C2 #define OPT_MCU_ESP32H2 906 ///< Espressif ESP32-H2 #define OPT_MCU_ESP32P4 907 ///< Espressif ESP32-P4 +#define OPT_MCU_ESP32H4 910 ///< Espressif ESP32-H4, 908, 909 are already used in the upstream #define TUSB_MCU_VENDOR_ESPRESSIF (CFG_TUSB_MCU >= 900 && CFG_TUSB_MCU < 1000) // check if Espressif MCU #define TUP_MCU_ESPRESSIF TUSB_MCU_VENDOR_ESPRESSIF // for backward compatibility