diff --git a/components/esp_hw_support/include/esp_private/esp_cpu_internal.h b/components/esp_hw_support/include/esp_private/esp_cpu_internal.h new file mode 100644 index 0000000000..60c2b7b753 --- /dev/null +++ b/components/esp_hw_support/include/esp_private/esp_cpu_internal.h @@ -0,0 +1,30 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#pragma once + +#include "sdkconfig.h" + +#if CONFIG_IDF_TARGET_ARCH_XTENSA +#include "xtensa_context.h" +#elif CONFIG_IDF_TARGET_ARCH_RISCV +#include "riscv/rvruntime-frames.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if CONFIG_IDF_TARGET_ARCH_XTENSA +typedef XtExcFrame esp_cpu_frame_t; +#elif CONFIG_IDF_TARGET_ARCH_RISCV +typedef RvExcFrame esp_cpu_frame_t; +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_system/include/esp_private/panic_internal.h b/components/esp_system/include/esp_private/panic_internal.h index 46cc0dad30..d9fadc3360 100644 --- a/components/esp_system/include/esp_private/panic_internal.h +++ b/components/esp_system/include/esp_private/panic_internal.h @@ -86,6 +86,8 @@ void panic_set_address(void *frame, uint32_t addr); uint32_t panic_get_cause(const void* frame); +void panic_prepare_frame_from_ctx(void* frame); + #ifdef __cplusplus } #endif diff --git a/components/esp_system/port/arch/riscv/debug_helpers.c b/components/esp_system/port/arch/riscv/debug_helpers.c index 5e4cf84f78..6b27451306 100644 --- a/components/esp_system/port/arch/riscv/debug_helpers.c +++ b/components/esp_system/port/arch/riscv/debug_helpers.c @@ -4,13 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "esp_debug_helpers.h" +#include "esp_private/panic_reason.h" +#include "esp_private/panic_internal.h" #include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_private/freertos_debug.h" #include "esp_err.h" #include "esp_attr.h" -#include "riscv/rvruntime-frames.h" +#include "esp_private/esp_cpu_internal.h" +#include #if CONFIG_ESP_SYSTEM_USE_EH_FRAME #include "esp_private/eh_frame_parser.h" @@ -47,12 +50,17 @@ esp_err_t IRAM_ATTR esp_backtrace_print(int depth) void *frame = snapshot.pxTopOfStack; + esp_cpu_frame_t backtrace_frame = {}; + memcpy(&backtrace_frame, frame, sizeof(esp_cpu_frame_t)); + #if CONFIG_ESP_SYSTEM_USE_EH_FRAME - esp_rom_printf("Print CPU %d (current core) backtrace\n", current_core); + esp_rom_printf("esp_backtrace_print: Print CPU %d (current core) backtrace\n", current_core); esp_eh_frame_print_backtrace(frame); #else // CONFIG_ESP_SYSTEM_USE_EH_FRAME - esp_rom_printf("Print CPU %d (current core) registers\n", current_core); - panic_print_registers(frame, current_core); + esp_rom_printf("esp_backtrace_print: Print CPU %d (current core) registers\n", current_core); + panic_prepare_frame_from_ctx(&backtrace_frame); + + panic_print_registers(&backtrace_frame, current_core); esp_rom_printf("\r\n"); #endif // CONFIG_ESP_SYSTEM_USE_EH_FRAME diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c index b2278dacb7..52fb63dd37 100644 --- a/components/esp_system/port/arch/riscv/panic_arch.c +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -350,3 +350,17 @@ void panic_set_address(void *f, uint32_t addr) { ((RvExcFrame *)f)->mepc = addr; } + +void panic_prepare_frame_from_ctx(void* frame) +{ + /* Cleanup the frame, status registers are not saved during context switches, so these will contain garbage + values from the stack. + */ + ((RvExcFrame *)frame)->mstatus = RV_READ_CSR(mstatus); + ((RvExcFrame *)frame)->mtvec = RV_READ_CSR(mtvec); + + ((RvExcFrame *)frame)->mcause = MCAUSE_INVALID_VALUE; + ((RvExcFrame *)frame)->mtval = MCAUSE_INVALID_VALUE; + + ((RvExcFrame *)frame)->mhartid = RV_READ_CSR(mhartid); +} diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index 5c2dd2f9d9..484774ecb1 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -479,3 +479,9 @@ void panic_print_backtrace(const void *f, int core) esp_backtrace_frame_t frame = {.pc = xt_frame->pc, .sp = xt_frame->a1, .next_pc = xt_frame->a0, .exc_frame = xt_frame}; esp_backtrace_print_from_frame(100, &frame, true); } + +void panic_prepare_frame_from_ctx(void* frame) +{ + /* Nothing to cleanup on xtensa */ + (void)frame; +} diff --git a/components/riscv/include/esp_private/panic_reason.h b/components/riscv/include/esp_private/panic_reason.h index fdbee96fa3..8817f470b2 100644 --- a/components/riscv/include/esp_private/panic_reason.h +++ b/components/riscv/include/esp_private/panic_reason.h @@ -22,3 +22,4 @@ #define MCAUSE_ILLIGAL_INSTRUCTION_ACCESS 1 #define MCAUSE_ILLEGAL_INSTRUCTION 2 #define MCAUSE_LOAD_ACCESS_FAULT 5 +#define MCAUSE_INVALID_VALUE 0xDEADC0DE // Frame mcause value was written by SW to indicate no useful info, e.g. during a register dump without a crash