From 91214b46142186b6c30ea468779c7ad39e1bc605 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 16 Jan 2025 10:46:37 +0700 Subject: zephyr --- src/osal/osal.h | 2 + src/osal/osal_zephyr.h | 123 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 src/osal/osal_zephyr.h (limited to 'src/osal') diff --git a/src/osal/osal.h b/src/osal/osal.h index 8f45ea5c1..38d45da44 100644 --- a/src/osal/osal.h +++ b/src/osal/osal.h @@ -63,6 +63,8 @@ typedef void (*osal_task_func_t)( void * ); #include "osal_rtthread.h" #elif CFG_TUSB_OS == OPT_OS_RTX4 #include "osal_rtx4.h" +#elif CFG_TUSB_OS == OPT_OS_ZEPHYR + #include "osal_zephyr.h" #elif CFG_TUSB_OS == OPT_OS_CUSTOM #include "tusb_os_custom.h" // implemented by application #else diff --git a/src/osal/osal_zephyr.h b/src/osal/osal_zephyr.h new file mode 100644 index 000000000..8ecb13c6d --- /dev/null +++ b/src/osal/osal_zephyr.h @@ -0,0 +1,123 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + */ +#ifndef TUSB_OSAL_ZEPHYR_H +#define TUSB_OSAL_ZEPHYR_H + +#include + +//--------------------------------------------------------------------+ +// TASK API +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { + k_msleep(msec); +} + +//--------------------------------------------------------------------+ +// Binary Semaphore API +//--------------------------------------------------------------------+ +typedef struct k_sem osal_semaphore_def_t, * osal_semaphore_t; + +TU_ATTR_ALWAYS_INLINE static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) { + k_sem_init(semdef, 0, 255); + return semdef; +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_delete(osal_semaphore_t semd_hdl) { + (void) semd_hdl; + return true; // nothing to do +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) { + (void) in_isr; + k_sem_give(sem_hdl); + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) { + return 0 == k_sem_take(sem_hdl, K_MSEC(msec)); +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t sem_hdl) { + k_sem_reset(sem_hdl); +} + +//--------------------------------------------------------------------+ +// MUTEX API +//--------------------------------------------------------------------+ +typedef struct k_mutex osal_mutex_def_t, *osal_mutex_t; + +TU_ATTR_ALWAYS_INLINE static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) { + if ( 0 == k_mutex_init(mdef) ) { + return mdef; + } else { + return NULL; + } +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_delete(osal_mutex_t mutex_hdl) { + (void) mutex_hdl; + return true; // nothing to do +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) { + return 0 == k_mutex_lock(mutex_hdl, K_MSEC(msec)); +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) { + return 0 == k_mutex_unlock(mutex_hdl); +} + +//--------------------------------------------------------------------+ +// QUEUE API +//--------------------------------------------------------------------+ +typedef struct k_msgq osal_queue_def_t, * osal_queue_t; + +// role device/host is used by OS NONE for mutex (disable usb isr) only +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) K_MSGQ_DEFINE(_name, sizeof(_type), _depth, 4) + +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { + // K_MSGQ_DEFINE already initializes the queue + return (osal_queue_t) qdef; +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { + (void) qhdl; + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { + return 0 == k_msgq_get(qhdl, data, K_MSEC(msec)); +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { + return 0 == k_msgq_put(qhdl, data, in_isr ? K_NO_WAIT : K_FOREVER); +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) { + return 0 == k_msgq_num_used_get(qhdl); +} + +#endif -- cgit v1.3.1 From 5a39bcf79ce564ce2b53b59223f9f384cba89d15 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Feb 2025 17:53:58 +0700 Subject: remove freeeRTOSConfig in examples --- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 191 --------------------- src/osal/osal_none.h | 24 +-- 2 files changed, 6 insertions(+), 209 deletions(-) delete mode 100644 examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h (limited to 'src/osal') diff --git a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index 902a54f08..000000000 --- a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * FreeRTOS Kernel V10.0.0 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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. If you wish to use our Amazon - * FreeRTOS name, please do so in a fair use way that does not cause confusion. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -// skip if included from IAR assembler -#ifndef __IASMARM__ - -// Include MCU header -#include "bsp/board_mcu.h" - -#if TUSB_MCU_VENDOR_ESPRESSIF - #error "ESP32-Sx should use IDF's FreeRTOSConfig.h" -#endif - -// TODO fix later -#if CFG_TUSB_MCU == OPT_MCU_MM32F327X - extern u32 SystemCoreClock; -#else - // FIXME cause redundant-decls warnings - extern uint32_t SystemCoreClock; -#endif - -#endif - -/* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) -#define configRUN_FREERTOS_SECURE_ONLY 1 - -#define configUSE_PREEMPTION 1 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#define configCPU_CLOCK_HZ SystemCoreClock -#define configTICK_RATE_HZ ( 1000 ) -#define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 4 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 - -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 - -/* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 -#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning -#define configCHECK_FOR_STACK_OVERFLOW 2 -#define configCHECK_HANDLER_INSTALLATION 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 1 // legacy trace -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) -#define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 0 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY -#define INCLUDE_xResumeFromISR 0 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_xTaskGetCurrentTaskHandle 0 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 -#define INCLUDE_pcTaskGetTaskName 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 0 -#define INCLUDE_xTimerPendFunctionCall 0 - -#ifdef __RX__ -/* Renesas RX series */ -#define vSoftwareInterruptISR INT_Excep_ICU_SWINT -#define vTickISR INT_Excep_CMT0_CMI0 -#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) -#define configKERNEL_INTERRUPT_PRIORITY 1 -#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 - -#else - -/* FreeRTOS hooks to NVIC vectors */ -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler -#define vPortSVCHandler SVC_Handler - -//--------------------------------------------------------------------+ -// Interrupt nesting behavior configuration. -//--------------------------------------------------------------------+ -#if defined(__NVIC_PRIO_BITS) - // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h - #define configPRIO_BITS __NVIC_PRIO_BITS - -#elif defined(__ECLIC_INTCTLBITS) - // RISC-V Bumblebee core from nuclei - #define configPRIO_BITS __ECLIC_INTCTLBITS - -#elif defined(__IASMARM__) - // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. - // Therefore we will hard coded it to minimum value of 2 to get pass ci build. - // IAR user must update this to correct value of the target MCU - #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" - #define configPRIO_BITS 2 - -#else - #error "FreeRTOS configPRIO_BITS to be defined" -#endif - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<interrupt_set(false); -} - -// unlock queue -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) { - // enable dcd/hcd interrupt - qhdl->interrupt_set(true); -} - TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; @@ -162,22 +150,22 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { (void) msec; // not used, always behave as msec = 0 - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); + qhdl->interrupt_set(false); + const bool success = tu_fifo_read(&qhdl->ff, data); + qhdl->interrupt_set(true); return success; } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { if (!in_isr) { - _osal_q_lock(qhdl); + qhdl->interrupt_set(false); } - bool success = tu_fifo_write(&qhdl->ff, data); + const bool success = tu_fifo_write(&qhdl->ff, data); if (!in_isr) { - _osal_q_unlock(qhdl); + qhdl->interrupt_set(true); } return success; -- cgit v1.3.1 From 72ee742761e5ed9cad29911ff19b8808972854ee Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 16 May 2025 20:09:02 +0700 Subject: 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(-) (limited to 'src/osal') 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; } @@ -102,9 +100,47 @@ TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) { } //--------------------------------------------------------------------+ -// Semaphore API +// 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) { -- cgit v1.3.1 From bb1d348eb3908543f7bc80fc462d91bba62edace Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 19 May 2025 22:51:40 +0700 Subject: 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(-) (limited to 'src/osal') 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 } -- cgit v1.3.1 From a4875fefead1a2b27f13a588dea44eaca737f553 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 20 May 2025 16:18:00 +0700 Subject: 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(-) (limited to 'src/osal') 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 } -- cgit v1.3.1 From c1d23a0a92bef016e22be3ed8194230cfab1c358 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 21 May 2025 11:19:07 +0700 Subject: 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(-) (limited to 'src/osal') 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 -- cgit v1.3.1