From c156e56684c3597c711b3c68cfba0d3951645191 Mon Sep 17 00:00:00 2001 From: Armando Date: Fri, 21 Jul 2023 11:36:28 +0800 Subject: [PATCH] feat(spinlock): added spinlock base support on p4 --- components/esp_hw_support/cpu.c | 25 +++++++++++++- components/esp_hw_support/include/spinlock.h | 34 ++++++++++++++++++-- components/riscv/include/riscv/rv_utils.h | 3 ++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/components/esp_hw_support/cpu.c b/components/esp_hw_support/cpu.c index 1e629c25f9..80ed61b5d5 100644 --- a/components/esp_hw_support/cpu.c +++ b/components/esp_hw_support/cpu.c @@ -466,8 +466,31 @@ exit: ret = xt_utils_compare_and_set(addr, compare_value, new_value); } return ret; -#else // __XTENSA__ + +//TODO: IDF-7771 +#else // __riscv +#if SOC_CPU_CORES_NUM > 1 + /* We use lr.w and sc.w pair for riscv TAS. lr.w will read the memory and register a cpu lock signal + * The state of the lock signal is internal to core, and it is not possible for another core to + * interface. sc.w will assert the address is registered. Then write memory and release the lock + * signal. During the lr.w and sc.w time, if other core acquires the same address, will wait + */ + volatile uint32_t old_value = 0xB33FFFFF; + volatile int error = 1; + + __asm__ __volatile__( + "0: lr.w %0, 0(%2) \n" + " bne %0, %3, 1f \n" + " sc.w %1, %4, 0(%2) \n" + " bnez %1, 0b \n" + "1: \n" + : "+r" (old_value), "+r" (error) + : "r" (addr), "r" (compare_value), "r" (new_value) + ); + return (old_value == compare_value); +#else // Single core targets don't have atomic CAS instruction. So access method is the same for internal and external RAM return rv_utils_compare_and_set(addr, compare_value, new_value); #endif +#endif } diff --git a/components/esp_hw_support/include/spinlock.h b/components/esp_hw_support/include/spinlock.h index ac5cb1ad52..3a5a3dcc4c 100644 --- a/components/esp_hw_support/include/spinlock.h +++ b/components/esp_hw_support/include/spinlock.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,8 +13,13 @@ #if __XTENSA__ #include "xtensa/xtruntime.h" #include "xt_utils.h" +#else +#include "riscv/rv_utils.h" #endif + +//TODO: IDF-7771, P4, see jira to know what changed and what need to be checked + #ifdef __cplusplus extern "C" { #endif @@ -72,11 +77,18 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l esp_cpu_cycle_count_t start_count; assert(lock); +#if __XTENSA__ irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); // Note: The core IDs are the full 32 bit (CORE_ID_REGVAL_PRO/CORE_ID_REGVAL_APP) values core_id = xt_utils_get_raw_core_id(); other_core_id = CORE_ID_REGVAL_XOR_SWAP ^ core_id; +#else //__riscv + irq_status = rv_utils_set_intlevel(RVHAL_EXCM_LEVEL); + + core_id = rv_utils_get_core_id(); + other_core_id = 1 - core_id; +#endif /* lock->owner should be one of SPINLOCK_FREE, CORE_ID_REGVAL_PRO, * CORE_ID_REGVAL_APP: @@ -89,7 +101,11 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l if (lock->owner == core_id) { assert(lock->count > 0 && lock->count < 0xFF); // Bad count value implies memory corruption lock->count++; +#if __XTENSA__ XTOS_RESTORE_INTLEVEL(irq_status); +#else + rv_utils_restore_intlevel(irq_status); +#endif return true; } @@ -126,7 +142,11 @@ exit: assert(lock->count < 0xFF); // Bad count value implies memory corruption } +#if __XTENSA__ XTOS_RESTORE_INTLEVEL(irq_status); +#else + rv_utils_restore_intlevel(irq_status); +#endif return lock_set; #else // !CONFIG_FREERTOS_UNICORE @@ -154,9 +174,15 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l uint32_t core_id; assert(lock); +#if __XTENSA__ irq_status = XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL); core_id = xt_utils_get_raw_core_id(); +#else + irq_status = rv_utils_set_intlevel(RVHAL_EXCM_LEVEL); + + core_id = rv_utils_get_core_id(); +#endif assert(core_id == lock->owner); // This is a lock that we didn't acquire, or the lock is corrupt lock->count--; @@ -166,8 +192,12 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l assert(lock->count < 0x100); // Indicates memory corruption } +#if __XTENSA__ XTOS_RESTORE_INTLEVEL(irq_status); -#endif +#else + rv_utils_restore_intlevel(irq_status); +#endif //#if __XTENSA__ +#endif //#if !CONFIG_FREERTOS_UNICORE && !BOOTLOADER_BUILD } #ifdef __cplusplus diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index 125f6caef5..e1525bd764 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -24,6 +24,9 @@ extern "C" { #define CSR_PCMR_MACHINE 0x7e1 #define CSR_PCCR_MACHINE 0x7e2 +//TODO: IDF-7771 +#define RVHAL_EXCM_LEVEL 4 + /* --------------------------------------------------- CPU Control ----------------------------------------------------- * * ------------------------------------------------------------------------------------------------------------------ */