From 1742a982d517eda174fe85f3c27aebf9f8465744 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Thu, 20 Mar 2025 16:43:14 +0100 Subject: [PATCH] feat(freertos): Enable Amazon FreeRTOS SMP kernel for esp32c5 and esp32c61 This commit enables the Amazon SMP port for FreeRTOS for the esp32c5 and esp32c61 targets. --- .../riscv/include/freertos/portmacro.h | 53 +++++++++++-------- .../FreeRTOS-Kernel-SMP/portable/riscv/port.c | 28 ++++------ 2 files changed, 39 insertions(+), 42 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h index ba635dcfee..3cc6ec39c5 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/include/freertos/portmacro.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -78,9 +78,6 @@ typedef uint32_t TickType_t; #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) -// interrupt module will mask interrupt with priority less than threshold -#define RVHAL_EXCM_LEVEL 4 - /* ----------------------------------------------- Port Configurations ------------------------------------------------- * - Configurations values supplied by each port * - Required by FreeRTOS @@ -191,9 +188,22 @@ void vPortTCBPreDeleteHook( void *pxTCB ); // --------------------- Interrupts ------------------------ #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() -#define portENABLE_INTERRUPTS() vPortClearInterruptMask(1) +#if !SOC_INT_CLIC_SUPPORTED +#define portENABLE_INTERRUPTS() vPortClearInterruptMask(RVHAL_INTR_ENABLE_THRESH) +#else +#define portENABLE_INTERRUPTS() vPortClearInterruptMask(RVHAL_INTR_ENABLE_THRESH_CLIC) +#endif /* !SOC_INT_CLIC_SUPPORTED */ #define portRESTORE_INTERRUPTS(x) vPortClearInterruptMask(x) +#define portSET_INTERRUPT_MASK_FROM_ISR() ({ \ + unsigned int cur_level; \ + cur_level = ulPortSetInterruptMask(); \ + cur_level; \ +}) +#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portRESTORE_INTERRUPTS(x) +#define portSET_INTERRUPT_MASK() portSET_INTERRUPT_MASK_FROM_ISR() +#define portCLEAR_INTERRUPT_MASK(x) portCLEAR_INTERRUPT_MASK_FROM_ISR(x) + /** * @brief Assert if in ISR context * @@ -226,16 +236,8 @@ extern void vTaskExitCritical( void ); #define portEXIT_CRITICAL(...) CHOOSE_MACRO_VA_ARG(portEXIT_CRITICAL_IDF, portEXIT_CRITICAL_SMP, ##__VA_ARGS__)(__VA_ARGS__) #endif -#define portSET_INTERRUPT_MASK_FROM_ISR() ({ \ - unsigned int cur_level; \ - cur_level = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG); \ - vTaskEnterCritical(); \ - cur_level; \ -}) -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ({ \ - vTaskExitCritical(); \ - portRESTORE_INTERRUPTS(x); \ -}) +#define portENTER_CRITICAL_FROM_ISR() vTaskEnterCriticalFromISR() +#define portEXIT_CRITICAL_FROM_ISR(x) vTaskExitCriticalFromISR(x) // ---------------------- Yielding ------------------------- @@ -328,21 +330,26 @@ void vPortExitCritical(void); static inline bool IRAM_ATTR xPortCanYield(void) { - uint32_t threshold = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG); #if SOC_INT_CLIC_SUPPORTED - threshold = threshold >> (CLIC_CPU_INT_THRESH_S + (8 - NLBITS)); - - /* When CLIC is supported, the lowest interrupt threshold level is 0. - * Therefore, an interrupt threshold level above 0 would mean that we - * are either in a critical section or in an ISR. + /* When CLIC is supported: + * - The lowest interrupt threshold level is 0. Therefore, an interrupt threshold level above 0 would mean that we + * are in a critical section. + * - Since CLIC enables HW interrupt nesting, we do not have the updated interrupt level in the + * INTERRUPT_CURRENT_CORE_INT_THRESH_REG register when nested interrupts occur. To know the current interrupt + * level, we read the machine-mode interrupt level (mil) field from the mintstatus CSR. A non-zero value indicates + * that we are in an interrupt context. */ - return (threshold == 0); -#endif /* SOC_INT_CLIC_SUPPORTED */ + uint32_t threshold = rv_utils_get_interrupt_threshold(); + uint32_t intr_level = rv_utils_get_interrupt_level(); + return ((intr_level == 0) && (threshold == 0)); +#else/* !SOC_INT_CLIC_SUPPORTED */ + uint32_t threshold = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG); /* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL * and exit critical code, will recover threshold value (1). so threshold <= 1 * means not in critical code */ return (threshold <= 1); +#endif } // Defined even for configNUMBER_OF_CORES > 1 for IDF compatibility diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c index d08948517d..3bd684e44e 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel-SMP/portable/riscv/port.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -126,24 +126,14 @@ void vPortSetStackWatchpoint(void *pxStackStart) UBaseType_t ulPortSetInterruptMask(void) { - int ret; - unsigned old_xstatus; - -#if CONFIG_SECURE_ENABLE_TEE - old_xstatus = RV_CLEAR_CSR(ustatus, USTATUS_UIE); + UBaseType_t prev_int_level = 0, int_level = 0; +#if !SOC_INT_CLIC_SUPPORTED + int_level = RVHAL_EXCM_LEVEL; #else - // For non-secure configuration - old_xstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); + int_level = RVHAL_EXCM_LEVEL_CLIC; #endif - ret = REG_READ(INTERRUPT_CURRENT_CORE_INT_THRESH_REG); - REG_WRITE(INTERRUPT_CURRENT_CORE_INT_THRESH_REG, RVHAL_EXCM_LEVEL); - -#if CONFIG_SECURE_ENABLE_TEE - RV_SET_CSR(ustatus, old_xstatus & USTATUS_UIE); -#else - RV_SET_CSR(mstatus, old_xstatus & MSTATUS_MIE); -#endif + prev_int_level = rv_utils_set_intlevel_regval(int_level); /** * In theory, this function should not return immediately as there is a * delay between the moment we mask the interrupt threshold register and @@ -155,12 +145,12 @@ UBaseType_t ulPortSetInterruptMask(void) * followed by two instructions: `ret` and `csrrs` (RV_SET_CSR). * That's why we don't need any additional nop instructions here. */ - return ret; + return prev_int_level; } void vPortClearInterruptMask(UBaseType_t mask) { - REG_WRITE(INTERRUPT_CURRENT_CORE_INT_THRESH_REG, mask); + rv_utils_restore_intlevel_regval(mask); /** * The delay between the moment we unmask the interrupt threshold register * and the moment the potential requested interrupt is triggered is not @@ -312,7 +302,7 @@ BaseType_t xPortStartScheduler(void) /* Setup the hardware to generate the tick. */ vPortSetupTimer(); - esprv_int_set_threshold(1); /* set global INTC masking level */ + esprv_int_set_threshold(RVHAL_INTR_ENABLE_THRESH); /* set global interrupt masking level */ rv_utils_intr_global_enable(); vPortYield();