From 13b55386bf5c20bd906e79e0e7aee261f6afe0fc Mon Sep 17 00:00:00 2001 From: Alexey Lapshin Date: Sat, 20 Jan 2024 00:21:18 +0400 Subject: [PATCH] feat(system): esp32p4: support hw stack guard --- components/esp_system/hw_stack_guard.c | 46 +++--- components/esp_system/linker.lf | 2 +- .../esp_system/port/arch/riscv/panic_arch.c | 18 ++- .../private/esp_private/hw_stack_guard.h | 40 ++--- components/esp_system/port/panic_handler.c | 41 +++-- .../hal/esp32c2/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32c3/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32c6/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32h2/include/hal/assist_debug_ll.h | 16 +- .../hal/esp32p4/include/hal/assist_debug_ll.h | 143 ++++++++++++++++++ components/riscv/vectors_clic.S | 10 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 + .../esp32p4/include/soc/assist_debug_reg.h | 1 - .../soc/esp32p4/include/soc/periph_defs.h | 1 + components/soc/esp32p4/include/soc/soc.h | 1 + components/soc/esp32p4/include/soc/soc_caps.h | 2 +- 16 files changed, 299 insertions(+), 74 deletions(-) create mode 100644 components/hal/esp32p4/include/hal/assist_debug_ll.h diff --git a/components/esp_system/hw_stack_guard.c b/components/esp_system/hw_stack_guard.c index 3cd73a4d9e..06040d85fa 100644 --- a/components/esp_system/hw_stack_guard.c +++ b/components/esp_system/hw_stack_guard.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,15 +15,20 @@ ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES { uint32_t core_id = esp_cpu_get_core_id(); - if (core_id == 0) { - /* initialize the peripheral only when running on core 0 */ - periph_module_enable(PERIPH_ASSIST_DEBUG_MODULE); - periph_module_reset(PERIPH_ASSIST_DEBUG_MODULE); + ESP_INTR_DISABLE(ETS_ASSIST_DEBUG_INUM); + +#if SOC_CPU_CORES_NUM > 1 + PERIPH_RCC_ATOMIC() +#endif + { + assist_debug_ll_enable_bus_clock(true); + assist_debug_ll_reset_register(); } - /* just in case, disable the interrupt and clear pending status */ - assist_debug_hal_sp_int_disable(core_id); - assist_debug_hal_sp_int_clear(core_id); + /* set interrupt to matrix */ + esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM); + esprv_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL); + esprv_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); /* * enable interrupt @@ -37,12 +42,6 @@ ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES */ assist_debug_hal_sp_int_enable(core_id); - /* enable interrup routine */ - esp_rom_route_intr_matrix(core_id, ETS_ASSIST_DEBUG_INTR_SOURCE, ETS_ASSIST_DEBUG_INUM); - - esprv_int_set_type(ETS_ASSIST_DEBUG_INUM, INTR_TYPE_LEVEL); - esprv_int_set_priority(ETS_ASSIST_DEBUG_INUM, SOC_INTERRUPT_LEVEL_MEDIUM); - ESP_INTR_ENABLE(ETS_ASSIST_DEBUG_INUM); return ESP_OK; } @@ -72,23 +71,22 @@ void esp_hw_stack_guard_set_bounds(uint32_t sp_min, uint32_t sp_max) assist_debug_hal_set_sp_bounds(core_id, sp_min, sp_max); } -void esp_hw_stack_guard_get_bounds(uint32_t *sp_min, uint32_t *sp_max) +void esp_hw_stack_guard_get_bounds(uint32_t core_id, uint32_t *sp_min, uint32_t *sp_max) { - uint32_t core_id = esp_cpu_get_core_id(); - assist_debug_hal_get_sp_bounds(core_id, sp_min, sp_max); } -bool esp_hw_stack_guard_is_fired(void) +uint32_t esp_hw_stack_guard_get_fired_cpu(void) { - uint32_t core_id = esp_cpu_get_core_id(); - - return assist_debug_hal_is_sp_ovf_fired(core_id); + for (uint32_t i = 0; i < SOC_CPU_CORES_NUM; i++) { + if (assist_debug_hal_is_sp_ovf_fired(i)) { + return i; + } + } + return ESP_HW_STACK_GUARD_NOT_FIRED; } -uint32_t esp_hw_stack_guard_get_pc(void) +uint32_t esp_hw_stack_guard_get_pc(uint32_t core_id) { - uint32_t core_id = esp_cpu_get_core_id(); - return assist_debug_hal_get_sp_ovf_pc(core_id); } diff --git a/components/esp_system/linker.lf b/components/esp_system/linker.lf index f512f550a9..f3eac77bc0 100644 --- a/components/esp_system/linker.lf +++ b/components/esp_system/linker.lf @@ -9,7 +9,7 @@ entries: reset_reason:esp_reset_reason_get_hint (noflash) if ESP_SYSTEM_HW_STACK_GUARD = y: hw_stack_guard:esp_hw_stack_guard_get_bounds (noflash) - hw_stack_guard:esp_hw_stack_guard_is_fired (noflash) + hw_stack_guard:esp_hw_stack_guard_get_fired_cpu (noflash) hw_stack_guard:esp_hw_stack_guard_get_pc (noflash) esp_err (noflash) diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index e7c8ee1fce..d2e25b2f01 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -60,20 +60,21 @@ static inline void print_cache_err_details(const void *frame) #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD static inline void print_assist_debug_details(const void *frame) { - uint32_t core_id = esp_cpu_get_core_id(); + uint32_t core_id = esp_hw_stack_guard_get_fired_cpu(); + if (core_id == ESP_HW_STACK_GUARD_NOT_FIRED) { + panic_print_str("ASSIST_DEBUG is not triggered BUT interrupt occured!\r\n\r\n"); + core_id = 0; + } uint32_t sp_min, sp_max; const char *task_name = pcTaskGetName(xTaskGetCurrentTaskHandleForCore(core_id)); - esp_hw_stack_guard_get_bounds(&sp_min, &sp_max); + esp_hw_stack_guard_get_bounds(core_id, &sp_min, &sp_max); panic_print_str("\r\n"); - if (!esp_hw_stack_guard_is_fired()) { - panic_print_str("ASSIST_DEBUG is not triggered BUT interrupt occured!\r\n\r\n"); - } panic_print_str("Detected in task \""); panic_print_str(task_name); panic_print_str("\" at 0x"); - panic_print_hex((int) esp_hw_stack_guard_get_pc()); + panic_print_hex((int) esp_hw_stack_guard_get_pc(core_id)); panic_print_str("\r\n"); panic_print_str("Stack pointer: 0x"); panic_print_hex((int)((RvExcFrame *)frame)->sp); @@ -250,7 +251,10 @@ void panic_soc_fill_info(void *f, panic_info_t *info) #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD else if (frame->mcause == ETS_ASSIST_DEBUG_INUM) { - info->core = esp_cache_err_get_cpuid(); + info->core = esp_hw_stack_guard_get_fired_cpu(); + if (info->core == ESP_HW_STACK_GUARD_NOT_FIRED) { + info->core = 0; + } info->reason = "Stack protection fault"; info->details = print_assist_debug_details; } diff --git a/components/esp_system/port/include/private/esp_private/hw_stack_guard.h b/components/esp_system/port/include/private/esp_private/hw_stack_guard.h index 3757ae02bc..ed6b64ec7c 100644 --- a/components/esp_system/port/include/private/esp_private/hw_stack_guard.h +++ b/components/esp_system/port/include/private/esp_private/hw_stack_guard.h @@ -14,15 +14,17 @@ extern "C" { #endif +#define ESP_HW_STACK_GUARD_NOT_FIRED UINT32_MAX + /* The functions below are designed to be used in interrupt/panic handler * In case using them in user's code put them into critical section.*/ void esp_hw_stack_guard_monitor_start(void); void esp_hw_stack_guard_monitor_stop(void); void esp_hw_stack_guard_set_bounds(uint32_t sp_min, uint32_t sp_max); -void esp_hw_stack_guard_get_bounds(uint32_t *sp_min, uint32_t *sp_max); -bool esp_hw_stack_guard_is_fired(void); -uint32_t esp_hw_stack_guard_get_pc(void); +void esp_hw_stack_guard_get_bounds(uint32_t core_id, uint32_t *sp_min, uint32_t *sp_max); +uint32_t esp_hw_stack_guard_get_fired_cpu(void); +uint32_t esp_hw_stack_guard_get_pc(uint32_t core_id); #ifdef __cplusplus }; @@ -33,8 +35,9 @@ uint32_t esp_hw_stack_guard_get_pc(void); #include "hal/assist_debug_ll.h" #define ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM (ASSIST_DEBUG_CORE_0_INTR_ENA_REG >> 12) -#define ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_0_SP_MIN_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG) -#define ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_0_SP_MAX_REG - ASSIST_DEBUG_CORE_0_INTR_ENA_REG) +#define ASSIST_DEBUG_CORE_0_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_0_SP_MIN_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_0_SP_MAX_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET (ASSIST_DEBUG_CORE_0_INTR_ENA_REG - DR_REG_ASSIST_DEBUG_BASE) .macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 reg1 lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM @@ -44,23 +47,24 @@ sw a1, ASSIST_DEBUG_CORE_0_SP_MAX_OFFSET(\reg1) .macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU0 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) .endm .macro ESP_HW_STACK_GUARD_MONITOR_START_CPU0 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_0_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_0_SP_SPILL_OFFSET(\reg1) .endm #if SOC_CPU_CORES_NUM > 1 #define ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM (ASSIST_DEBUG_CORE_1_INTR_ENA_REG >> 12) -#define ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_1_SP_MIN_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG) -#define ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_1_SP_MAX_REG - ASSIST_DEBUG_CORE_1_INTR_ENA_REG) +#define ASSIST_DEBUG_CORE_1_SP_MIN_OFFSET (ASSIST_DEBUG_CORE_1_SP_MIN_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET (ASSIST_DEBUG_CORE_1_SP_MAX_REG - DR_REG_ASSIST_DEBUG_BASE) +#define ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET (ASSIST_DEBUG_CORE_1_INTR_ENA_REG - DR_REG_ASSIST_DEBUG_BASE) .macro ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 reg1 lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM @@ -70,22 +74,22 @@ sw a1, ASSIST_DEBUG_CORE_1_SP_MAX_OFFSET(\reg1) .macro ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) andi \reg2, \reg2, ~ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) .endm .macro ESP_HW_STACK_GUARD_MONITOR_START_CPU1 reg1 reg2 lui \reg1, ASSIST_DEBUG_CORE_1_INTR_ENA_REG_IMM -lw \reg2, 0(\reg1) +lw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) ori \reg2, \reg2, ASSIST_DEBUG_SP_SPILL_BITS -sw \reg2, 0(\reg1) +sw \reg2, ASSIST_DEBUG_CORE_1_SP_SPILL_OFFSET(\reg1) .endm .macro ESP_HW_STACK_GUARD_SET_BOUNDS_CUR_CORE reg1 /* Check the current core ID */ csrr \reg1, mhartid -beqz \reg1, @1f +beqz \reg1, 1f /* Core 1 */ ESP_HW_STACK_GUARD_SET_BOUNDS_CPU1 \reg1 j 2f @@ -98,7 +102,7 @@ ESP_HW_STACK_GUARD_SET_BOUNDS_CPU0 \reg1 .macro ESP_HW_STACK_GUARD_MONITOR_START_CUR_CORE reg1 reg2 /* Check the current core ID */ csrr \reg1, mhartid -beqz \reg1, @1f +beqz \reg1, 1f /* Core 1 */ ESP_HW_STACK_GUARD_MONITOR_START_CPU1 \reg1 \reg2 j 2f @@ -111,7 +115,7 @@ ESP_HW_STACK_GUARD_MONITOR_START_CPU0 \reg1 \reg2 .macro ESP_HW_STACK_GUARD_MONITOR_STOP_CUR_CORE reg1 reg2 /* Check the current core ID */ csrr \reg1, mhartid -beqz \reg1, @1f +beqz \reg1, 1f /* Core 1 */ ESP_HW_STACK_GUARD_MONITOR_STOP_CPU1 \reg1 \reg2 j 2f diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/panic_handler.c index a8ccce4a8c..6a1af168bd 100644 --- a/components/esp_system/port/panic_handler.c +++ b/components/esp_system/port/panic_handler.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -37,6 +37,10 @@ #include "hal/wdt_types.h" #include "hal/wdt_hal.h" +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD +#include "esp_private/hw_stack_guard.h" +#endif + extern int _invalid_pc_placeholder; extern void esp_panic_handler_reconfigure_wdts(uint32_t timeout_ms); @@ -117,6 +121,14 @@ static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_exc info->frame = frame; } +#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE +FORCE_INLINE_ATTR __attribute__((__noreturn__)) +void busy_wait(void) +{ + while (1) {;} // infinite loop +} +#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE + static void panic_handler(void *frame, bool pseudo_excause) { panic_info_t info = { 0 }; @@ -134,19 +146,24 @@ static void panic_handler(void *frame, bool pseudo_excause) // These are cases where both CPUs both go into panic handler. The following code ensures // only one core proceeds to the system panic handler. if (pseudo_excause) { -#define BUSY_WAIT_IF_TRUE(b) { if (b) while(1); } - // For WDT expiry, pause the non-offending core - offending core handles panic - BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1); - BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0); - // For cache error, pause the non-offending core - offending core handles panic - if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) { - // Only print the backtrace for the offending core in case of the cache error - g_exc_frames[core_id] = NULL; - while (1) { - ; - } + // For WDT expiry, pause the non-offending core - offending core handles panic + if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1) { + busy_wait(); + } else if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0) { + busy_wait(); + } else if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) { + g_exc_frames[core_id] = NULL; // Only print the backtrace for the offending core + busy_wait(); } +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD + else if (panic_get_cause(frame) == ETS_ASSIST_DEBUG_INUM && + esp_hw_stack_guard_get_fired_cpu() != core_id && + esp_hw_stack_guard_get_fired_cpu() != ESP_HW_STACK_GUARD_NOT_FIRED) { + g_exc_frames[core_id] = NULL; // Only print the backtrace for the offending core + busy_wait(); + } +#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD } // Need to reconfigure WDTs before we stall any other CPU diff --git a/components/hal/esp32c2/include/hal/assist_debug_ll.h b/components/hal/esp32c2/include/hal/assist_debug_ll.h index 02c7e4089a..ce98af9292 100644 --- a/components/hal/esp32c2/include/hal/assist_debug_ll.h +++ b/components/hal/esp32c2/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/system_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + SYSTEM.cpu_peri_clk_en.clk_en_assist_debug = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + SYSTEM.cpu_peri_rst_en.rst_en_assist_debug = true; + SYSTEM.cpu_peri_rst_en.rst_en_assist_debug = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/assist_debug_ll.h b/components/hal/esp32c3/include/hal/assist_debug_ll.h index 02c7e4089a..128b35d903 100644 --- a/components/hal/esp32c3/include/hal/assist_debug_ll.h +++ b/components/hal/esp32c3/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/system_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + SYSTEM.cpu_peri_clk_en.reg_clk_en_assist_debug = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + SYSTEM.cpu_peri_rst_en.reg_rst_en_assist_debug = true; + SYSTEM.cpu_peri_rst_en.reg_rst_en_assist_debug = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/assist_debug_ll.h b/components/hal/esp32c6/include/hal/assist_debug_ll.h index 02c7e4089a..2a83bb0c14 100644 --- a/components/hal/esp32c6/include/hal/assist_debug_ll.h +++ b/components/hal/esp32c6/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/pcr_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + PCR.assist_conf.assist_clk_en = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + PCR.assist_conf.assist_rst_en = true; + PCR.assist_conf.assist_rst_en = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/assist_debug_ll.h b/components/hal/esp32h2/include/hal/assist_debug_ll.h index 02c7e4089a..2a83bb0c14 100644 --- a/components/hal/esp32h2/include/hal/assist_debug_ll.h +++ b/components/hal/esp32h2/include/hal/assist_debug_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +17,7 @@ #include #include "esp_attr.h" #include "hal/assert.h" +#include "soc/pcr_struct.h" #ifdef __cplusplus extern "C" { @@ -54,7 +55,7 @@ extern "C" { * interrupt, instead of "ENA". */ - /* These functions are optimazed and designed for internal usage. + /* These functions are optimized and designed for internal usage. * So, the API may differ from general ll layer pattern */ FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(__attribute__((unused)) uint32_t core_id) @@ -112,6 +113,17 @@ FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(__attribute__((unused return REG_READ(ASSIST_DEBUG_CORE_0_SP_PC_REG); } +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + PCR.assist_conf.assist_clk_en = enable; +} + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + PCR.assist_conf.assist_rst_en = true; + PCR.assist_conf.assist_rst_en = false; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32p4/include/hal/assist_debug_ll.h b/components/hal/esp32p4/include/hal/assist_debug_ll.h new file mode 100644 index 0000000000..34f6bb6c01 --- /dev/null +++ b/components/hal/esp32p4/include/hal/assist_debug_ll.h @@ -0,0 +1,143 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// The LL layer for DEBUG_ASSIST peripheral + +#pragma once + +#include "soc/assist_debug_reg.h" +#define ASSIST_DEBUG_SP_SPILL_BITS (ASSIST_DEBUG_CORE_0_SP_SPILL_MIN_ENA | ASSIST_DEBUG_CORE_0_SP_SPILL_MAX_ENA) + +#ifndef __ASSEMBLER__ + +#include +#include +#include "esp_attr.h" +#include "hal/assert.h" +#include "soc/hp_sys_clkrst_struct.h" +#include "sdkconfig.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Most other peripherals have 4 interrupt-related registers: INT_ENA_REG, INT_CLR_REG, INT_RAW_REG, INT_ST_REG, the + * meaning of which is well-understood. + * + * Assist_debug peripheral uses a different structure of interrupt registers: + * INT_ENA_REG, INT_RLS_REG, INT_CLR_REG, INT_RAW_REG. + * + * Their behavior can be explained using the following (verilog-like) pseudo-code: + * reg sp_spill_max_st + * assign sp_spill_max = (sp > SP_MAX_REG) + * assign SP_SPILL_MAX_RAW = sp_spill_max & SPILL_MAX_ENA + * always (@posedge clk) begin + * if (reset) then sp_spill_max_st <= 0 + * elif SP_SPILL_MAX_CLR then sp_spill_max_st <= 0 + * else sp_spill_max_st <= SP_SPILL_MAX_RAW & SP_SPILL_MAX_RLS + * end + * // ...same for sp_spill_min and other things dsoc/hp_sys_clkrst_struct.hebug_assist can check. + * + * // this is the final interrupt line coming out of the peripheral: + * assign DEBUG_ASSIST_INT = sp_spill_max_st | sp_spill_min_st | ... + * + * Basically, there is no "ST" register showing the final (latched) interrupt state, and there is an additional + * "RLS" register which just like "ENA" can be used to mask the interrupt. + * Note that writing to CLR clears the (internal) latched interrupt state 'sp_spill_max_st', + * but doesn't affect the software-readable RAW register. + * + * In this code, we use "ENA" to enable monitoring of a particular condition, and "RLS" to enable the interrupt. + * This allows checking whether the condition (e.g. sp > SP_MAX) has occurred by reading the RAW register, without + * actually triggering the interrupt. Hence you will see the somewhat counter-intuitive use of "RLS" to enable the + * interrupt, instead of "ENA". + */ + + /* These functions are optimized and designed for internal usage. + * So, the API may differ from general ll layer pattern */ + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_enable(uint32_t core_id) +{ + REG_SET_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_ENA_REG : ASSIST_DEBUG_CORE_0_INTR_ENA_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_monitor_disable(uint32_t core_id) +{ + REG_CLR_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_ENA_REG : ASSIST_DEBUG_CORE_0_INTR_ENA_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_enable(uint32_t core_id) +{ + REG_SET_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_RLS_REG : ASSIST_DEBUG_CORE_0_INTR_RLS_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_disable(uint32_t core_id) +{ + REG_CLR_BIT(core_id ? ASSIST_DEBUG_CORE_1_INTR_RLS_REG : ASSIST_DEBUG_CORE_0_INTR_RLS_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR bool assist_debug_ll_sp_spill_is_fired(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_INTR_RAW_REG : ASSIST_DEBUG_CORE_0_INTR_RAW_REG) & ASSIST_DEBUG_SP_SPILL_BITS; +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_interrupt_clear(uint32_t core_id) +{ + REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_INTR_CLR_REG : ASSIST_DEBUG_CORE_0_INTR_CLR_REG, ASSIST_DEBUG_SP_SPILL_BITS); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_set_min(uint32_t core_id, uint32_t min) +{ + REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_SP_MIN_REG : ASSIST_DEBUG_CORE_0_SP_MIN_REG, min); +} + +FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_min(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_MIN_REG : ASSIST_DEBUG_CORE_0_SP_MIN_REG); +} + +FORCE_INLINE_ATTR void assist_debug_ll_sp_spill_set_max(uint32_t core_id, uint32_t max) +{ + REG_WRITE(core_id ? ASSIST_DEBUG_CORE_1_SP_MAX_REG : ASSIST_DEBUG_CORE_0_SP_MAX_REG, max); +} + +FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_max(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_MAX_REG : ASSIST_DEBUG_CORE_0_SP_MAX_REG); +} + +FORCE_INLINE_ATTR uint32_t assist_debug_ll_sp_spill_get_pc(uint32_t core_id) +{ + return REG_READ(core_id ? ASSIST_DEBUG_CORE_1_SP_PC_REG : ASSIST_DEBUG_CORE_0_SP_PC_REG); +} + +FORCE_INLINE_ATTR void assist_debug_ll_enable_bus_clock(bool enable) +{ + HP_SYS_CLKRST.soc_clk_ctrl0.reg_busmon_cpu_clk_en = enable; +} +#define assist_debug_ll_enable_bus_clock(...) \ + (void)__DECLARE_RCC_ATOMIC_ENV; assist_debug_ll_enable_bus_clock(__VA_ARGS__) + +FORCE_INLINE_ATTR void assist_debug_ll_reset_register(void) +{ + /* esp32p4 has no assist_debug reset register: disable & clear interrupts manually. */ + for (int i = 0; i < CONFIG_SOC_CPU_CORES_NUM; i++) { + assist_debug_ll_sp_spill_monitor_disable(i); + assist_debug_ll_sp_spill_interrupt_clear(i); + assist_debug_ll_sp_spill_set_min(i, 0); + assist_debug_ll_sp_spill_set_max(i, 0xffffffff); + /* Enable PC register storing when trigger stack monitor. */ + REG_WRITE(i ? ASSIST_DEBUG_CORE_1_RCD_EN_REG : ASSIST_DEBUG_CORE_0_RCD_EN_REG, ASSIST_DEBUG_CORE_1_RCD_PDEBUGEN | ASSIST_DEBUG_CORE_1_RCD_RECORDEN); + } +} +#define assist_debug_ll_reset_register(...) \ + (void)__DECLARE_RCC_ATOMIC_ENV; assist_debug_ll_reset_register(__VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif // __ASSEMBLER__ diff --git a/components/riscv/vectors_clic.S b/components/riscv/vectors_clic.S index e1b2ad0e35..543c868762 100644 --- a/components/riscv/vectors_clic.S +++ b/components/riscv/vectors_clic.S @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,12 @@ #define MEMPROT_ISR _interrupt_handler #endif // CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#if CONFIG_ESP_SYSTEM_HW_STACK_GUARD + #define ASTDBG_ISR _panic_handler +#else + #define ASTDBG_ISR _interrupt_handler +#endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD + #if CONFIG_ESP_IPC_ISR_ENABLE #define IPC_ISR_HANDLER esp_ipc_isr_handler #else @@ -109,7 +115,7 @@ _mtvt_table: .word _panic_handler /* 40: ETS_INT_WDT_INUM (+16) panic-interrupt (soc-level panic) */ .word _panic_handler /* 41: ETS_CACHEERR_INUM (+16) panic-interrupt (soc-level panic) */ .word MEMPROT_ISR /* 42: ETS_MEMPROT_ERR_INUM (+16) handler (soc-level panic) */ - .word _interrupt_handler /* 43: Free interrupt number */ + .word ASTDBG_ISR /* 43: ETS_ASSIST_DEBUG_INUM (+16) handler (soc-level panic) */ .word IPC_ISR_HANDLER /* 44: ETS_IPC_ISR_INUM (+16) handler*/ .word _interrupt_handler /* 45: Free interrupt number */ .word _interrupt_handler /* 46: Free interrupt number */ diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 4da0a19281..06f6053582 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -211,6 +211,10 @@ config SOC_CLK_TREE_SUPPORTED bool default y +config SOC_ASSIST_DEBUG_SUPPORTED + bool + default y + config SOC_WDT_SUPPORTED bool default y diff --git a/components/soc/esp32p4/include/soc/assist_debug_reg.h b/components/soc/esp32p4/include/soc/assist_debug_reg.h index 6eda629f77..89c49a9cc6 100644 --- a/components/soc/esp32p4/include/soc/assist_debug_reg.h +++ b/components/soc/esp32p4/include/soc/assist_debug_reg.h @@ -5,7 +5,6 @@ */ #pragma once -#include #include "soc/soc.h" #ifdef __cplusplus extern "C" { diff --git a/components/soc/esp32p4/include/soc/periph_defs.h b/components/soc/esp32p4/include/soc/periph_defs.h index 8be5b45219..cadf54fdf7 100644 --- a/components/soc/esp32p4/include/soc/periph_defs.h +++ b/components/soc/esp32p4/include/soc/periph_defs.h @@ -68,6 +68,7 @@ typedef enum { PERIPH_AXI_PDMA_MODULE, PERIPH_UHCI_MODULE, PERIPH_PCNT_MODULE, + PERIPH_ASSIST_DEBUG_MODULE, /* LP peripherals */ PERIPH_LP_I2C0_MODULE, PERIPH_LP_UART0_MODULE, diff --git a/components/soc/esp32p4/include/soc/soc.h b/components/soc/esp32p4/include/soc/soc.h index 3f729140fe..a6653173c9 100644 --- a/components/soc/esp32p4/include/soc/soc.h +++ b/components/soc/esp32p4/include/soc/soc.h @@ -231,6 +231,7 @@ #define ETS_T1_WDT_INUM 24 #define ETS_CACHEERR_INUM 25 #define ETS_MEMPROT_ERR_INUM 26 +#define ETS_ASSIST_DEBUG_INUM 27 // Note: this interrupt can be combined with others (e.g., CACHEERR), as we can identify its trigger is activated #define ETS_IPC_ISR_INUM 28 //CPU0 Max valid interrupt number #define ETS_MAX_INUM 31 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index fce0f67512..1f79bbc93f 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -80,7 +80,7 @@ // #define SOC_ULP_SUPPORTED 1 //TODO: IDF-7534 #define SOC_SDMMC_HOST_SUPPORTED 1 #define SOC_CLK_TREE_SUPPORTED 1 -// #define SOC_ASSIST_DEBUG_SUPPORTED 1 //TODO: IDF-7565 +#define SOC_ASSIST_DEBUG_SUPPORTED 1 #define SOC_WDT_SUPPORTED 1 #define SOC_SPI_FLASH_SUPPORTED 1 // #define SOC_TOUCH_SENSOR_SUPPORTED 1 //TODO: IDF-7477