From 3415d3525c76d0828a75f5ba5a73cd1adb5d278a Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 1 Oct 2025 15:55:30 +0200 Subject: [PATCH 01/22] remove S3 DIO Flash add 120 OPI Flash / PSRAM --- configs/builds.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/configs/builds.json b/configs/builds.json index c0c1358cd..98013375f 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -169,14 +169,13 @@ "bootloaders":[ ["qio","120m","qio_ram"], ["qio","80m","qio_ram"], - ["dio","80m","qio_ram"], - ["opi","80m","opi_ram"] + ["opi","80m","opi_ram"], + ["opi","120m","opi_ram"] ], "mem_variants":[ ["qio","80m","opi_ram"], - ["dio","80m","qio_ram"], - ["dio","80m","opi_ram"], - ["opi","80m","opi_ram"] + ["opi","80m","opi_ram"], + ["opi","120m","opi_ram"] ] } ] From 2b10a150f261d6b46741aa5ba68f9756a053d82c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 2 Oct 2025 21:21:48 +0200 Subject: [PATCH 02/22] Comment out CONFIG_LIBC_LOCKS_PLACE_IN_IRAM --- configs/defconfig.common | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/defconfig.common b/configs/defconfig.common index b1333cd37..5e78df96a 100644 --- a/configs/defconfig.common +++ b/configs/defconfig.common @@ -43,6 +43,7 @@ CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=0 # CONFIG_SPIRAM_BANKSWITCH_ENABLE is not set +# CONFIG_LIBC_LOCKS_PLACE_IN_IRAM is not set CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH=y CONFIG_RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH=y CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM=y From e16765e0ffce44a8f74cdf5ad2199e800e74434c Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 5 Oct 2025 19:35:51 +0200 Subject: [PATCH 03/22] Update SPI flash configuration in defconfig Change SPI flash configuration options for HPM. --- configs/defconfig.120m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/defconfig.120m b/configs/defconfig.120m index baadadcfb..87338c1e7 100644 --- a/configs/defconfig.120m +++ b/configs/defconfig.120m @@ -2,5 +2,6 @@ CONFIG_IDF_EXPERIMENTAL_FEATURES=y CONFIG_ESPTOOLPY_FLASHFREQ_120M=y CONFIG_SPIRAM_SPEED_120M=y CONFIG_SPIRAM_SPEED=120 -# CONFIG_SPI_FLASH_HPM_ENA=y +CONFIG_SPI_FLASH_HPM_ENABLE=y +CONFIG_SPI_FLASH_HPM_AUTO=y CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y From 50ac059f2732ae115a6f591a7014e1fd2dbc27bd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 11 Oct 2025 20:52:57 +0200 Subject: [PATCH 04/22] Rename Wi-Fi configuration parameters --- configs/defconfig.esp32p4 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/configs/defconfig.esp32p4 b/configs/defconfig.esp32p4 index 5dce4d101..22e68128a 100644 --- a/configs/defconfig.esp32p4 +++ b/configs/defconfig.esp32p4 @@ -63,13 +63,13 @@ CONFIG_ESP_WIFI_REMOTE_ENABLED=y CONFIG_ESP_WIFI_REMOTE_LIBRARY_HOSTED=y #### Add Wi-Fi Remote config for better performance: -CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=16 -CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=64 -CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=64 -CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y -CONFIG_ESP_WIFI_TX_BA_WIN=32 -CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y -CONFIG_ESP_WIFI_RX_BA_WIN=32 +CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=16 +CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=64 +CONFIG_WIFI_RMT_DYNAMIC_TX_BUFFER_NUM=64 +CONFIG_WIFI_RMT_AMPDU_TX_ENABLED=y +CONFIG_WIFI_RMT_TX_BA_WIN=32 +CONFIG_WIFI_RMT_AMPDU_RX_ENABLED=y +CONFIG_WIFI_RMT_RX_BA_WIN=32 CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534 CONFIG_LWIP_TCP_WND_DEFAULT=65534 From ed192312fe54646fd669d2373da269cd026a8433 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 23 Oct 2025 19:54:03 +0200 Subject: [PATCH 05/22] Disable itwt --- configs/defconfig.esp32p4 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configs/defconfig.esp32p4 b/configs/defconfig.esp32p4 index 22e68128a..7314b2646 100644 --- a/configs/defconfig.esp32p4 +++ b/configs/defconfig.esp32p4 @@ -31,6 +31,8 @@ CONFIG_CACHE_L2_CACHE_LINE_128B=y # RGB Display Optimizations CONFIG_LCD_RGB_ISR_IRAM_SAFE=y +# ESP_HOSTED_ENABLE_ITWT is not set +# ESP_HOSTED_ENABLE_DPP is not set CONFIG_SLAVE_IDF_TARGET_ESP32C6=y CONFIG_ESP_SDIO_BUS_WIDTH=4 CONFIG_ESP_SDIO_CLOCK_FREQ_KHZ=40000 From 338827e3b1c5027321a3404cee617669532a916f Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Thu, 23 Oct 2025 20:48:40 +0200 Subject: [PATCH 06/22] Update defconfig.esp32p4 --- configs/defconfig.esp32p4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/defconfig.esp32p4 b/configs/defconfig.esp32p4 index 7314b2646..ab8ba466a 100644 --- a/configs/defconfig.esp32p4 +++ b/configs/defconfig.esp32p4 @@ -31,8 +31,8 @@ CONFIG_CACHE_L2_CACHE_LINE_128B=y # RGB Display Optimizations CONFIG_LCD_RGB_ISR_IRAM_SAFE=y -# ESP_HOSTED_ENABLE_ITWT is not set -# ESP_HOSTED_ENABLE_DPP is not set +# CONFIG_ESP_HOSTED_ENABLE_ITWT is not set +# CONFIG_ESP_HOSTED_ENABLE_DPP is not set CONFIG_SLAVE_IDF_TARGET_ESP32C6=y CONFIG_ESP_SDIO_BUS_WIDTH=4 CONFIG_ESP_SDIO_CLOCK_FREQ_KHZ=40000 From f43e117b714e0906b30cc7ca369ad7d22ecba59b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sun, 26 Oct 2025 14:17:09 +0100 Subject: [PATCH 07/22] Add default TCP send buffer configuration --- configs/defconfig.common | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/defconfig.common b/configs/defconfig.common index 5e78df96a..2a4b28964 100644 --- a/configs/defconfig.common +++ b/configs/defconfig.common @@ -89,6 +89,7 @@ CONFIG_LWIP_IPV6_AUTOCONFIG=y CONFIG_LWIP_IPV6_RDNSS_MAX_DNS_SERVERS=2 CONFIG_LWIP_TCP_SYNMAXRTX=6 CONFIG_LWIP_TCP_MSS=1436 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 CONFIG_LWIP_TCP_RTO_TIME=3000 CONFIG_LWIP_TCP_SACK_OUT=y CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 From 599a53f10dbbc47d41465f650887586edcda7bcd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Wed, 5 Nov 2025 12:40:19 +0100 Subject: [PATCH 08/22] Enable host configuration options in tusb_config.h --- .../arduino_tinyusb/include/tusb_config.h | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/components/arduino_tinyusb/include/tusb_config.h b/components/arduino_tinyusb/include/tusb_config.h index 7d628d3e7..c64768391 100755 --- a/components/arduino_tinyusb/include/tusb_config.h +++ b/components/arduino_tinyusb/include/tusb_config.h @@ -76,6 +76,10 @@ extern "C" { # define CONFIG_TINYUSB_NCM_ENABLED 0 #endif +#if CONFIG_TINYUSB_ENABLED +# define CFG_TUD_ENABLED 1 +#endif + /* */ /* COMMON CONFIGURATION */ /* */ @@ -162,6 +166,27 @@ extern "C" { #define CFG_TUD_VENDOR_RX_BUFSIZE CONFIG_TINYUSB_VENDOR_RX_BUFSIZE #define CFG_TUD_VENDOR_TX_BUFSIZE CONFIG_TINYUSB_VENDOR_TX_BUFSIZE +/* */ +/* HOST CONFIGURATION */ +/* */ + +#define CFG_TUH_ENABLED CFG_TUD_ENABLED +#define CFG_TUSB_RHPORT1_MODE OPT_MODE_HOST +#define BOARD_TUH_RHPORT 1 +#define BOARD_TUH_MAX_SPEED CFG_TUD_MAX_SPEED +#define CFG_TUH_ENUMERATION_BUFSIZE 256 + +#define CFG_TUH_HUB 2 // number of supported hubs +#define CFG_TUH_CDC 1 // CDC ACM +#define CFG_TUH_CDC_FTDI 1 // FTDI Serial. FTDI is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_CP210X 1 // CP210x Serial. CP210X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_CDC_CH34X 1 // CH340 or CH341 Serial. CH34X is not part of CDC class, only to re-use CDC driver API +#define CFG_TUH_HID 1 // typical keyboard + mouse device can have 3-4 HID interfaces +#define CFG_TUH_MSC 1 +//#define CFG_TUH_VENDOR 3 + +#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) + //------------- HID -------------// #define CFG_TUH_HID_EPIN_BUFSIZE 64 #define CFG_TUH_HID_EPOUT_BUFSIZE 64 From 131efded651fd3d77df67fad1ba2959a8daa340e Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 8 Nov 2025 21:33:38 +0100 Subject: [PATCH 09/22] Clean up CMakeLists.txt by removing comments Removed commented out espressif source file from srcs. --- components/arduino_tinyusb/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/components/arduino_tinyusb/CMakeLists.txt b/components/arduino_tinyusb/CMakeLists.txt index 242b0ef17..0d1fe9fb7 100755 --- a/components/arduino_tinyusb/CMakeLists.txt +++ b/components/arduino_tinyusb/CMakeLists.txt @@ -24,8 +24,6 @@ if(CONFIG_TINYUSB_ENABLED) endif() set(srcs - # espressif: - #"${COMPONENT_DIR}/src/dcd_dwc2.c" # tusb: "${COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c" "${COMPONENT_DIR}/tinyusb/src/portable/synopsys/dwc2/dwc2_common.c" From 5448af77cc7c25fe7fc38cc7829176c92388b650 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 8 Nov 2025 21:33:52 +0100 Subject: [PATCH 10/22] Delete components/arduino_tinyusb/patches/dcd_dwc2.patch --- .../arduino_tinyusb/patches/dcd_dwc2.patch | 84 ------------------- 1 file changed, 84 deletions(-) delete mode 100755 components/arduino_tinyusb/patches/dcd_dwc2.patch diff --git a/components/arduino_tinyusb/patches/dcd_dwc2.patch b/components/arduino_tinyusb/patches/dcd_dwc2.patch deleted file mode 100755 index 2521a38e5..000000000 --- a/components/arduino_tinyusb/patches/dcd_dwc2.patch +++ /dev/null @@ -1,84 +0,0 @@ ---- a/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:17:40.000000000 +0300 -+++ b/components/arduino_tinyusb/src/dcd_dwc2.c 2024-10-02 12:19:48.000000000 +0300 -@@ -243,6 +243,17 @@ - //-------------------------------------------------------------------- - // Endpoint - //-------------------------------------------------------------------- -+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+// Keep count of how many FIFOs are in use -+static uint8_t _allocated_fifos = 1; //FIFO0 is always in use -+ -+// Will either return an unused FIFO number, or 0 if all are used. -+static uint8_t get_free_fifo(void) { -+ if (_allocated_fifos < 5) return _allocated_fifos++; -+ return 0; -+} -+#endif -+ - static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint_desc) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); -@@ -266,7 +277,18 @@ - depctl.set_data0_iso_even = 1; - } - if (dir == TUSB_DIR_IN) { -- depctl.tx_fifo_num = epnum; -+ //depctl.tx_fifo_num = epnum; -+ uint8_t fifo_num = epnum; -+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ // Special Case for EP5, which is used by CDC but not actually called by the driver -+ // we can give it a fake FIFO -+ if (epnum == 5) { -+ fifo_num = epnum; -+ } else { -+ fifo_num = get_free_fifo(); -+ } -+#endif -+ depctl.tx_fifo_num = fifo_num; - } - - dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; -@@ -557,6 +579,10 @@ - } - } - -+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ _allocated_fifos = 1; -+#endif -+ - dfifo_flush_tx(dwc2, 0x10); // all tx fifo - dfifo_flush_rx(dwc2); - -@@ -997,6 +1023,9 @@ - if (gintsts & GINTSTS_USBRST) { - // USBRST is start of reset. - dwc2->gintsts = GINTSTS_USBRST; -+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ _allocated_fifos = 1; -+#endif - - usbd_spin_lock(true); - handle_bus_reset(rhport); -@@ -1008,7 +1037,11 @@ - - if (gintsts & GINTSTS_USBSUSP) { - dwc2->gintsts = GINTSTS_USBSUSP; -- dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); -+ //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); -+ dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ _allocated_fifos = 1; -+#endif - } - - if (gintsts & GINTSTS_WKUINT) { -@@ -1025,6 +1058,9 @@ - - if (otg_int & GOTGINT_SEDET) { - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -+#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -+ _allocated_fifos = 1; -+#endif - } - - dwc2->gotgint = otg_int; From 02f98056858f6a1f1a8027764f5dce8943a27f8d Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 8 Nov 2025 21:34:03 +0100 Subject: [PATCH 11/22] Delete components/arduino_tinyusb/src/dcd_dwc2.c --- components/arduino_tinyusb/src/dcd_dwc2.c | 1141 --------------------- 1 file changed, 1141 deletions(-) delete mode 100644 components/arduino_tinyusb/src/dcd_dwc2.c diff --git a/components/arduino_tinyusb/src/dcd_dwc2.c b/components/arduino_tinyusb/src/dcd_dwc2.c deleted file mode 100644 index b6c3b1b22..000000000 --- a/components/arduino_tinyusb/src/dcd_dwc2.c +++ /dev/null @@ -1,1141 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 William D. Jones - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * Copyright (c) 2020 Jan Duempelmann - * Copyright (c) 2020 Reinhard Panhuber - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if CFG_TUD_ENABLED && defined(TUP_USBIP_DWC2) - -#if !(CFG_TUD_DWC2_SLAVE_ENABLE || CFG_TUD_DWC2_DMA_ENABLE) -#error DWC2 require either CFG_TUD_DWC2_SLAVE_ENABLE or CFG_TUD_DWC2_DMA_ENABLE to be enabled -#endif - -// Debug level for DWC2 -#define DWC2_DEBUG 2 - -#include "device/dcd.h" -#include "device/usbd_pvt.h" -#include "dwc2_common.h" - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM -//--------------------------------------------------------------------+ -typedef struct { - uint8_t* buffer; - tu_fifo_t* ff; - uint16_t total_len; - uint16_t max_size; - uint8_t interval; -} xfer_ctl_t; - -// This variable is modified from ISR context, so it must be protected by critical section -static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; -#define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) - -typedef struct { - // EP0 transfers are limited to 1 packet - larger sizes has to be split - uint16_t ep0_pending[2]; // Index determines direction as tusb_dir_t type - uint16_t dfifo_top; // top free location in DFIFO in words - - // Number of IN endpoints active - uint8_t allocated_epin_count; - - // SOF enabling flag - required for SOF to not get disabled in ISR when SOF was enabled by - bool sof_en; -} dcd_data_t; - -static dcd_data_t _dcd_data; - -CFG_TUD_MEM_SECTION static struct { - TUD_EPBUF_DEF(setup_packet, 8); -} _dcd_usbbuf; - -TU_ATTR_ALWAYS_INLINE static inline uint8_t dwc2_ep_count(const dwc2_regs_t* dwc2) { - #if TU_CHECK_MCU(OPT_MCU_GD32VF103) - return DWC2_EP_MAX; - #else - const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; - return ghwcfg2.num_dev_ep + 1; - #endif -} - - -//-------------------------------------------------------------------- -// DMA -//-------------------------------------------------------------------- -#if CFG_TUD_MEM_DCACHE_ENABLE -bool dcd_dcache_clean(const void* addr, uint32_t data_size) { - TU_VERIFY(addr && data_size); - return dwc2_dcache_clean(addr, data_size); -} - -bool dcd_dcache_invalidate(const void* addr, uint32_t data_size) { - TU_VERIFY(addr && data_size); - return dwc2_dcache_invalidate(addr, data_size); -} - -bool dcd_dcache_clean_invalidate(const void* addr, uint32_t data_size) { - TU_VERIFY(addr && data_size); - return dwc2_dcache_clean_invalidate(addr, data_size); -} -#endif - -TU_ATTR_ALWAYS_INLINE static inline bool dma_device_enabled(const dwc2_regs_t* dwc2) { - (void) dwc2; - // Internal DMA only - const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; - return CFG_TUD_DWC2_DMA_ENABLE && ghwcfg2.arch == GHWCFG2_ARCH_INTERNAL_DMA; -} - -static void dma_setup_prepare(uint8_t rhport) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - - if (dwc2->gsnpsid >= DWC2_CORE_REV_3_00a) { - if(dwc2->epout[0].doepctl & DOEPCTL_EPENA) { - return; - } - } - - // Receive only 1 packet - dwc2->epout[0].doeptsiz = (1 << DOEPTSIZ_STUPCNT_Pos) | (1 << DOEPTSIZ_PKTCNT_Pos) | (8 << DOEPTSIZ_XFRSIZ_Pos); - dwc2->epout[0].doepdma = (uintptr_t) _dcd_usbbuf.setup_packet; - dwc2->epout[0].doepctl |= DOEPCTL_EPENA | DOEPCTL_USBAEP; -} - -//--------------------------------------------------------------------+ -// Data FIFO -//--------------------------------------------------------------------+ - - -/* Device Data FIFO scheme - - The FIFO is split up into - - EPInfo: for storing DMA metadata, only required when use DMA. Maximum size is called - EP_LOC_CNT = ep_fifo_size - ghwcfg3.dfifo_depth. For value less than EP_LOC_CNT, gdfifocfg must be configured before - gahbcfg.dmaen is set - - Buffer mode: 1 word per endpoint direction - - Scatter/Gather DMA: 4 words per endpoint direction - - TX FIFO: one fifo for each IN endpoint. Size is dynamic depending on packet size, starting from top with EP0 IN. - - Shared RX FIFO: a shared fifo for all OUT endpoints. Typically, can hold up to 2 packets of the largest EP size. - - We allocated TX FIFO from top to bottom (using top pointer), this to allow the RX FIFO to grow dynamically which is - possible since the free space is located between the RX and TX FIFOs. - - ---------------- ep_fifo_size - | DxEPIDMAn | - |-------------|-- gdfifocfg.EPINFOBASE (max is ghwcfg3.dfifo_depth) - | IN FIFO 0 | control EP - |-------------| - | IN FIFO 1 | - |-------------| - | . . . . | - |-------------| - | IN FIFO n | - |-------------| - | FREE | - |-------------|-- GRXFSIZ (expandable) - | OUT FIFO | - | ( Shared ) | - --------------- 0 - - According to "FIFO RAM allocation" section in RM, FIFO RAM are allocated as follows (each word 32-bits): - - Each EP IN needs at least max packet size - - All EP OUT shared a unique OUT FIFO which uses (for Slave or Buffer DMA, Scatt/Gather DMA use different formula): - - 13 for setup packets + control words (up to 3 setup packets). - - 1 for global NAK (not required/used here). - - Largest-EPsize/4 + 1. ( FS: 64 bytes, HS: 512 bytes). Recommended is "2 x (Largest-EPsize/4 + 1)" - - 2 for each used OUT endpoint - - Therefore GRXFSIZ = 13 + 1 + 2 x (Largest-EPsize/4 + 1) + 2 x EPOUTnum -*/ - -TU_ATTR_ALWAYS_INLINE static inline uint16_t calc_device_grxfsiz(uint16_t largest_ep_size, uint8_t ep_count) { - return 13 + 1 + 2 * ((largest_ep_size / 4) + 1) + 2 * ep_count; -} - -static bool dfifo_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t packet_size) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; - const uint8_t ep_count = dwc2_controller->ep_count; - const uint8_t epnum = tu_edpt_number(ep_addr); - const uint8_t dir = tu_edpt_dir(ep_addr); - - TU_ASSERT(epnum < ep_count); - - uint16_t fifo_size = tu_div_ceil(packet_size, 4); - if (dir == TUSB_DIR_OUT) { - // Calculate required size of RX FIFO - const uint16_t new_sz = calc_device_grxfsiz(4 * fifo_size, ep_count); - - // If size_rx needs to be extended check if there is enough free space - if (dwc2->grxfsiz < new_sz) { - TU_ASSERT(new_sz <= _dcd_data.dfifo_top); - dwc2->grxfsiz = new_sz; // Enlarge RX FIFO - } - } else { - // Check IN endpoints concurrently active limit - if(dwc2_controller->ep_in_count) { - TU_ASSERT(_dcd_data.allocated_epin_count < dwc2_controller->ep_in_count); - _dcd_data.allocated_epin_count++; - } - - // If The TXFELVL is configured as half empty, the fifo must be twice the max_size. - if ((dwc2->gahbcfg & GAHBCFG_TX_FIFO_EPMTY_LVL) == 0) { - fifo_size *= 2; - } - - // Check if free space is available - TU_ASSERT(_dcd_data.dfifo_top >= fifo_size + dwc2->grxfsiz); - _dcd_data.dfifo_top -= fifo_size; - // TU_LOG(DWC2_DEBUG, " TX FIFO %u: allocated %u words at offset %u\r\n", epnum, fifo_size, dfifo_top); - - // Both TXFD and TXSA are in unit of 32-bit words. - if (epnum == 0) { - dwc2->dieptxf0 = (fifo_size << DIEPTXF0_TX0FD_Pos) | _dcd_data.dfifo_top; - } else { - // DIEPTXF starts at FIFO #1. - dwc2->dieptxf[epnum - 1] = (fifo_size << DIEPTXF_INEPTXFD_Pos) | _dcd_data.dfifo_top; - } - } - - return true; -} - -static void dfifo_device_init(uint8_t rhport) { - const dwc2_controller_t* dwc2_controller = &_dwc2_controller[rhport]; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2->grxfsiz = calc_device_grxfsiz(CFG_TUD_ENDPOINT0_SIZE, dwc2_controller->ep_count); - - // Scatter/Gather DMA mode is not yet supported. Buffer DMA only need 1 words per endpoint direction - const bool is_dma = dma_device_enabled(dwc2); - _dcd_data.dfifo_top = dwc2_controller->ep_fifo_size/4; - if (is_dma) { - _dcd_data.dfifo_top -= 2 * dwc2_controller->ep_count; - } - dwc2->gdfifocfg = (_dcd_data.dfifo_top << GDFIFOCFG_EPINFOBASE_SHIFT) | _dcd_data.dfifo_top; - - // Allocate FIFO for EP0 IN - dfifo_alloc(rhport, 0x80, CFG_TUD_ENDPOINT0_SIZE); -} - - -//-------------------------------------------------------------------- -// Endpoint -//-------------------------------------------------------------------- -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) -// Keep count of how many FIFOs are in use -static uint8_t _allocated_fifos = 1; //FIFO0 is always in use - -// Will either return an unused FIFO number, or 0 if all are used. -static uint8_t get_free_fifo(void) { - if (_allocated_fifos < 5) return _allocated_fifos++; - return 0; -} -#endif - -static void edpt_activate(uint8_t rhport, const tusb_desc_endpoint_t* p_endpoint_desc) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const uint8_t epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress); - const uint8_t dir = tu_edpt_dir(p_endpoint_desc->bEndpointAddress); - - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); - xfer->max_size = tu_edpt_packet_size(p_endpoint_desc); - xfer->interval = p_endpoint_desc->bInterval; - - // Endpoint control - dwc2_depctl_t depctl = {.value = 0}; - depctl.mps = xfer->max_size; - depctl.active = 1; - depctl.type = p_endpoint_desc->bmAttributes.xfer; - if (p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS) { - depctl.set_data0_iso_even = 1; - } - if (dir == TUSB_DIR_IN) { - //depctl.tx_fifo_num = epnum; - uint8_t fifo_num = epnum; -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - // Special Case for EP5, which is used by CDC but not actually called by the driver - // we can give it a fake FIFO - if (epnum == 5) { - fifo_num = epnum; - } else { - fifo_num = get_free_fifo(); - } -#endif - depctl.tx_fifo_num = fifo_num; - } - - dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; - dep->ctl = depctl.value; - dwc2->daintmsk |= TU_BIT(epnum + DAINT_SHIFT(dir)); -} - -static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { - (void) rhport; - - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const uint8_t epnum = tu_edpt_number(ep_addr); - const uint8_t dir = tu_edpt_dir(ep_addr); - dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; - - if (dir == TUSB_DIR_IN) { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(dep->diepctl & DIEPCTL_EPENA)) { - dep->diepctl |= DIEPCTL_SNAK | (stall ? DIEPCTL_STALL : 0); - } else { - // Stop transmitting packets and NAK IN xfers. - dep->diepctl |= DIEPCTL_SNAK; - while ((dep->diepint & DIEPINT_INEPNE) == 0) {} - - // Disable the endpoint. - dep->diepctl |= DIEPCTL_EPDIS | (stall ? DIEPCTL_STALL : 0); - while ((dep->diepint & DIEPINT_EPDISD_Msk) == 0) {} - - dep->diepint = DIEPINT_EPDISD; - } - - // Flush the FIFO, and wait until we have confirmed it cleared. - dfifo_flush_tx(dwc2, epnum); - } else { - // Only disable currently enabled non-control endpoint - if ((epnum == 0) || !(dep->doepctl & DOEPCTL_EPENA)) { - dep->doepctl |= stall ? DOEPCTL_STALL : 0; - } else { - // Asserting GONAK is required to STALL an OUT endpoint. - // Simpler to use polling here, we don't use the "B"OUTNAKEFF interrupt - // anyway, and it can't be cleared by user code. If this while loop never - // finishes, we have bigger problems than just the stack. - dwc2->dctl |= DCTL_SGONAK; - while ((dwc2->gintsts & GINTSTS_BOUTNAKEFF_Msk) == 0) {} - - // Ditto here disable the endpoint. - dep->doepctl |= DOEPCTL_EPDIS | (stall ? DOEPCTL_STALL : 0); - while ((dep->doepint & DOEPINT_EPDISD_Msk) == 0) {} - - dep->doepint = DOEPINT_EPDISD; - - // Allow other OUT endpoints to keep receiving. - dwc2->dctl |= DCTL_CGONAK; - } - } -} - -// Since this function returns void, it is not possible to return a boolean success message -// We must make sure that this function is not called when the EP is disabled -// Must be called from critical section -static void edpt_schedule_packets(uint8_t rhport, const uint8_t epnum, const uint8_t dir) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - xfer_ctl_t* const xfer = XFER_CTL_BASE(epnum, dir); - dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; - - uint16_t num_packets; - uint16_t total_bytes; - - // EP0 is limited to one packet per xfer - if (epnum == 0) { - total_bytes = tu_min16(_dcd_data.ep0_pending[dir], xfer->max_size); - _dcd_data.ep0_pending[dir] -= total_bytes; - num_packets = 1; - } else { - total_bytes = xfer->total_len; - num_packets = tu_div_ceil(total_bytes, xfer->max_size); - if (num_packets == 0) { - num_packets = 1; // zero length packet still count as 1 - } - } - - // transfer size: A full OUT transfer (multiple packets, possibly) triggers XFRC. - dwc2_ep_tsize_t deptsiz = {.value = 0}; - deptsiz.xfer_size = total_bytes; - deptsiz.packet_count = num_packets; - dep->tsiz = deptsiz.value; - - // control - dwc2_depctl_t depctl = {.value = dep->ctl}; - depctl.clear_nak = 1; - depctl.enable = 1; - if (depctl.type == DEPCTL_EPTYPE_ISOCHRONOUS && xfer->interval == 1) { - const dwc2_dsts_t dsts = {.value = dwc2->dsts}; - const uint32_t odd_now = dsts.frame_number & 1u; - if (odd_now) { - depctl.set_data0_iso_even = 1; - } else { - depctl.set_data1_iso_odd = 1; - } - } - - const bool is_dma = dma_device_enabled(dwc2); - if(is_dma) { - if (dir == TUSB_DIR_IN && total_bytes != 0) { - dcd_dcache_clean(xfer->buffer, total_bytes); - } - dep->diepdma = (uintptr_t) xfer->buffer; - dep->diepctl = depctl.value; // enable endpoint - } else { - dep->diepctl = depctl.value; // enable endpoint - - // Enable tx fifo empty interrupt only if there is data. Note must after depctl enable - if (dir == TUSB_DIR_IN && total_bytes != 0) { - dwc2->diepempmsk |= (1 << epnum); - } - } -} - -//-------------------------------------------------------------------- -// Controller API -//-------------------------------------------------------------------- -bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { - (void) rh_init; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - - tu_memclr(&_dcd_data, sizeof(_dcd_data)); - - // Core Initialization - const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); - const bool is_dma = dma_device_enabled(dwc2); - TU_ASSERT(dwc2_core_init(rhport, is_highspeed, is_dma)); - - //------------- 7.1 Device Initialization -------------// - // Set device max speed - uint32_t dcfg = dwc2->dcfg & ~DCFG_DSPD_Msk; - if (is_highspeed) { - dcfg |= DCFG_DSPD_HS << DCFG_DSPD_Pos; - - // XCVRDLY: transceiver delay between xcvr_sel and txvalid during device chirp is required - // when using with some PHYs such as USB334x (USB3341, USB3343, USB3346, USB3347) - const dwc2_ghwcfg2_t ghwcfg2 = {.value = dwc2->ghwcfg2}; - if (ghwcfg2.hs_phy_type == GHWCFG2_HSPHY_ULPI) { - dcfg |= DCFG_XCVRDLY; - } - } else { - dcfg |= DCFG_DSPD_FS << DCFG_DSPD_Pos; - } - - dcfg |= DCFG_NZLSOHSK; // send STALL back and discard if host send non-zlp during control status - dwc2->dcfg = dcfg; - - dcd_disconnect(rhport); - - // Force device mode - dwc2->gusbcfg = (dwc2->gusbcfg & ~GUSBCFG_FHMOD) | GUSBCFG_FDMOD; - - // Clear A override, force B Valid - dwc2->gotgctl = (dwc2->gotgctl & ~GOTGCTL_AVALOEN) | GOTGCTL_BVALOEN | GOTGCTL_BVALOVAL; - - // Enable required interrupts - dwc2->gintmsk |= GINTMSK_OTGINT | GINTMSK_USBSUSPM | GINTMSK_USBRST | GINTMSK_ENUMDNEM | GINTMSK_WUIM; - - // TX FIFO empty level for interrupt is complete empty - uint32_t gahbcfg = dwc2->gahbcfg; - gahbcfg |= GAHBCFG_TX_FIFO_EPMTY_LVL; - gahbcfg |= GAHBCFG_GINT; // Enable global interrupt - dwc2->gahbcfg = gahbcfg; - - dcd_connect(rhport); - return true; -} - -void dcd_int_enable(uint8_t rhport) { - dwc2_dcd_int_enable(rhport); -} - -void dcd_int_disable(uint8_t rhport) { - dwc2_dcd_int_disable(rhport); -} - -void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2->dcfg = (dwc2->dcfg & ~DCFG_DAD_Msk) | (dev_addr << DCFG_DAD_Pos); - - // Response with status after changing device address - dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); -} - -void dcd_remote_wakeup(uint8_t rhport) { - (void) rhport; - - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - - // set remote wakeup - dwc2->dctl |= DCTL_RWUSIG; - - // enable SOF to detect bus resume - dwc2->gintsts = GINTSTS_SOF; - dwc2->gintmsk |= GINTMSK_SOFM; - - // Per specs: remote wakeup signal bit must be clear within 1-15ms - dwc2_remote_wakeup_delay(); - - dwc2->dctl &= ~DCTL_RWUSIG; -} - -void dcd_connect(uint8_t rhport) { - (void) rhport; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - -#ifdef TUP_USBIP_DWC2_ESP32 - usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; - conf.pad_pull_override = 0; - conf.dp_pullup = 0; - conf.dp_pulldown = 0; - conf.dm_pullup = 0; - conf.dm_pulldown = 0; - USB_WRAP.otg_conf = conf; -#endif - - dwc2->dctl &= ~DCTL_SDIS; -} - -void dcd_disconnect(uint8_t rhport) { - (void) rhport; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - -#ifdef TUP_USBIP_DWC2_ESP32 - usb_wrap_otg_conf_reg_t conf = USB_WRAP.otg_conf; - conf.pad_pull_override = 1; - conf.dp_pullup = 0; - conf.dp_pulldown = 1; - conf.dm_pullup = 0; - conf.dm_pulldown = 1; - USB_WRAP.otg_conf = conf; -#endif - - dwc2->dctl |= DCTL_SDIS; -} - -// Be advised: audio, video and possibly other iso-ep classes use dcd_sof_enable() to enable/disable its corresponding ISR on purpose! -void dcd_sof_enable(uint8_t rhport, bool en) { - (void) rhport; - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - - _dcd_data.sof_en = en; - - if (en) { - dwc2->gintsts = GINTSTS_SOF; - dwc2->gintmsk |= GINTMSK_SOFM; - } else { - dwc2->gintmsk &= ~GINTMSK_SOFM; - } -} - -/*------------------------------------------------------------------*/ -/* DCD Endpoint port - *------------------------------------------------------------------*/ - -bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_edpt) { - TU_ASSERT(dfifo_alloc(rhport, desc_edpt->bEndpointAddress, tu_edpt_packet_size(desc_edpt))); - edpt_activate(rhport, desc_edpt); - return true; -} - -// Close all non-control endpoints, cancel all pending transfers if any. -void dcd_edpt_close_all(uint8_t rhport) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const ep_count = _dwc2_controller[rhport].ep_count; - - usbd_spin_lock(false); - - _dcd_data.allocated_epin_count = 0; - - // Disable non-control interrupt - dwc2->daintmsk = (1 << DAINTMSK_OEPM_Pos) | (1 << DAINTMSK_IEPM_Pos); - - for (uint8_t n = 1; n < ep_count; n++) { - for (uint8_t d = 0; d < 2; d++) { - dwc2_dep_t* dep = &dwc2->ep[d][n]; - if (dep->ctl & EPCTL_EPENA) { - dep->ctl |= EPCTL_SNAK | EPCTL_EPDIS; - } - xfer_status[n][1-d].max_size = 0; - } - } - -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - _allocated_fifos = 1; -#endif - - dfifo_flush_tx(dwc2, 0x10); // all tx fifo - dfifo_flush_rx(dwc2); - dfifo_device_init(rhport); // re-init dfifo - - usbd_spin_unlock(false); -} - -bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { - TU_ASSERT(dfifo_alloc(rhport, ep_addr, largest_packet_size)); - return true; -} - -bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { - // Disable EP to clear potential incomplete transfers - edpt_disable(rhport, p_endpoint_desc->bEndpointAddress, false); - edpt_activate(rhport, p_endpoint_desc); - return true; -} - -bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); - bool ret; - - usbd_spin_lock(false); - - if (xfer->max_size == 0) { - ret = false; // Endpoint is closed - } else { - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; - - // EP0 can only handle one packet - if (epnum == 0) { - _dcd_data.ep0_pending[dir] = total_bytes; - } - - // Schedule packets to be sent within interrupt - edpt_schedule_packets(rhport, epnum, dir); - ret = true; - } - - usbd_spin_unlock(false); - - return ret; -} - -// The number of bytes has to be given explicitly to allow more flexible control of how many -// bytes should be written and second to keep the return value free to give back a boolean -// success message. If total_bytes is too big, the FIFO will copy only what is available -// into the USB buffer! -bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t total_bytes) { - // USB buffers always work in bytes so to avoid unnecessary divisions we demand item_size = 1 - TU_ASSERT(ff->item_size == 1); - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); - bool ret; - - usbd_spin_lock(false); - - if (xfer->max_size == 0) { - ret = false; // Endpoint is closed - } else { - xfer->buffer = NULL; - xfer->ff = ff; - xfer->total_len = total_bytes; - - // Schedule packets to be sent within interrupt - // TODO xfer fifo may only available for slave mode - edpt_schedule_packets(rhport, epnum, dir); - ret = true; - } - - usbd_spin_unlock(false); - - return ret; -} - -void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - edpt_disable(rhport, ep_addr, true); - if((tu_edpt_number(ep_addr) == 0) && dma_device_enabled(dwc2)) { - dma_setup_prepare(rhport); - } -} - -void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - dwc2_dep_t* dep = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][epnum]; - - // Clear stall and reset data toggle - dep->ctl &= ~EPCTL_STALL;; - dep->ctl |= EPCTL_SD0PID_SEVNFRM; -} - -//-------------------------------------------------------------------- -// Interrupt Handler -//-------------------------------------------------------------------- - -// 7.4.1 Initialization on USB Reset -// Must be called from critical section -static void handle_bus_reset(uint8_t rhport) { - dwc2_regs_t *dwc2 = DWC2_REG(rhport); - const uint8_t ep_count = dwc2_ep_count(dwc2); - - tu_memclr(xfer_status, sizeof(xfer_status)); - - _dcd_data.sof_en = false; - _dcd_data.allocated_epin_count = 0; - - // 1. NAK for all OUT endpoints - for (uint8_t n = 0; n < ep_count; n++) { - dwc2->epout[n].doepctl |= DOEPCTL_SNAK; - } - - // Disable all IN endpoints - for (uint8_t n = 0; n < ep_count; n++) { - if (dwc2->epin[n].diepctl & DIEPCTL_EPENA) { - dwc2->epin[n].diepctl |= DIEPCTL_SNAK | DIEPCTL_EPDIS; - } - } - - // 2. Set up interrupt mask for EP0 - dwc2->daintmsk = TU_BIT(DAINTMSK_OEPM_Pos) | TU_BIT(DAINTMSK_IEPM_Pos); - dwc2->doepmsk = DOEPMSK_STUPM | DOEPMSK_XFRCM; - dwc2->diepmsk = DIEPMSK_TOM | DIEPMSK_XFRCM; - - // 4. Set up DFIFO - dfifo_flush_tx(dwc2, 0x10); // all tx fifo - dfifo_flush_rx(dwc2); - dfifo_device_init(rhport); - - // 5. Reset device address - dwc2_dcfg_t dcfg = {.value = dwc2->dcfg}; - dcfg.address = 0; - dwc2->dcfg = dcfg.value; - - // Fixed both control EP0 size to 64 bytes - dwc2->epin[0].ctl &= ~(0x03 << DIEPCTL_MPSIZ_Pos); - dwc2->epout[0].ctl &= ~(0x03 << DOEPCTL_MPSIZ_Pos); - - xfer_status[0][TUSB_DIR_OUT].max_size = 64; - xfer_status[0][TUSB_DIR_IN].max_size = 64; - - if(dma_device_enabled(dwc2)) { - dma_setup_prepare(rhport); - } else { - dwc2->epout[0].doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); - } - - dwc2->gintmsk |= GINTMSK_OEPINT | GINTMSK_IEPINT; -} - -static void handle_enum_done(uint8_t rhport) { - dwc2_regs_t *dwc2 = DWC2_REG(rhport); - const dwc2_dsts_t dsts = {.value = dwc2->dsts}; - tusb_speed_t speed; - switch (dsts.enum_speed) { - case DCFG_SPEED_HIGH: - speed = TUSB_SPEED_HIGH; - break; - - case DCFG_SPEED_LOW: - speed = TUSB_SPEED_LOW; - break; - - case DCFG_SPEED_FULL_30_60MHZ: - case DCFG_SPEED_FULL_48MHZ: - default: - speed = TUSB_SPEED_FULL; - break; - } - - // TODO must update GUSBCFG_TRDT according to link speed - dcd_event_bus_reset(rhport, speed, true); -} - -#if 0 -TU_ATTR_ALWAYS_INLINE static inline void print_doepint(uint32_t doepint) { - const char* str[] = { - "XFRC", "DIS", "AHBERR", "SETUP_DONE", - "ORXED", "STATUS_RX", "SETUP_B2B", "RSV7", - "OPERR", "BNA", "RSV10", "ISODROP", - "BBLERR", "NAK", "NYET", "SETUP_RX" - }; - - for(uint32_t i=0; ififo[0]; - - // Pop control word off FIFO - const dwc2_grxstsp_t grxstsp = {.value = dwc2->grxstsp}; - const uint8_t epnum = grxstsp.ep_ch_num; - - dwc2_dep_t* epout = &dwc2->epout[epnum]; - - switch (grxstsp.packet_status) { - case GRXSTS_PKTSTS_GLOBAL_OUT_NAK: - // Global OUT NAK: do nothing - break; - - case GRXSTS_PKTSTS_SETUP_RX: { - // Setup packet received - uint32_t* setup = (uint32_t*)(uintptr_t) _dcd_usbbuf.setup_packet; - // We can receive up to three setup packets in succession, but only the last one is valid. - setup[0] = (*rx_fifo); - setup[1] = (*rx_fifo); - break; - } - - case GRXSTS_PKTSTS_SETUP_DONE: - // Setup packet done: - // After popping this out, dwc2 asserts a DOEPINT_SETUP interrupt which is handled by handle_epout_irq() - epout->doeptsiz |= (3 << DOEPTSIZ_STUPCNT_Pos); - break; - - case GRXSTS_PKTSTS_RX_DATA: { - // Out packet received - const uint16_t byte_count = grxstsp.byte_count; - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - - if (byte_count) { - // Read packet off RxFIFO - if (xfer->ff) { - tu_fifo_write_n_const_addr_full_words(xfer->ff, (const void*) (uintptr_t) rx_fifo, byte_count); - } else { - dfifo_read_packet(dwc2, xfer->buffer, byte_count); - xfer->buffer += byte_count; - } - - // short packet, minus remaining bytes (xfer_size) - if (byte_count < xfer->max_size) { - const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; - xfer->total_len -= tsiz.xfer_size; - if (epnum == 0) { - xfer->total_len -= _dcd_data.ep0_pending[TUSB_DIR_OUT]; - _dcd_data.ep0_pending[TUSB_DIR_OUT] = 0; - } - } - } - break; - } - - case GRXSTS_PKTSTS_RX_COMPLETE: - // Out packet done - // After this entry is popped from the receive FIFO, dwc2 asserts a Transfer Completed interrupt on - // the specified OUT endpoint which will be handled by handle_epout_irq() - break; - - default: break; - } -} - -static void handle_epout_slave(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { - if (doepint_bm.setup_phase_done) { - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); - return; - } - - // Normal OUT transfer complete - if (doepint_bm.xfer_complete) { - // only handle data skip if it is setup or status related - // Note: even though (xfer_complete + status_phase_rx) is for buffered DMA only, for STM32L47x (dwc2 v3.00a) they - // can is set when GRXSTS_PKTSTS_SETUP_RX is popped therefore they can bet set before/together with setup_phase_done - if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { - // EP0 can only handle one packet, Schedule another packet to be received. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); - } else { - dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } - } -} - -static void handle_epin_slave(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepint_bm) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - dwc2_dep_t* epin = &dwc2->epin[epnum]; - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); - - if (diepint_bm.xfer_complete) { - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) { - // EP0 can only handle one packet. Schedule another packet to be transmitted. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); - } else { - dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } - - // TX FIFO empty bit is read-only. It will only be cleared by hardware when written bytes is more than - // - 64 bytes or - // - Half/Empty of TX FIFO size (configured by GAHBCFG.TXFELVL) - if (diepint_bm.txfifo_empty && (dwc2->diepempmsk & (1 << epnum))) { - dwc2_ep_tsize_t tsiz = {.value = epin->tsiz}; - const uint16_t remain_packets = tsiz.packet_count; - - // Process every single packet (only whole packets can be written to fifo) - for (uint16_t i = 0; i < remain_packets; i++) { - tsiz.value = epin->tsiz; - const uint16_t remain_bytes = (uint16_t) tsiz.xfer_size; - const uint16_t xact_bytes = tu_min16(remain_bytes, xfer->max_size); - - // Check if dtxfsts has enough space available - if (xact_bytes > ((epin->dtxfsts & DTXFSTS_INEPTFSAV_Msk) << 2)) { - break; - } - - // Push packet to Tx-FIFO - if (xfer->ff) { - volatile uint32_t* tx_fifo = dwc2->fifo[epnum]; - tu_fifo_read_n_const_addr_full_words(xfer->ff, (void*)(uintptr_t)tx_fifo, xact_bytes); - } else { - dfifo_write_packet(dwc2, epnum, xfer->buffer, xact_bytes); - xfer->buffer += xact_bytes; - } - } - - // Turn off TXFE if all bytes are written. - tsiz.value = epin->tsiz; - if (tsiz.xfer_size == 0) { - dwc2->diepempmsk &= ~(1 << epnum); - } - } -} -#endif - -#if CFG_TUD_DWC2_DMA_ENABLE -static void handle_epout_dma(uint8_t rhport, uint8_t epnum, dwc2_doepint_t doepint_bm) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - - if (doepint_bm.setup_phase_done) { - dma_setup_prepare(rhport); - dcd_dcache_invalidate(_dcd_usbbuf.setup_packet, 8); - dcd_event_setup_received(rhport, _dcd_usbbuf.setup_packet, true); - return; - } - - // OUT XFER complete - if (doepint_bm.xfer_complete) { - // only handle data skip if it is setup or status related - // Normal OUT transfer complete - if (!doepint_bm.status_phase_rx && !doepint_bm.setup_packet_rx) { - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_OUT]) { - // EP0 can only handle one packet Schedule another packet to be received. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_OUT); - } else { - dwc2_dep_t* epout = &dwc2->epout[epnum]; - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_OUT); - - // determine actual received bytes - const dwc2_ep_tsize_t tsiz = {.value = epout->tsiz}; - const uint16_t remain = tsiz.xfer_size; - xfer->total_len -= remain; - - // this is ZLP, so prepare EP0 for next setup - // TODO use status phase rx - if(epnum == 0 && xfer->total_len == 0) { - dma_setup_prepare(rhport); - } - - dcd_dcache_invalidate(xfer->buffer, xfer->total_len); - dcd_event_xfer_complete(rhport, epnum, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } - } -} - -static void handle_epin_dma(uint8_t rhport, uint8_t epnum, dwc2_diepint_t diepint_bm) { - xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, TUSB_DIR_IN); - - if (diepint_bm.xfer_complete) { - if ((epnum == 0) && _dcd_data.ep0_pending[TUSB_DIR_IN]) { - // EP0 can only handle one packet. Schedule another packet to be transmitted. - edpt_schedule_packets(rhport, epnum, TUSB_DIR_IN); - } else { - if(epnum == 0) { - dma_setup_prepare(rhport); - } - dcd_event_xfer_complete(rhport, epnum | TUSB_DIR_IN_MASK, xfer->total_len, XFER_RESULT_SUCCESS, true); - } - } -} -#endif - -static void handle_ep_irq(uint8_t rhport, uint8_t dir) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const bool is_dma = dma_device_enabled(dwc2); - const uint8_t ep_count = dwc2_ep_count(dwc2); - const uint8_t daint_offset = (dir == TUSB_DIR_IN) ? DAINT_IEPINT_Pos : DAINT_OEPINT_Pos; - dwc2_dep_t* ep_base = &dwc2->ep[dir == TUSB_DIR_IN ? 0 : 1][0]; - - // DAINT for a given EP clears when DEPINTx is cleared. - // EPINT will be cleared when DAINT bits are cleared. - for (uint8_t epnum = 0; epnum < ep_count; epnum++) { - if (dwc2->daint & TU_BIT(daint_offset + epnum)) { - dwc2_dep_t* epout = &ep_base[epnum]; - union { - uint32_t value; - dwc2_diepint_t diepint_bm; - dwc2_doepint_t doepint_bm; - } intr; - intr.value = epout->intr; - - epout->intr = intr.value; // Clear interrupt - - if (is_dma) { - #if CFG_TUD_DWC2_DMA_ENABLE - if (dir == TUSB_DIR_IN) { - handle_epin_dma(rhport, epnum, intr.diepint_bm); - } else { - handle_epout_dma(rhport, epnum, intr.doepint_bm); - } - #endif - } else { - #if CFG_TUD_DWC2_SLAVE_ENABLE - if (dir == TUSB_DIR_IN) { - handle_epin_slave(rhport, epnum, intr.diepint_bm); - } else { - handle_epout_slave(rhport, epnum, intr.doepint_bm); - } - #endif - } - } - } -} - -/* Interrupt Hierarchy - DIEPINT DIEPINT - \ / - \ / - DAINT - / \ - / \ - GINTSTS: OEPInt IEPInt | USBReset | EnumDone | USBSusp | WkUpInt | OTGInt | SOF | RXFLVL - - Note: when OTG_MULTI_PROC_INTRPT = 1, Device Each endpoint interrupt deachint/deachmsk/diepeachmsk/doepeachmsk - are combined to generate dedicated interrupt line for each endpoint. - */ -void dcd_int_handler(uint8_t rhport) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - const uint32_t gintmask = dwc2->gintmsk; - const uint32_t gintsts = dwc2->gintsts & gintmask; - - if (gintsts & GINTSTS_USBRST) { - // USBRST is start of reset. - dwc2->gintsts = GINTSTS_USBRST; -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - _allocated_fifos = 1; -#endif - - usbd_spin_lock(true); - handle_bus_reset(rhport); - usbd_spin_unlock(true); - } - - if (gintsts & GINTSTS_ENUMDNE) { - // ENUMDNE is the end of reset where speed of the link is detected - dwc2->gintsts = GINTSTS_ENUMDNE; - handle_enum_done(rhport); - } - - if (gintsts & GINTSTS_USBSUSP) { - dwc2->gintsts = GINTSTS_USBSUSP; - //dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - _allocated_fifos = 1; -#endif - } - - if (gintsts & GINTSTS_WKUINT) { - dwc2->gintsts = GINTSTS_WKUINT; - dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); - } - - // TODO check GINTSTS_DISCINT for disconnect detection - // if(int_status & GINTSTS_DISCINT) - - if (gintsts & GINTSTS_OTGINT) { - // OTG INT bit is read-only - const uint32_t otg_int = dwc2->gotgint; - - if (otg_int & GOTGINT_SEDET) { - dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true); -#if TU_CHECK_MCU(OPT_MCU_ESP32S2, OPT_MCU_ESP32S3) - _allocated_fifos = 1; -#endif - } - - dwc2->gotgint = otg_int; - } - - if(gintsts & GINTSTS_SOF) { - dwc2->gintsts = GINTSTS_SOF; - const uint32_t frame = (dwc2->dsts & DSTS_FNSOF) >> DSTS_FNSOF_Pos; - - // Disable SOF interrupt if SOF was not explicitly enabled since SOF was used for remote wakeup detection - if (!_dcd_data.sof_en) { - dwc2->gintmsk &= ~GINTMSK_SOFM; - } - - dcd_event_sof(rhport, frame, true); - } - -#if CFG_TUD_DWC2_SLAVE_ENABLE - // RxFIFO non-empty interrupt handling. - if (gintsts & GINTSTS_RXFLVL) { - // RXFLVL bit is read-only - dwc2->gintmsk &= ~GINTMSK_RXFLVLM; // disable RXFLVL interrupt while reading - - do { - handle_rxflvl_irq(rhport); // read all packets - } while(dwc2->gintsts & GINTSTS_RXFLVL); - - dwc2->gintmsk |= GINTMSK_RXFLVLM; - } -#endif - - // OUT endpoint interrupt handling. - if (gintsts & GINTSTS_OEPINT) { - // OEPINT is read-only, clear using DOEPINTn - handle_ep_irq(rhport, TUSB_DIR_OUT); - } - - // IN endpoint interrupt handling. - if (gintsts & GINTSTS_IEPINT) { - // IEPINT bit read-only, clear using DIEPINTn - handle_ep_irq(rhport, TUSB_DIR_IN); - } -} - -#if CFG_TUD_TEST_MODE -void dcd_enter_test_mode(uint8_t rhport, tusb_feature_test_mode_t test_selector) { - dwc2_regs_t* dwc2 = DWC2_REG(rhport); - - // Enable the test mode - dwc2->dctl = (dwc2->dctl & ~DCTL_TCTL_Msk) | (((uint8_t) test_selector) << DCTL_TCTL_Pos); -} -#endif - -#endif From 81f60028b5d077a37d4d8e92510d8e09d7746768 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 8 Nov 2025 21:34:33 +0100 Subject: [PATCH 12/22] Delete tools/patch-tinyusb.sh --- tools/patch-tinyusb.sh | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 tools/patch-tinyusb.sh diff --git a/tools/patch-tinyusb.sh b/tools/patch-tinyusb.sh deleted file mode 100644 index eeaa4d43b..000000000 --- a/tools/patch-tinyusb.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -mv components/arduino_tinyusb/src/dcd_dwc2.c components/arduino_tinyusb/src/dcd_dwc2.c.prev -cp components/arduino_tinyusb/tinyusb/src/portable/synopsys/dwc2/dcd_dwc2.c components/arduino_tinyusb/src/dcd_dwc2.c -patch -p1 -N -i components/arduino_tinyusb/patches/dcd_dwc2.patch From 34ba42ec30844c1d10c073c00e82f57fd6425277 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Sat, 8 Nov 2025 21:34:57 +0100 Subject: [PATCH 13/22] Remove patch application from update script Remove patch application for dwc2_esp32_h.diff --- tools/update-components.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/update-components.sh b/tools/update-components.sh index c7d4088c6..8b3499875 100755 --- a/tools/update-components.sh +++ b/tools/update-components.sh @@ -18,7 +18,4 @@ else git clean -ffdx cd - fi -cd $TINYUSB_REPO_DIR -patch -p1 -N -i $AR_PATCHES/dwc2_esp32_h.diff -cd - if [ $? -ne 0 ]; then exit 1; fi From f5300935fc58f26c30771d4baf2400b00129e7dd Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:27:20 +0100 Subject: [PATCH 14/22] Delete patches/dwc2_esp32_h.diff --- patches/dwc2_esp32_h.diff | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 patches/dwc2_esp32_h.diff diff --git a/patches/dwc2_esp32_h.diff b/patches/dwc2_esp32_h.diff deleted file mode 100644 index 94cb86f32..000000000 --- a/patches/dwc2_esp32_h.diff +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h -index 49b8c54cb..8b5e99741 100644 ---- a/src/portable/synopsys/dwc2/dwc2_esp32.h -+++ b/src/portable/synopsys/dwc2/dwc2_esp32.h -@@ -70,11 +70,13 @@ static void dwc2_int_handler_wrap(void* arg) { - const tusb_role_t role = (tusb_role_t) tu_u16_high((uint16_t)(uintptr_t)arg); - #if CFG_TUD_ENABLED - if (role == TUSB_ROLE_DEVICE) { -+ void dcd_int_handler(uint8_t rhport); - dcd_int_handler(rhport); - } - #endif - #if CFG_TUH_ENABLED && !CFG_TUH_MAX3421 - if (role == TUSB_ROLE_HOST) { -+ void hcd_int_handler(uint8_t rhport, bool in_isr); - hcd_int_handler(rhport, true); - } - #endif From 41920aead74f1a927170275a234799c35ed76ac9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 10 Nov 2025 14:31:18 +0100 Subject: [PATCH 15/22] Enable LCD RGB ISR IRAM safe configuration --- configs/defconfig.opi_ram | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/defconfig.opi_ram b/configs/defconfig.opi_ram index b4ebe1a15..1e191ba25 100644 --- a/configs/defconfig.opi_ram +++ b/configs/defconfig.opi_ram @@ -2,6 +2,7 @@ CONFIG_SPIRAM=y CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y # CONFIG_SPIRAM_MEMTEST is not set +CONFIG_LCD_RGB_ISR_IRAM_SAFE=y CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y # bounce buffer mode relies on GDMA EOF interrupt to be service-able # I2S_ISR_IRAM_SAFE has to be set!! Done in common config From 36dcb21435411af841e43021624b8e72c5a79872 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Mon, 10 Nov 2025 16:51:59 +0100 Subject: [PATCH 16/22] Disable CONFIG_LCD_RGB_RESTART_IN_VSYNC option --- configs/defconfig.esp32s3 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/defconfig.esp32s3 b/configs/defconfig.esp32s3 index 96b434df7..aeac084a6 100644 --- a/configs/defconfig.esp32s3 +++ b/configs/defconfig.esp32s3 @@ -24,8 +24,9 @@ CONFIG_BOOTLOADER_FLASH_DC_AWARE=y # # S3 Display shift fix -> https://espressif-docs.readthedocs-hosted.com/projects/esp-faq/en/latest/software-framework/peripherals/lcd.html +# with latest uDisplay refactoring no need to enable! # -CONFIG_LCD_RGB_RESTART_IN_VSYNC=y +# CONFIG_LCD_RGB_RESTART_IN_VSYNC is not set # # Bluetooth From 0c5186209fc7c7ce98f82c86900a1209899622ce Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:58:03 +0100 Subject: [PATCH 17/22] Modify esp32s3 target configurations Updated idf_libs and bootloaders for esp32s3 target. --- configs/builds.json | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/configs/builds.json b/configs/builds.json index 98013375f..9c511c5d1 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -165,16 +165,11 @@ { "target": "esp32s3", "features":[], - "idf_libs":["qio","80m","qio_ram"], + "idf_libs":["qio","120","opi_ram"], "bootloaders":[ - ["qio","120m","qio_ram"], - ["qio","80m","qio_ram"], - ["opi","80m","opi_ram"], - ["opi","120m","opi_ram"] + ["qio","120m","opi_ram"] ], "mem_variants":[ - ["qio","80m","opi_ram"], - ["opi","80m","opi_ram"], ["opi","120m","opi_ram"] ] } From 20d28008d840530fd565e86ead085bbd95bbcde7 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:58:44 +0100 Subject: [PATCH 18/22] Rename workflow to 'IDF v5.5 S3 120M' --- .github/workflows/parallel_build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/parallel_build.yaml b/.github/workflows/parallel_build.yaml index 8f2153530..ff6eb9275 100644 --- a/.github/workflows/parallel_build.yaml +++ b/.github/workflows/parallel_build.yaml @@ -1,4 +1,4 @@ -name: IDF v5.5 based build +name: IDF v5.5 S3 120M on: workflow_dispatch: # Manually start a workflow From 728df4f185560cb35df3bb52635d371a5f9e7784 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:03:25 +0100 Subject: [PATCH 19/22] Fix typo in idf_libs for esp32s3 target --- configs/builds.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/builds.json b/configs/builds.json index 9c511c5d1..084eaf78c 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -165,7 +165,7 @@ { "target": "esp32s3", "features":[], - "idf_libs":["qio","120","opi_ram"], + "idf_libs":["qio","120m","opi_ram"], "bootloaders":[ ["qio","120m","opi_ram"] ], From 28c74f1869eb2ccad86c7985c06f45df79d74c59 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Nov 2025 13:48:24 +0100 Subject: [PATCH 20/22] Change S3 bootloader and memory variants --- configs/builds.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/configs/builds.json b/configs/builds.json index 084eaf78c..65b69cb9e 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -167,10 +167,18 @@ "features":[], "idf_libs":["qio","120m","opi_ram"], "bootloaders":[ - ["qio","120m","opi_ram"] + ["qio","120m","opi_ram"], + ["qio","120m","qio_ram"], + ["qio","80m","qio_ram"], + ["opi","80m","opi_ram"], + ["opi","120m","opi_ram"], + ["opi","120m","qio_ram"] ], "mem_variants":[ - ["opi","120m","opi_ram"] + ["opi","120m","qio_ram"], + ["opi","120m","opi_ram"], + ["qio","120m","qio_ram"], + ["qio","120m","opi_ram"] ] } ] From c394de7b0dec854bdc2031c17edd2c213fb972f9 Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:03:06 +0100 Subject: [PATCH 21/22] S3 reduce bootloaders --- configs/builds.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/configs/builds.json b/configs/builds.json index 65b69cb9e..9c3061904 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -167,12 +167,10 @@ "features":[], "idf_libs":["qio","120m","opi_ram"], "bootloaders":[ - ["qio","120m","opi_ram"], ["qio","120m","qio_ram"], - ["qio","80m","qio_ram"], - ["opi","80m","opi_ram"], ["opi","120m","opi_ram"], - ["opi","120m","qio_ram"] + ["qio","80m","qio_ram"], + ["opi","80m","opi_ram"] ], "mem_variants":[ ["opi","120m","qio_ram"], From fabbc37592f9e7f95b8f510e0401941f44481f9b Mon Sep 17 00:00:00 2001 From: Jason2866 <24528715+Jason2866@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:21:32 +0100 Subject: [PATCH 22/22] add speed to mem variant folder for S3 (#124) --- build.sh | 14 ++++++++++++-- configs/builds.json | 9 +++++---- tools/copy-libs.sh | 9 +++++++-- tools/copy-mem-variant.sh | 5 +++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/build.sh b/build.sh index e96fc314b..7e9f92548 100755 --- a/build.sh +++ b/build.sh @@ -211,11 +211,17 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do # Build IDF Libs idf_libs_configs="$main_configs" + + # Extract frequency from idf_libs (element [1]) for esp32s3 + if [ "$target" = "esp32s3" ]; then + export MEM_VARIANT_FREQ=$(echo "$target_json" | jq -r '.idf_libs[1]') + fi + for defconf in `echo "$target_json" | jq -c '.idf_libs[]' | tr -d '"'`; do idf_libs_configs="$idf_libs_configs;configs/defconfig.$defconf" done - echo "* Build IDF-Libs: $idf_libs_configs" + echo "* Build IDF-Libs: $idf_libs_configs (freq: $MEM_VARIANT_FREQ)" rm -rf build sdkconfig idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$idf_libs_configs" idf-libs if [ $? -ne 0 ]; then exit 1; fi @@ -236,11 +242,15 @@ for target_json in `jq -c '.targets[]' configs/builds.json`; do # Build Memory Variants for mem_conf in `echo "$target_json" | jq -c '.mem_variants[]'`; do mem_configs="$main_configs" + + # Extract frequency from mem_variant (element [1]) + export MEM_VARIANT_FREQ=$(echo "$mem_conf" | jq -r '.[1]') + for defconf in `echo "$mem_conf" | jq -c '.[]' | tr -d '"'`; do mem_configs="$mem_configs;configs/defconfig.$defconf"; done - echo "* Build Memory Variant: $mem_configs" + echo "* Build Memory Variant: $mem_configs (freq: $MEM_VARIANT_FREQ)" rm -rf build sdkconfig idf.py -DIDF_TARGET="$target" -DSDKCONFIG_DEFAULTS="$mem_configs" mem-variant if [ $? -ne 0 ]; then exit 1; fi diff --git a/configs/builds.json b/configs/builds.json index 9c3061904..507f4ddbc 100644 --- a/configs/builds.json +++ b/configs/builds.json @@ -165,7 +165,7 @@ { "target": "esp32s3", "features":[], - "idf_libs":["qio","120m","opi_ram"], + "idf_libs":["qio","80m","qio_ram"], "bootloaders":[ ["qio","120m","qio_ram"], ["opi","120m","opi_ram"], @@ -173,10 +173,11 @@ ["opi","80m","opi_ram"] ], "mem_variants":[ - ["opi","120m","qio_ram"], + ["opi","80m","opi_ram"], + ["qio","80m","opi_ram"], + ["qio","120m","opi_ram"], ["opi","120m","opi_ram"], - ["qio","120m","qio_ram"], - ["qio","120m","opi_ram"] + ["qio","120m","qio_ram"] ] } ] diff --git a/tools/copy-libs.sh b/tools/copy-libs.sh index b55c810a2..283670abb 100755 --- a/tools/copy-libs.sh +++ b/tools/copy-libs.sh @@ -13,6 +13,11 @@ else fi MEMCONF=$OCT_FLASH"_$OCT_PSRAM" +# For esp32s3, add frequency from environment variable set by build.sh +if [ "$IDF_TARGET" = "esp32s3" ] && [ -n "$MEM_VARIANT_FREQ" ]; then + MEMCONF=$MEMCONF"_$MEM_VARIANT_FREQ" +fi + source ./tools/config.sh echo "IDF_TARGET: $IDF_TARGET, MEMCONF: $MEMCONF, PWD: $PWD, OUT: $AR_SDK" @@ -463,7 +468,7 @@ for item; do fi fi done -echo " join($PIO_SDK, board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_qspi\")), \"include\")," >> "$AR_PLATFORMIO_PY" +echo " join($PIO_SDK, (board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_qspi\")) + (\"_\" + board_config.get(\"build.f_boot\", board_config.get(\"build.f_flash\", \"80000000L\")).replace(\"000000L\", \"m\") if board_config.get(\"build.mcu\") == \"esp32s3\" else \"\")), \"include\")," >> "$AR_PLATFORMIO_PY" echo " join(FRAMEWORK_DIR, \"cores\", board_config.get(\"build.core\"))" >> "$AR_PLATFORMIO_PY" echo " ]," >> "$AR_PLATFORMIO_PY" echo "" >> "$AR_PLATFORMIO_PY" @@ -488,7 +493,7 @@ done echo " LIBPATH=[" >> "$AR_PLATFORMIO_PY" echo " join($PIO_SDK, \"lib\")," >> "$AR_PLATFORMIO_PY" echo " join($PIO_SDK, \"ld\")," >> "$AR_PLATFORMIO_PY" -echo " join($PIO_SDK, board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_qspi\")))" >> "$AR_PLATFORMIO_PY" +echo " join($PIO_SDK, (board_config.get(\"build.arduino.memory_type\", (board_config.get(\"build.flash_mode\", \"dio\") + \"_qspi\")) + (\"_\" + board_config.get(\"build.f_boot\", board_config.get(\"build.f_flash\", \"80000000L\")).replace(\"000000L\", \"m\") if board_config.get(\"build.mcu\") == \"esp32s3\" else \"\")))" >> "$AR_PLATFORMIO_PY" echo " ]," >> "$AR_PLATFORMIO_PY" echo "" >> "$AR_PLATFORMIO_PY" diff --git a/tools/copy-mem-variant.sh b/tools/copy-mem-variant.sh index 9b8f3b58e..2d81101e0 100755 --- a/tools/copy-mem-variant.sh +++ b/tools/copy-mem-variant.sh @@ -11,6 +11,11 @@ fi MEMCONF=$OCT_FLASH"_$OCT_PSRAM" +# For esp32s3, add frequency from environment variable set by build.sh +if [ "$IDF_TARGET" = "esp32s3" ] && [ -n "$MEM_VARIANT_FREQ" ]; then + MEMCONF=$MEMCONF"_$MEM_VARIANT_FREQ" +fi + source ./tools/config.sh echo "IDF_TARGET: $IDF_TARGET, MEMCONF: $MEMCONF"