From c8baba10f9a7a6150348618aec74719522887c93 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Wed, 9 Apr 2025 10:52:44 +0200 Subject: [PATCH 1/9] fix(dcd): Fixed race condition on device disconnect TinyUSB does not provide any locking means to protect the DCD variables. This can lead to race conditions when the user is trying to submit a transfer while the device is being disconnected. This can cause the device to be in an inconsistent state, leading to a crash or undefined behavior. This commit adds a spin-lock to protect the DCD variables during device disconnect. Closes https://github.com/espressif/esp-idf/issues/9691 Also reported in https://github.com/espressif/esp-usb/pull/131 --- src/portable/synopsys/dwc2/dcd_dwc2.c | 24 +++++++++++++++++++++ src/portable/synopsys/dwc2/dwc2_critical.h | 25 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/portable/synopsys/dwc2/dwc2_critical.h diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 52d675611..23273cb78 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -40,6 +40,7 @@ #include "device/dcd.h" #include "dwc2_common.h" +#include "dwc2_critical.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -52,6 +53,9 @@ typedef struct { 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]) @@ -321,6 +325,9 @@ static void edpt_disable(uint8_t rhport, uint8_t ep_addr, bool stall) { } } +// 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); @@ -531,6 +538,7 @@ 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; + DCD_ENTER_CRITICAL(); _dcd_data.allocated_epin_count = 0; // Disable non-control interrupt @@ -550,6 +558,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo + DCD_EXIT_CRITICAL(); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -568,7 +577,12 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + if (xfer->max_size == 0) { + DCD_EXIT_CRITICAL(); + return false; // Endpoint is closed + } xfer->buffer = buffer; xfer->ff = NULL; xfer->total_len = total_bytes; @@ -580,6 +594,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir); + DCD_EXIT_CRITICAL(); return true; } @@ -595,7 +610,12 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); + DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + if (xfer->max_size == 0) { + DCD_EXIT_CRITICAL(); + return false; // Endpoint is closed + } xfer->buffer = NULL; xfer->ff = ff; xfer->total_len = total_bytes; @@ -603,6 +623,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode edpt_schedule_packets(rhport, epnum, dir); + DCD_EXIT_CRITICAL(); return true; } @@ -631,6 +652,7 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) { //-------------------------------------------------------------------- // 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); @@ -989,8 +1011,10 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. + DCD_ENTER_CRITICAL(); dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); + DCD_EXIT_CRITICAL(); } if (gintsts & GINTSTS_ENUMDNE) { diff --git a/src/portable/synopsys/dwc2/dwc2_critical.h b/src/portable/synopsys/dwc2/dwc2_critical.h new file mode 100644 index 000000000..e2508c8fd --- /dev/null +++ b/src/portable/synopsys/dwc2/dwc2_critical.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef TUSB_DWC2_CRITICAL_H_ +#define TUSB_DWC2_CRITICAL_H_ + +#include "common/tusb_mcu.h" + +#if defined(TUP_USBIP_DWC2_ESP32) + #include "freertos/FreeRTOS.h" + static portMUX_TYPE dcd_lock = portMUX_INITIALIZER_UNLOCKED; + #define DCD_ENTER_CRITICAL() portENTER_CRITICAL(&dcd_lock) + #define DCD_EXIT_CRITICAL() portEXIT_CRITICAL(&dcd_lock) + +#else + // Define critical section macros for DWC2 as no-op if not defined + // This is to avoid breaking existing code that does not use critical section + #define DCD_ENTER_CRITICAL() // no-op + #define DCD_EXIT_CRITICAL() // no-op +#endif + +#endif // TUSB_DWC2_CRITICAL_H_ From 72ee742761e5ed9cad29911ff19b8808972854ee Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 May 2025 20:09:02 +0700 Subject: [PATCH 2/9] add osal_critical API() for use with dwc2 --- src/osal/osal_freertos.h | 84 +++++++++++++++++---------- src/osal/osal_none.h | 17 ++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 82 +++++++++++++++----------- 3 files changed, 116 insertions(+), 67 deletions(-) diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index a3a0f3a3f..ba998bfa1 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -42,20 +42,20 @@ extern "C" { //--------------------------------------------------------------------+ #if configSUPPORT_STATIC_ALLOCATION - typedef StaticSemaphore_t osal_semaphore_def_t; - typedef StaticSemaphore_t osal_mutex_def_t; +typedef StaticSemaphore_t osal_semaphore_def_t; +typedef StaticSemaphore_t osal_mutex_def_t; #else - // not used therefore defined to smallest possible type to save space - typedef uint8_t osal_semaphore_def_t; - typedef uint8_t osal_mutex_def_t; + +// not used therefore defined to the smallest possible type to save space +typedef uint8_t osal_semaphore_def_t; +typedef uint8_t osal_mutex_def_t; #endif typedef SemaphoreHandle_t osal_semaphore_t; typedef SemaphoreHandle_t osal_mutex_t; typedef QueueHandle_t osal_queue_t; -typedef struct -{ +typedef struct { uint16_t depth; uint16_t item_sz; void* buf; @@ -83,16 +83,14 @@ typedef struct //--------------------------------------------------------------------+ // TASK API //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline uint32_t _osal_ms2tick(uint32_t msec) { - if ( msec == OSAL_TIMEOUT_WAIT_FOREVER ) return portMAX_DELAY; - if ( msec == 0 ) return 0; + if (msec == OSAL_TIMEOUT_WAIT_FOREVER) { return portMAX_DELAY; } + if (msec == 0) { return 0; } uint32_t ticks = pdMS_TO_TICKS(msec); - // configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms - // we still need to delay at least 1 tick - if ( ticks == 0 ) ticks = 1; + // If configTICK_RATE_HZ is less than 1000 and 1 tick > 1 ms, we still need to delay at least 1 tick + if (ticks == 0) { ticks = 1; } return ticks; } @@ -101,10 +99,48 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { vTaskDelay(pdMS_TO_TICKS(msec)); } +//--------------------------------------------------------------------+ +// Critical API +//--------------------------------------------------------------------+ +#if TUSB_MCU_VENDOR_ESPRESSIF +// Espressif critical take spinlock as argument +typedef portMUX_TYPE osal_critical_t; + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + spinlock_initialize(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { + portENTER_CRITICAL(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { + portEXIT_CRITICAL(ctx); +} + +#else + +typedef uint8_t osal_critical_t; // not used + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { + (void) ctx; + portENTER_CRITICAL(); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { + (void) ctx; + portEXIT_CRITICAL(); +} + +#endif + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t *semdef) { #if configSUPPORT_STATIC_ALLOCATION return xSemaphoreCreateBinaryStatic(semdef); @@ -120,19 +156,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t } TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { - if ( !in_isr ) { + if (!in_isr) { return xSemaphoreGive(sem_hdl) != 0; } else { BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t res = xSemaphoreGiveFromISR(sem_hdl, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - return res != 0; } } @@ -148,7 +177,6 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t c //--------------------------------------------------------------------+ // MUTEX API (priority inheritance) //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t *mdef) { #if configSUPPORT_STATIC_ALLOCATION return xSemaphoreCreateMutexStatic(mdef); @@ -174,7 +202,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hd //--------------------------------------------------------------------+ // QUEUE API //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { osal_queue_t q; @@ -201,19 +228,12 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, v } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const *data, bool in_isr) { - if ( !in_isr ) { + if (!in_isr) { return xQueueSendToBack(qhdl, data, OSAL_TIMEOUT_WAIT_FOREVER) != 0; } else { BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t res = xQueueSendToBackFromISR(qhdl, data, &xHigherPriorityTaskWoken); - -#if CFG_TUSB_MCU == OPT_MCU_ESP32S2 || CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // not needed after https://github.com/espressif/esp-idf/commit/c5fd79547ac9b7bae06fa660e9f814d18d3390b7 (IDF v5) - if ( xHigherPriorityTaskWoken ) portYIELD_FROM_ISR(); -#else portYIELD_FROM_ISR(xHigherPriorityTaskWoken); -#endif - return res != 0; } } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 40e9bb83a..d9100cfdd 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -40,6 +40,23 @@ extern "C" { TU_ATTR_WEAK void osal_task_delay(uint32_t msec); #endif +//--------------------------------------------------------------------+ +// Critical API +//--------------------------------------------------------------------+ +typedef uint8_t osal_critical_t; // not used + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { + (void) ctx; +} + //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 23273cb78..5dd392409 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -40,7 +40,6 @@ #include "device/dcd.h" #include "dwc2_common.h" -#include "dwc2_critical.h" //--------------------------------------------------------------------+ // MACRO TYPEDEF CONSTANT ENUM @@ -53,12 +52,12 @@ typedef struct { uint8_t interval; } xfer_ctl_t; -/* -This variable is modified from ISR context, so it must be protected by critical section -*/ +// 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]) +static osal_critical_t _dcd_critical; + 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 @@ -394,6 +393,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); tu_memclr(&_dcd_data, sizeof(_dcd_data)); + osal_critical_init(&_dcd_critical); // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); @@ -538,7 +538,7 @@ 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; - DCD_ENTER_CRITICAL(); + osal_critical_enter(&_dcd_critical); _dcd_data.allocated_epin_count = 0; // Disable non-control interrupt @@ -558,7 +558,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -576,27 +576,33 @@ bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * p_endpo 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); - - DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + + bool ret; + + osal_critical_enter(&_dcd_critical); + if (xfer->max_size == 0) { - DCD_EXIT_CRITICAL(); - return false; // Endpoint is closed - } - xfer->buffer = buffer; - xfer->ff = NULL; - xfer->total_len = total_bytes; + 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; + // 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; } - // Schedule packets to be sent within interrupt - edpt_schedule_packets(rhport, epnum, dir); - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); - return true; + return ret; } // The number of bytes has to be given explicitly to allow more flexible control of how many @@ -609,23 +615,29 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - - DCD_ENTER_CRITICAL(); xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); + + bool ret; + + osal_critical_enter(&_dcd_critical); + if (xfer->max_size == 0) { - DCD_EXIT_CRITICAL(); - return false; // Endpoint is closed + 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; } - 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); - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); - return true; + return ret; } void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { @@ -1011,10 +1023,10 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. - DCD_ENTER_CRITICAL(); + osal_critical_enter(&_dcd_critical); dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); - DCD_EXIT_CRITICAL(); + osal_critical_exit(&_dcd_critical); } if (gintsts & GINTSTS_ENUMDNE) { From 9aea7751f292f40684d4533196037c26e2239934 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 May 2025 18:57:39 +0700 Subject: [PATCH 3/9] dwc2 only enter critical in isr with multiple core CPUs --- src/common/tusb_mcu.h | 7 +++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 14 ++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index a0175d664..6678265b5 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -369,6 +369,10 @@ #define TUP_DCD_ENDPOINT_MAX 7 // only 5 TX FIFO for endpoint IN #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #if CFG_TUSB_MCU == OPT_MCU_ESP32S3 + #define TUP_MCU_MULTIPLE_CORE 1 + #endif + // Disable slave if DMA is enabled #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE @@ -381,6 +385,8 @@ #define CFG_TUSB_OS_INC_PATH_DEFAULT freertos/ + #define TUP_MCU_MULTIPLE_CORE 1 + // Disable slave if DMA is enabled #define CFG_TUD_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUD_DWC2_DMA_ENABLE #define CFG_TUH_DWC2_SLAVE_ENABLE_DEFAULT !CFG_TUH_DWC2_DMA_ENABLE @@ -410,6 +416,7 @@ #elif TU_CHECK_MCU(OPT_MCU_RP2040) #define TUP_DCD_EDPT_ISO_ALLOC #define TUP_DCD_ENDPOINT_MAX 16 + #define TUP_MCU_MULTIPLE_CORE 1 #define TU_ATTR_FAST_FUNC __attribute__((section(".time_critical.tinyusb"))) diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 5dd392409..dc00ba82b 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -539,6 +539,7 @@ void dcd_edpt_close_all(uint8_t rhport) { uint8_t const ep_count = _dwc2_controller[rhport].ep_count; osal_critical_enter(&_dcd_critical); + _dcd_data.allocated_epin_count = 0; // Disable non-control interrupt @@ -556,8 +557,8 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_tx(dwc2, 0x10); // all tx fifo dfifo_flush_rx(dwc2); - dfifo_device_init(rhport); // re-init dfifo + osal_critical_exit(&_dcd_critical); } @@ -577,7 +578,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to 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; osal_critical_enter(&_dcd_critical); @@ -596,7 +596,6 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to // Schedule packets to be sent within interrupt edpt_schedule_packets(rhport, epnum, dir); - ret = true; } @@ -616,7 +615,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t 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; osal_critical_enter(&_dcd_critical); @@ -631,7 +629,6 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t // Schedule packets to be sent within interrupt // TODO xfer fifo may only available for slave mode edpt_schedule_packets(rhport, epnum, dir); - ret = true; } @@ -1017,16 +1014,21 @@ static void handle_ep_irq(uint8_t rhport, uint8_t dir) { */ 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. + #if TUP_MCU_MULTIPLE_CORE osal_critical_enter(&_dcd_critical); + #endif + dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); + + #if TUP_MCU_MULTIPLE_CORE osal_critical_exit(&_dcd_critical); + #endif } if (gintsts & GINTSTS_ENUMDNE) { From bffe5d97cc2f4f5a9ba8b4f09d30be97ce70a3de Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 May 2025 20:22:29 +0700 Subject: [PATCH 4/9] limit hil-hfp iar build to 4 parallel jobs --- .github/workflows/build.yml | 2 +- tools/build.py | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 28447cc80..fe2ed61c9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -266,7 +266,7 @@ jobs: run: python3 tools/get_deps.py $BUILD_ARGS - name: Build - run: python3 tools/build.py --toolchain iar $BUILD_ARGS + run: python3 tools/build.py -j 4 --toolchain iar $BUILD_ARGS - name: Test on actual hardware (hardware in the loop) run: python3 test/hil/hil_test.py hfp.json diff --git a/tools/build.py b/tools/build.py index d28ddd929..f2f6e6228 100755 --- a/tools/build.py +++ b/tools/build.py @@ -23,6 +23,7 @@ build_separator = '-' * 95 build_status = [STATUS_OK, STATUS_FAILED, STATUS_SKIPPED] verbose = False +parallel_jobs = os.cpu_count() # ----------------------------- # Helper @@ -110,13 +111,17 @@ def cmake_board(board, toolchain, build_flags_on): f'-DTOOLCHAIN={toolchain} {build_flags}') if rcmd.returncode == 0: cmd = f"cmake --build {build_dir}" - # circleci docker return $nproc as 36 core, limit parallel according to resource class. Required for IAR, also prevent crashed/killed by docker + njobs = parallel_jobs + + # circleci docker return $nproc as 36 core, limit parallel according to resource class. + # Required for IAR, also prevent crashed/killed by docker if os.getenv('CIRCLECI'): resource_class = { 'small': 1, 'medium': 2, 'medium+': 3, 'large': 4 } for rc in resource_class: if rc in os.getenv('CIRCLE_JOB'): - cmd += f' --parallel {resource_class[rc]}' + njobs = resource_class[rc] break + cmd += f' --parallel {njobs}' rcmd = run_cmd(cmd) ret[0 if rcmd.returncode == 0 else 1] += 1 @@ -211,6 +216,7 @@ def build_family(family, toolchain, build_system, build_flags_on, one_per_family # ----------------------------- def main(): global verbose + global parallel_jobs parser = argparse.ArgumentParser() parser.add_argument('families', nargs='*', default=[], help='Families to build') @@ -219,6 +225,7 @@ def main(): parser.add_argument('-s', '--build-system', default='cmake', help='Build system to use, default is cmake') parser.add_argument('-f1', '--build-flags-on', action='append', default=[], help='Build flag to pass to build system') parser.add_argument('-1', '--one-per-family', action='store_true', default=False, help='Build only one random board inside a family') + parser.add_argument('-j', '--jobs', type=int, default=os.cpu_count(), help='Number of jobs to run in parallel') parser.add_argument('-v', '--verbose', action='store_true', help='Verbose output') args = parser.parse_args() @@ -229,6 +236,7 @@ def main(): build_flags_on = args.build_flags_on one_per_family = args.one_per_family verbose = args.verbose + parallel_jobs = args.jobs if len(families) == 0 and len(boards) == 0: print("Please specify families or board to build") From bb1d348eb3908543f7bc80fc462d91bba62edace Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 May 2025 22:51:40 +0700 Subject: [PATCH 5/9] implement osal critical for none/freertos/pico-sdk --- src/device/usbd.c | 9 +++----- src/osal/osal_freertos.h | 30 +++++++++++++++++++-------- src/osal/osal_none.h | 19 ++++++++++++----- src/osal/osal_pico.h | 21 +++++++++++++++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 19 +++++++++-------- 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 9c381d5e0..32de8740b 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1242,13 +1242,10 @@ TU_ATTR_FAST_FUNC void dcd_event_handler(dcd_event_t const* event, bool in_isr) // USBD API For Class Driver //--------------------------------------------------------------------+ -void usbd_int_set(bool enabled) -{ - if (enabled) - { +void usbd_int_set(bool enabled) { + if (enabled) { dcd_int_enable(_usbd_rhport); - }else - { + } else { dcd_int_disable(_usbd_rhport); } } diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index ba998bfa1..5d6534709 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -102,38 +102,50 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { //--------------------------------------------------------------------+ // Critical API //--------------------------------------------------------------------+ +#define OSAL_CRITIAL_DEF(_name, _int_set) \ + osal_critical_t _name + #if TUSB_MCU_VENDOR_ESPRESSIF -// Espressif critical take spinlock as argument +// Espressif critical take spinlock as argument and does not use in_isr typedef portMUX_TYPE osal_critical_t; TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { spinlock_initialize(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; portENTER_CRITICAL(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; portEXIT_CRITICAL(ctx); } #else -typedef uint8_t osal_critical_t; // not used +typedef UBaseType_t osal_critical_t; TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { - (void) ctx; - portENTER_CRITICAL(); +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + if (in_isr) { + *ctx = taskENTER_CRITICAL_FROM_ISR(); + } else { + taskENTER_CRITICAL(); + } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { (void) ctx; - portEXIT_CRITICAL(); + if (in_isr) { + taskEXIT_CRITICAL_FROM_ISR(*ctx); + } else { + taskEXIT_CRITICAL(); + } } #endif diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index d9100cfdd..05a121ae6 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -43,18 +43,27 @@ TU_ATTR_WEAK void osal_task_delay(uint32_t msec); //--------------------------------------------------------------------+ // Critical API //--------------------------------------------------------------------+ -typedef uint8_t osal_critical_t; // not used +typedef struct { + void (* interrupt_set)(bool); +} osal_critical_t; + +#define OSAL_CRITIAL_DEF(_name, _int_set) \ + osal_critical_t _name = { .interrupt_set = _int_set } TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx) { - (void) ctx; +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + if (!in_isr) { + ctx->interrupt_set(false); + } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx) { - (void) ctx; +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { + if (!in_isr) { + ctx->interrupt_set(true); + } } //--------------------------------------------------------------------+ diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index 315de0950..be631ed18 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -43,6 +43,27 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { sleep_ms(msec); } +//--------------------------------------------------------------------+ +// Critical API +//--------------------------------------------------------------------+ +typedef critical_section_t osal_critical_t; +#define OSAL_CRITIAL_DEF(_name, _int_set) \ + osal_critical_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { + critical_section_init(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; + critical_section_enter_blocking(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { + (void) in_isr; + critical_section_exit(ctx); +} + //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index dc00ba82b..4a2dad69e 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -39,6 +39,7 @@ #define DWC2_DEBUG 2 #include "device/dcd.h" +#include "device/usbd_pvt.h" #include "dwc2_common.h" //--------------------------------------------------------------------+ @@ -56,7 +57,7 @@ typedef struct { static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) -static osal_critical_t _dcd_critical; +static OSAL_CRITIAL_DEF(_dcd_critical, usbd_int_set); typedef struct { // EP0 transfers are limited to 1 packet - larger sizes has to be split @@ -538,7 +539,7 @@ 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; - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, false); _dcd_data.allocated_epin_count = 0; @@ -559,7 +560,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, false); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -580,7 +581,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -599,7 +600,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, false); return ret; } @@ -617,7 +618,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -632,7 +633,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, false); return ret; } @@ -1020,14 +1021,14 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. #if TUP_MCU_MULTIPLE_CORE - osal_critical_enter(&_dcd_critical); + osal_critical_enter(&_dcd_critical, true); #endif dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); #if TUP_MCU_MULTIPLE_CORE - osal_critical_exit(&_dcd_critical); + osal_critical_exit(&_dcd_critical, true); #endif } From a4875fefead1a2b27f13a588dea44eaca737f553 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 20 May 2025 16:18:00 +0700 Subject: [PATCH 6/9] rename osal_critcal to osal_spinlock add spinlock implementation for most rtos --- src/osal/osal.h | 4 ++++ src/osal/osal_freertos.h | 22 +++++++++++----------- src/osal/osal_mynewt.h | 22 ++++++++++++++++++++++ src/osal/osal_none.h | 15 ++++++++------- src/osal/osal_pico.h | 14 +++++++------- src/osal/osal_rtthread.h | 22 ++++++++++++++++++++++ src/osal/osal_rtx4.h | 19 +++++++++++++++++++ src/osal/osal_zephyr.h | 25 +++++++++++++++++++++++++ src/portable/synopsys/dwc2/dcd_dwc2.c | 20 ++++++++++---------- 9 files changed, 128 insertions(+), 35 deletions(-) diff --git a/src/osal/osal.h b/src/osal/osal.h index 38d45da44..a33280425 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -75,6 +75,10 @@ typedef void (*osal_task_func_t)( void * ); // OSAL Porting API // Should be implemented as static inline function in osal_port.h header /* + void osal_spin_init(osal_spinlock_t *ctx); + void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) + void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr); + osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef); bool osal_semaphore_delete(osal_semaphore_t semd_hdl); bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr); diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 5d6534709..09b6cb338 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -100,38 +100,38 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { } //--------------------------------------------------------------------+ -// Critical API +// Spinlock API //--------------------------------------------------------------------+ -#define OSAL_CRITIAL_DEF(_name, _int_set) \ - osal_critical_t _name +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name #if TUSB_MCU_VENDOR_ESPRESSIF // Espressif critical take spinlock as argument and does not use in_isr -typedef portMUX_TYPE osal_critical_t; +typedef portMUX_TYPE osal_spinlock_t; -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { spinlock_initialize(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; portENTER_CRITICAL(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; portEXIT_CRITICAL(ctx); } #else -typedef UBaseType_t osal_critical_t; +typedef UBaseType_t osal_spinlock_t; -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { if (in_isr) { *ctx = taskENTER_CRITICAL_FROM_ISR(); } else { @@ -139,7 +139,7 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ct } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { (void) ctx; if (in_isr) { taskEXIT_CRITICAL_FROM_ISR(*ctx); diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index 16def0d2a..58d226b10 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -40,6 +40,28 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { os_time_delay( os_time_ms_to_ticks32(msec) ); } +//--------------------------------------------------------------------+ +// Spinlock API +//--------------------------------------------------------------------+ +typedef os_sr_t osal_spinlock_t; + +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + OS_ENTER_CRITICAL(*ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + OS_ENTER_CRITICAL(*ctx); +} + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 05a121ae6..2a0170ba4 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -41,26 +41,27 @@ TU_ATTR_WEAK void osal_task_delay(uint32_t msec); #endif //--------------------------------------------------------------------+ -// Critical API +// Spinlock API //--------------------------------------------------------------------+ typedef struct { void (* interrupt_set)(bool); -} osal_critical_t; +} osal_spinlock_t; -#define OSAL_CRITIAL_DEF(_name, _int_set) \ - osal_critical_t _name = { .interrupt_set = _int_set } +// For SMP, spinlock must be locked by hardware, not use interrupt +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name = { .interrupt_set = _int_set } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { (void) ctx; } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { if (!in_isr) { ctx->interrupt_set(false); } } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { if (!in_isr) { ctx->interrupt_set(true); } diff --git a/src/osal/osal_pico.h b/src/osal/osal_pico.h index be631ed18..ace5907d7 100644 --- a/src/osal/osal_pico.h +++ b/src/osal/osal_pico.h @@ -44,22 +44,22 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { } //--------------------------------------------------------------------+ -// Critical API +// Spinlock API //--------------------------------------------------------------------+ -typedef critical_section_t osal_critical_t; -#define OSAL_CRITIAL_DEF(_name, _int_set) \ - osal_critical_t _name +typedef critical_section_t osal_spinlock_t; // pico implement critical section with spinlock +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_init(osal_critical_t *ctx) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { critical_section_init(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_enter(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; critical_section_enter_blocking(ctx); } -TU_ATTR_ALWAYS_INLINE static inline void osal_critical_exit(osal_critical_t *ctx, bool in_isr) { +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { (void) in_isr; critical_section_exit(ctx); } diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h index c27814835..97f5dc69a 100644 --- a/src/osal/osal_rtthread.h +++ b/src/osal/osal_rtthread.h @@ -42,6 +42,28 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { rt_thread_mdelay(msec); } +//--------------------------------------------------------------------+ +// Spinlock API +//--------------------------------------------------------------------+ +typedef struct rt_spinlock osal_spinlock_t; + +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + rt_spin_lock_init(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + rt_spin_lock(ctx); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + rt_spin_unlock(ctx); +} + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_rtx4.h b/src/osal/osal_rtx4.h index 35909e4d6..35860ddd5 100644 --- a/src/osal/osal_rtx4.h +++ b/src/osal/osal_rtx4.h @@ -56,6 +56,25 @@ TU_ATTR_ALWAYS_INLINE static inline uint16_t msec2wait(uint32_t msec) { } } +//--------------------------------------------------------------------+ +// Spinlock API, stub not implemented +//--------------------------------------------------------------------+ +typedef uint8_t osal_spinlock_t; +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) ctx; (void) in_isr; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) ctx; (void) in_isr; +} + //--------------------------------------------------------------------+ // Semaphore API //--------------------------------------------------------------------+ diff --git a/src/osal/osal_zephyr.h b/src/osal/osal_zephyr.h index 8ecb13c6d..7a43b8ec1 100644 --- a/src/osal/osal_zephyr.h +++ b/src/osal/osal_zephyr.h @@ -35,6 +35,31 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { k_msleep(msec); } +//--------------------------------------------------------------------+ +// Spinlock API +//--------------------------------------------------------------------+ +typedef struct { + struct k_spinlock lock; + k_spinlock_key_t key; +} osal_spinlock_t; + +#define OSAL_SPINLOCK_DEF(_name, _int_set) \ + osal_spinlock_t _name + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { + (void) ctx; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + ctx->key = k_spin_lock(&ctx->lock); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { + (void) in_isr; + k_spin_unlock(&ctx->lock, ctx->key); +} + //--------------------------------------------------------------------+ // Binary Semaphore API //--------------------------------------------------------------------+ diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 4a2dad69e..67484c3df 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -57,7 +57,7 @@ typedef struct { static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) -static OSAL_CRITIAL_DEF(_dcd_critical, usbd_int_set); +static OSAL_SPINLOCK_DEF(_dcd_spinlock, usbd_int_set); typedef struct { // EP0 transfers are limited to 1 packet - larger sizes has to be split @@ -394,7 +394,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); tu_memclr(&_dcd_data, sizeof(_dcd_data)); - osal_critical_init(&_dcd_critical); + osal_spin_init(&_dcd_spinlock); // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); @@ -539,7 +539,7 @@ 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; - osal_critical_enter(&_dcd_critical, false); + osal_spin_lock(&_dcd_spinlock, false); _dcd_data.allocated_epin_count = 0; @@ -560,7 +560,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - osal_critical_exit(&_dcd_critical, false); + osal_spin_unlock(&_dcd_spinlock, false); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -581,7 +581,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical, false); + osal_spin_lock(&_dcd_spinlock, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -600,7 +600,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - osal_critical_exit(&_dcd_critical, false); + osal_spin_unlock(&_dcd_spinlock, false); return ret; } @@ -618,7 +618,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_critical_enter(&_dcd_critical, false); + osal_spin_lock(&_dcd_spinlock, false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -633,7 +633,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - osal_critical_exit(&_dcd_critical, false); + osal_spin_unlock(&_dcd_spinlock, false); return ret; } @@ -1021,14 +1021,14 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. #if TUP_MCU_MULTIPLE_CORE - osal_critical_enter(&_dcd_critical, true); + osal_spin_lock(&_dcd_spinlock, true); #endif dwc2->gintsts = GINTSTS_USBRST; handle_bus_reset(rhport); #if TUP_MCU_MULTIPLE_CORE - osal_critical_exit(&_dcd_critical, true); + osal_spin_unlock(&_dcd_spinlock, true); #endif } From c1d23a0a92bef016e22be3ed8194230cfab1c358 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 11:19:07 +0700 Subject: [PATCH 7/9] osal_spin skipping lock/unlock when executed in isr --- src/osal/osal_freertos.h | 17 ++++++++++++++--- src/osal/osal_mynewt.h | 8 ++++++-- src/osal/osal_none.h | 2 +- src/osal/osal_rtthread.h | 8 ++++++-- src/osal/osal_zephyr.h | 8 ++++++-- src/portable/synopsys/dwc2/dcd_dwc2.c | 9 ++------- src/portable/synopsys/dwc2/dwc2_esp32.h | 4 ++-- 7 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/osal/osal_freertos.h b/src/osal/osal_freertos.h index 09b6cb338..bde5ec010 100644 --- a/src/osal/osal_freertos.h +++ b/src/osal/osal_freertos.h @@ -114,12 +114,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } portENTER_CRITICAL(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } portEXIT_CRITICAL(ctx); } @@ -133,6 +137,10 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { if (in_isr) { + if (!TUP_MCU_MULTIPLE_CORE) { + (void) ctx; + return; // single core MCU does not need to lock in ISR + } *ctx = taskENTER_CRITICAL_FROM_ISR(); } else { taskENTER_CRITICAL(); @@ -140,8 +148,11 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bo } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) ctx; if (in_isr) { + if (!TUP_MCU_MULTIPLE_CORE) { + (void) ctx; + return; // single core MCU does not need to lock in ISR + } taskEXIT_CRITICAL_FROM_ISR(*ctx); } else { taskEXIT_CRITICAL(); diff --git a/src/osal/osal_mynewt.h b/src/osal/osal_mynewt.h index 58d226b10..ee95e684f 100644 --- a/src/osal/osal_mynewt.h +++ b/src/osal/osal_mynewt.h @@ -53,12 +53,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } OS_ENTER_CRITICAL(*ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } OS_ENTER_CRITICAL(*ctx); } diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h index 2a0170ba4..a8eb1042b 100644 --- a/src/osal/osal_none.h +++ b/src/osal/osal_none.h @@ -47,7 +47,7 @@ typedef struct { void (* interrupt_set)(bool); } osal_spinlock_t; -// For SMP, spinlock must be locked by hardware, not use interrupt +// For SMP, spinlock must be locked by hardware, cannot just use interrupt #define OSAL_SPINLOCK_DEF(_name, _int_set) \ osal_spinlock_t _name = { .interrupt_set = _int_set } diff --git a/src/osal/osal_rtthread.h b/src/osal/osal_rtthread.h index 97f5dc69a..a778f5425 100644 --- a/src/osal/osal_rtthread.h +++ b/src/osal/osal_rtthread.h @@ -55,12 +55,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } rt_spin_lock(ctx); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } rt_spin_unlock(ctx); } diff --git a/src/osal/osal_zephyr.h b/src/osal/osal_zephyr.h index 7a43b8ec1..91f225f79 100644 --- a/src/osal/osal_zephyr.h +++ b/src/osal/osal_zephyr.h @@ -51,12 +51,16 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_spin_init(osal_spinlock_t *ctx) { } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_lock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } ctx->key = k_spin_lock(&ctx->lock); } TU_ATTR_ALWAYS_INLINE static inline void osal_spin_unlock(osal_spinlock_t *ctx, bool in_isr) { - (void) in_isr; + if (!TUP_MCU_MULTIPLE_CORE && in_isr) { + return; // single core MCU does not need to lock in ISR + } k_spin_unlock(&ctx->lock, ctx->key); } diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 67484c3df..19eac6e15 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -1020,16 +1020,11 @@ void dcd_int_handler(uint8_t rhport) { if (gintsts & GINTSTS_USBRST) { // USBRST is start of reset. - #if TUP_MCU_MULTIPLE_CORE - osal_spin_lock(&_dcd_spinlock, true); - #endif - dwc2->gintsts = GINTSTS_USBRST; - handle_bus_reset(rhport); - #if TUP_MCU_MULTIPLE_CORE + osal_spin_lock(&_dcd_spinlock, true); + handle_bus_reset(rhport); osal_spin_unlock(&_dcd_spinlock, true); - #endif } if (gintsts & GINTSTS_ENUMDNE) { diff --git a/src/portable/synopsys/dwc2/dwc2_esp32.h b/src/portable/synopsys/dwc2/dwc2_esp32.h index 3309760ff..49b8c54cb 100644 --- a/src/portable/synopsys/dwc2/dwc2_esp32.h +++ b/src/portable/synopsys/dwc2/dwc2_esp32.h @@ -55,8 +55,8 @@ static const dwc2_controller_t _dwc2_controller[] = { // On ESP32 for consistency we associate // - Port0 to OTG_FS, and Port1 to OTG_HS static const dwc2_controller_t _dwc2_controller[] = { -{ .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_OTG11_CH0_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 }, -{ .reg_base = DWC2_HS_REG_BASE, .irqnum = ETS_USB_OTG_INTR_SOURCE, .ep_count = 16, .ep_in_count = 8, .ep_fifo_size = 4096 } + { .reg_base = DWC2_FS_REG_BASE, .irqnum = ETS_USB_OTG11_CH0_INTR_SOURCE, .ep_count = 7, .ep_in_count = 5, .ep_fifo_size = 1024 }, + { .reg_base = DWC2_HS_REG_BASE, .irqnum = ETS_USB_OTG_INTR_SOURCE, .ep_count = 16, .ep_in_count = 8, .ep_fifo_size = 4096 } }; #endif From 5551a3e430c1a330ec2a09121abc79fbb7b3c7b0 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 11:41:06 +0700 Subject: [PATCH 8/9] add usbd_spin_lock/unlock for driver usage --- src/device/usbd.c | 22 ++++++++++++++++------ src/device/usbd_pvt.h | 2 ++ src/portable/synopsys/dwc2/dcd_dwc2.c | 19 ++++++++----------- 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/device/usbd.c b/src/device/usbd.c index 32de8740b..6e5fcf3b6 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -340,15 +340,16 @@ TU_ATTR_ALWAYS_INLINE static inline usbd_class_driver_t const * get_driver(uint8 enum { RHPORT_INVALID = 0xFFu }; tu_static uint8_t _usbd_rhport = RHPORT_INVALID; -// Event queue -// usbd_int_set() is used as mutex in OS NONE config +static OSAL_SPINLOCK_DEF(_usbd_spin, usbd_int_set); + +// Event queue: usbd_int_set() is used as mutex in OS NONE config OSAL_QUEUE_DEF(usbd_int_set, _usbd_qdef, CFG_TUD_TASK_QUEUE_SZ, dcd_event_t); -tu_static osal_queue_t _usbd_q; +static osal_queue_t _usbd_q; // Mutex for claiming endpoint #if OSAL_MUTEX_REQUIRED - tu_static osal_mutex_def_t _ubsd_mutexdef; - tu_static osal_mutex_t _usbd_mutex; + static osal_mutex_def_t _ubsd_mutexdef; + static osal_mutex_t _usbd_mutex; #else #define _usbd_mutex NULL #endif @@ -466,7 +467,7 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { TU_ASSERT(rh_init); TU_LOG_USBD("USBD init on controller %u, speed = %s\r\n", rhport, - rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full"); + rh_init->speed == TUSB_SPEED_HIGH ? "High" : "Full"); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(usbd_device_t)); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(dcd_event_t)); TU_LOG_INT(CFG_TUD_LOG_LEVEL, sizeof(tu_fifo_t)); @@ -475,6 +476,8 @@ bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_varclr(&_usbd_dev); _usbd_queued_setup = 0; + osal_spin_init(&_usbd_spin); + #if OSAL_MUTEX_REQUIRED // Init device mutex _usbd_mutex = osal_mutex_create(&_ubsd_mutexdef); @@ -1250,6 +1253,13 @@ void usbd_int_set(bool enabled) { } } +void usbd_spin_lock(bool in_isr) { + osal_spin_lock(&_usbd_spin, in_isr); +} +void usbd_spin_unlock(bool in_isr) { + osal_spin_unlock(&_usbd_spin, in_isr); +} + // Parse consecutive endpoint descriptors (IN & OUT) bool usbd_open_edpt_pair(uint8_t rhport, uint8_t const* p_desc, uint8_t ep_count, uint8_t xfer_type, uint8_t* ep_out, uint8_t* ep_in) { diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index 190d6fd7f..5c6f9dbee 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -68,6 +68,8 @@ usbd_class_driver_t const* usbd_app_driver_get_cb(uint8_t* driver_count) TU_ATTR typedef bool (*usbd_control_xfer_cb_t)(uint8_t rhport, uint8_t stage, tusb_control_request_t const * request); void usbd_int_set(bool enabled); +void usbd_spin_lock(bool in_isr); +void usbd_spin_unlock(bool in_isr); //--------------------------------------------------------------------+ // USBD Endpoint API diff --git a/src/portable/synopsys/dwc2/dcd_dwc2.c b/src/portable/synopsys/dwc2/dcd_dwc2.c index 19eac6e15..865c51894 100644 --- a/src/portable/synopsys/dwc2/dcd_dwc2.c +++ b/src/portable/synopsys/dwc2/dcd_dwc2.c @@ -57,8 +57,6 @@ typedef struct { static xfer_ctl_t xfer_status[DWC2_EP_MAX][2]; #define XFER_CTL_BASE(_ep, _dir) (&xfer_status[_ep][_dir]) -static OSAL_SPINLOCK_DEF(_dcd_spinlock, usbd_int_set); - 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 @@ -394,7 +392,6 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dwc2_regs_t* dwc2 = DWC2_REG(rhport); tu_memclr(&_dcd_data, sizeof(_dcd_data)); - osal_spin_init(&_dcd_spinlock); // Core Initialization const bool is_highspeed = dwc2_core_is_highspeed(dwc2, TUSB_ROLE_DEVICE); @@ -539,7 +536,7 @@ 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; - osal_spin_lock(&_dcd_spinlock, false); + usbd_spin_lock(false); _dcd_data.allocated_epin_count = 0; @@ -560,7 +557,7 @@ void dcd_edpt_close_all(uint8_t rhport) { dfifo_flush_rx(dwc2); dfifo_device_init(rhport); // re-init dfifo - osal_spin_unlock(&_dcd_spinlock, false); + usbd_spin_unlock(false); } bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet_size) { @@ -581,7 +578,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_spin_lock(&_dcd_spinlock, false); + usbd_spin_lock(false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -600,7 +597,7 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to ret = true; } - osal_spin_unlock(&_dcd_spinlock, false); + usbd_spin_unlock(false); return ret; } @@ -618,7 +615,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t xfer_ctl_t* xfer = XFER_CTL_BASE(epnum, dir); bool ret; - osal_spin_lock(&_dcd_spinlock, false); + usbd_spin_lock(false); if (xfer->max_size == 0) { ret = false; // Endpoint is closed @@ -633,7 +630,7 @@ bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t* ff, uint16_t ret = true; } - osal_spin_unlock(&_dcd_spinlock, false); + usbd_spin_unlock(false); return ret; } @@ -1022,9 +1019,9 @@ void dcd_int_handler(uint8_t rhport) { // USBRST is start of reset. dwc2->gintsts = GINTSTS_USBRST; - osal_spin_lock(&_dcd_spinlock, true); + usbd_spin_lock(true); handle_bus_reset(rhport); - osal_spin_unlock(&_dcd_spinlock, true); + usbd_spin_unlock(true); } if (gintsts & GINTSTS_ENUMDNE) { From 58dfc126ac96d151bc6a9e9ee8bda564b52c350f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 14:36:53 +0700 Subject: [PATCH 9/9] remove unused dwc2_critical.h --- src/portable/synopsys/dwc2/dwc2_critical.h | 25 ---------------------- 1 file changed, 25 deletions(-) delete mode 100644 src/portable/synopsys/dwc2/dwc2_critical.h diff --git a/src/portable/synopsys/dwc2/dwc2_critical.h b/src/portable/synopsys/dwc2/dwc2_critical.h deleted file mode 100644 index e2508c8fd..000000000 --- a/src/portable/synopsys/dwc2/dwc2_critical.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef TUSB_DWC2_CRITICAL_H_ -#define TUSB_DWC2_CRITICAL_H_ - -#include "common/tusb_mcu.h" - -#if defined(TUP_USBIP_DWC2_ESP32) - #include "freertos/FreeRTOS.h" - static portMUX_TYPE dcd_lock = portMUX_INITIALIZER_UNLOCKED; - #define DCD_ENTER_CRITICAL() portENTER_CRITICAL(&dcd_lock) - #define DCD_EXIT_CRITICAL() portEXIT_CRITICAL(&dcd_lock) - -#else - // Define critical section macros for DWC2 as no-op if not defined - // This is to avoid breaking existing code that does not use critical section - #define DCD_ENTER_CRITICAL() // no-op - #define DCD_EXIT_CRITICAL() // no-op -#endif - -#endif // TUSB_DWC2_CRITICAL_H_