From 03f4744497e0389aa25b57c5fdcbf581276fc145 Mon Sep 17 00:00:00 2001 From: Omar Chebib Date: Tue, 29 Jul 2025 09:39:16 +0800 Subject: [PATCH] feat(riscv): add support for the DSP coprocessor --- .../FreeRTOS-Kernel/portable/riscv/port.c | 6 +- .../FreeRTOS-Kernel/portable/riscv/portasm.S | 68 +++++++++++++++++++ components/riscv/include/riscv/csr_dsp.h | 27 ++++++++ components/riscv/include/riscv/rv_utils.h | 23 ++++++- .../riscv/include/riscv/rvruntime-frames.h | 32 ++++++++- components/riscv/vectors.S | 18 ++--- .../esp32h4/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32h4/include/soc/soc_caps.h | 1 + 8 files changed, 168 insertions(+), 11 deletions(-) create mode 100644 components/riscv/include/riscv/csr_dsp.h diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c index e5dbf8238c..8e67e71af4 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c @@ -136,7 +136,11 @@ BaseType_t xPortStartScheduler(void) #if SOC_CPU_HAS_PIE /* Similarly, disable PIE */ rv_utils_disable_pie(); -#endif /* SOC_CPU_HAS_FPU */ +#endif /* SOC_CPU_HAS_PIE */ + +#if SOC_CPU_HAS_DSP + rv_utils_disable_dsp(); +#endif /* SOC_CPU_HAS_DSP */ #if SOC_CPU_HAS_HWLOOP /* Initialize the Hardware loop feature */ diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/portasm.S b/components/freertos/FreeRTOS-Kernel/portable/riscv/portasm.S index 1bccf990c6..667c68c9a8 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/portasm.S +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/portasm.S @@ -10,6 +10,7 @@ #include "riscv/rvruntime-frames.h" #include "riscv/csr_hwlp.h" #include "riscv/csr_pie.h" +#include "riscv/csr_dsp.h" .extern pxCurrentTCBs @@ -329,6 +330,59 @@ generate_coprocessor_routine pie, PIE_COPROC_IDX, pie_enable, pie_save_regs, pie #endif /* SOC_CPU_HAS_PIE */ +#if SOC_CPU_HAS_DSP + +/** + * @brief Macros to enable and disable the DSP coprocessor on the current core + */ +.macro dsp_enable scratch_reg=a0 + li \scratch_reg, 1 + csrw CSR_DSP_STATE_REG, \scratch_reg +.endm + +/** + * @brief Disable the DSP coprocessor while returning the former status in the given register + */ +.macro dsp_disable reg + csrrw \reg, CSR_DSP_STATE_REG, zero + /* Only keep the lowest two bits, if register is 0, DSP was off */ + andi \reg, \reg, 0b11 + beqz \reg, 1f + /* It was ON, return the enable bit in \reg */ + li \reg, 1 << DSP_COPROC_IDX +1: +.endm + +/** + * @brief Macros to save and restore the DSP coprocessor registers to and from the given frame + */ +.macro dsp_save_regs frame=a0 + csrr a1, CSR_DSP_XACC_L + sw a1, RV_DSP_XACC_L(\frame) + csrr a1, CSR_DSP_XACC_H + sw a1, RV_DSP_XACC_H(\frame) + csrr a1, CSR_DSP_SAR + sw a1, RV_DSP_SAR(\frame) + csrr a1, CSR_DSP_STATUS + sw a1, RV_DSP_STATUS(\frame) +.endm + + +.macro dsp_restore_regs frame=a0 + lw a1, RV_DSP_XACC_L(\frame) + csrw CSR_DSP_XACC_L, a1 + lw a1, RV_DSP_XACC_H(\frame) + csrw CSR_DSP_XACC_H, a1 + lw a1, RV_DSP_SAR(\frame) + csrw CSR_DSP_SAR, a1 + lw a1, RV_DSP_STATUS(\frame) + csrw CSR_DSP_STATUS, a1 +.endm + +generate_coprocessor_routine dsp, DSP_COPROC_IDX, dsp_enable, dsp_save_regs, dsp_restore_regs + +#endif /* SOC_CPU_HAS_DSP */ + #if SOC_CPU_HAS_FPU /* Bit to set in mstatus to enable the FPU */ @@ -513,6 +567,12 @@ rtos_int_enter: or s2, s2, a0 #endif /* SOC_CPU_HAS_PIE */ +#if SOC_CPU_HAS_DSP + /* The current DSP coprocessor status will be returned in a0 */ + dsp_disable a0 + or s2, s2, a0 +#endif /* SOC_CPU_HAS_DSP */ + #if SOC_CPU_HAS_FPU fpu_disable a0 #endif /* SOC_CPU_HAS_FPU */ @@ -675,6 +735,14 @@ no_context_switch: pie_enable a1 1: #endif /* SOC_CPU_HAS_PIE */ + +#if SOC_CPU_HAS_DSP + /* Re-enable the DSP coprocessor if it was used */ + andi a1, s8, 1 << DSP_COPROC_IDX + beqz a1, 1f + dsp_enable a1 +1: +#endif /* SOC_CPU_HAS_DSP */ j restore_stack_pointer context_switch_requested: diff --git a/components/riscv/include/riscv/csr_dsp.h b/components/riscv/include/riscv/csr_dsp.h new file mode 100644 index 0000000000..8e17ae92f2 --- /dev/null +++ b/components/riscv/include/riscv/csr_dsp.h @@ -0,0 +1,27 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "soc/soc_caps.h" + +#if SOC_CPU_HAS_DSP + +#define CSR_DSP_XACC_L 0x806 +#define CSR_DSP_XACC_H 0x807 +#define CSR_DSP_SAR 0x809 +#define CSR_DSP_STATUS 0x80a + +/** + * CSR lowest 2 bits describe the following states: + * 00: Off + * 01: Initial + * 10: Clean + * 11: Dirty + */ +#define CSR_DSP_STATE_REG 0x7f3 + +#endif /* SOC_CPU_HAS_DSP */ diff --git a/components/riscv/include/riscv/rv_utils.h b/components/riscv/include/riscv/rv_utils.h index dca85fa17b..7a0ebbfcef 100644 --- a/components/riscv/include/riscv/rv_utils.h +++ b/components/riscv/include/riscv/rv_utils.h @@ -14,6 +14,7 @@ #include "riscv/csr.h" #include "riscv/interrupt.h" #include "riscv/csr_pie.h" +#include "riscv/csr_dsp.h" #include "sdkconfig.h" #if CONFIG_SECURE_ENABLE_TEE && !NON_OS_BUILD @@ -275,7 +276,27 @@ FORCE_INLINE_ATTR void rv_utils_disable_pie(void) RV_WRITE_CSR(CSR_PIE_STATE_REG, 0); } -#endif /* SOC_CPU_HAS_FPU */ +#endif /* SOC_CPU_HAS_PIE */ + + +/* ------------------------------------------------- DSP Related ---------------------------------------------------- + * + * ------------------------------------------------------------------------------------------------------------------ */ + +#if SOC_CPU_HAS_DSP + +FORCE_INLINE_ATTR void rv_utils_enable_dsp(void) +{ + RV_WRITE_CSR(CSR_DSP_STATE_REG, 1); +} + + +FORCE_INLINE_ATTR void rv_utils_disable_dsp(void) +{ + RV_WRITE_CSR(CSR_DSP_STATE_REG, 0); +} + +#endif /* SOC_CPU_HAS_DSP */ diff --git a/components/riscv/include/riscv/rvruntime-frames.h b/components/riscv/include/riscv/rvruntime-frames.h index 45f013b0e5..947a8bab63 100644 --- a/components/riscv/include/riscv/rvruntime-frames.h +++ b/components/riscv/include/riscv/rvruntime-frames.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -179,6 +179,36 @@ STRUCT_END(RvHWLPSaveArea) #endif /* SOC_CPU_HAS_HWLOOP */ +#if SOC_CPU_HAS_DSP + +/* DSP coprocessor is considered coprocessor 1, just like the HWLP, make sure both are not present on the same target */ +#define DSP_COPROC_IDX 1 + +#ifdef SOC_CPU_HAS_HWLOOP +#error "HWLP and DSP share the same coprocessor index!" +#endif + +/** + * @brief DSP save area + */ +STRUCT_BEGIN +STRUCT_FIELD (long, 4, RV_DSP_XACC_L, xacc_l) +STRUCT_FIELD (long, 4, RV_DSP_XACC_H, xacc_h) +STRUCT_FIELD (long, 4, RV_DSP_SAR, sar) +STRUCT_FIELD (long, 4, RV_DSP_STATUS, status) +STRUCT_END(RvDSPSaveArea) + +/* Redefine the coprocessor area size previously defined to 0 */ +#undef RV_COPROC1_SIZE + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) + #define RV_COPROC1_SIZE RvDSPSaveAreaSize +#else + #define RV_COPROC1_SIZE sizeof(RvDSPSaveArea) +#endif /* defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) */ + +#endif /* SOC_CPU_HAS_DSP */ + #if SOC_CPU_HAS_PIE diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index 88d67d3288..47d0b372d9 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -20,22 +20,18 @@ #if ( SOC_CPU_COPROC_NUM > 0 ) /* Targets with coprocessors present a special CSR to get Illegal Instruction exception reason */ -#ifdef __clang__ - /* Clang does not support constant declared via `equ` as operand for csrrw - * TODO: LLVM-369 - */ #define EXT_ILL_CSR 0x7F0 -#else - .equ EXT_ILL_CSR, 0x7F0 -#endif /* EXT_ILL CSR reasons are stored as follows: * - Bit 0: FPU core instruction (Load/Store instructions NOT concerned) * - Bit 1: Hardware Loop instructions - * - Bit 2: PIE core */ + * - Bit 2: PIE core + * - Bit 3: DSP core + */ .equ EXT_ILL_RSN_FPU, 1 .equ EXT_ILL_RSN_HWLP, 2 .equ EXT_ILL_RSN_PIE, 4 + .equ EXT_ILL_RSN_DSP, 8 #endif /* SOC_CPU_COPROC_NUM > 0 */ /* Macro which first allocates space on the stack to save general @@ -252,6 +248,12 @@ _panic_handler: bnez a1, rtos_save_pie_coproc #endif /* SOC_CPU_HAS_PIE */ +#if SOC_CPU_HAS_DSP + /* Check if the DSP bit is set. */ + andi a1, a0, EXT_ILL_RSN_DSP + bnez a1, rtos_save_dsp_coproc +#endif /* SOC_CPU_HAS_DSP */ + /* We cannot check the HWLP bit in a0 since a hardware bug may set this bit even though no HWLP * instruction was executed in the program at all, so check mtval (`t0`) */ #if SOC_CPU_HAS_HWLOOP diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index dae76e5395..ab2572594a 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -183,6 +183,10 @@ config SOC_CPU_HAS_FPU_EXT_ILL_BUG bool default n +config SOC_CPU_HAS_DSP + bool + default y + config SOC_CPU_COPROC_NUM int default 2 diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index c8ca8b3808..fe26ac767f 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -161,6 +161,7 @@ #define SOC_BRANCH_PREDICTOR_SUPPORTED 1 #define SOC_CPU_HAS_FPU 1 #define SOC_CPU_HAS_FPU_EXT_ILL_BUG 0 // EXT_ILL CSR doesn't support FLW/FSW +#define SOC_CPU_HAS_DSP 1 #define SOC_CPU_COPROC_NUM 2 #define SOC_CPU_BREAKPOINTS_NUM 4