From f7344e0a462d310b2ce24751ae4cb814a4fade3e Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Mon, 20 Apr 2026 17:47:40 +0800 Subject: [PATCH] refactor(panic): route panic handlers through esp_sys_event Let panic-related components register their hooks through esp_sys_event so panic sequencing stays extensible without hardcoded esp_system dependencies. --- components/esp_gdbstub/CMakeLists.txt | 7 +- components/esp_gdbstub/src/gdbstub.c | 28 +++++++ components/esp_system/CMakeLists.txt | 12 --- components/esp_system/crosscore_int.c | 20 +++-- .../include/esp_private/crosscore_int.h | 11 ++- .../include/esp_private/esp_sys_event_panic.h | 65 ++++++++++++++++ .../include/esp_private/panic_internal.h | 11 ++- .../esp_system/include/esp_sys_event_list.inc | 4 + components/esp_system/ld/linux/sections.ld | 10 +++ components/esp_system/linker.lf | 14 +++- components/esp_system/panic.c | 75 ++++++++----------- components/esp_trace/CMakeLists.txt | 1 + .../esp_trace/src/core/esp_trace_core.c | 22 ++++++ components/espcoredump/src/core_dump_init.c | 22 +++++- 14 files changed, 233 insertions(+), 69 deletions(-) create mode 100644 components/esp_system/include/esp_private/esp_sys_event_panic.h diff --git a/components/esp_gdbstub/CMakeLists.txt b/components/esp_gdbstub/CMakeLists.txt index 09f95507d6f..b0dbfba0885 100644 --- a/components/esp_gdbstub/CMakeLists.txt +++ b/components/esp_gdbstub/CMakeLists.txt @@ -28,4 +28,9 @@ idf_component_register(SRCS ${srcs} PRIV_INCLUDE_DIRS ${priv_includes} LDFRAGMENTS "linker.lf" REQUIRES "freertos" - PRIV_REQUIRES esp_hal_wdt esp_hal_uart) + PRIV_REQUIRES esp_hal_wdt esp_hal_uart esp_system) + +if(CONFIG_ESP_SYSTEM_PANIC_GDBSTUB) + # Make sure the panic event registration in gdbstub.c is considered by the linker + target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_gdbstub_panic_handler") +endif() diff --git a/components/esp_gdbstub/src/gdbstub.c b/components/esp_gdbstub/src/gdbstub.c index e24af43151b..a46dd280ee5 100644 --- a/components/esp_gdbstub/src/gdbstub.c +++ b/components/esp_gdbstub/src/gdbstub.c @@ -24,6 +24,10 @@ #include "hal/wdt_hal.h" #endif +#include "esp_private/esp_sys_event_panic.h" +#include "esp_private/panic_internal.h" +#include "esp_private/crosscore_int.h" + #if GDBSTUB_QXFER_FEATURES_ENABLED #define GDBSTUB_QXFER_SUPPORTED_STR ";qXfer:features:read+" #else @@ -55,6 +59,7 @@ static void send_reason(void); esp_gdbstub_scratch_t s_scratch; esp_gdbstub_gdb_regfile_t *gdb_local_regfile = &s_scratch.regfile; + /** * @brief panic handler */ @@ -105,6 +110,21 @@ void esp_gdbstub_panic_handler(void *in_frame) } } +#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB +// Panic event handler - enters GDB stub (never returns) +// Priority 999 ensures this runs last, after trace and coredump handlers +ESP_PANIC_HANDLER_REGISTER(esp_gdbstub_panic_event, 999) +{ + (void)user_arg; + esp_panic_ctx_t *panic_ctx = (esp_panic_ctx_t *)ctx; + panic_print_str("Entering gdb stub now.\r\n"); + panic_disable_all_wdts(); + esp_gdbstub_panic_handler((void *)panic_ctx->info->frame); + // Never returns + return ESP_OK; +} +#endif /* CONFIG_ESP_SYSTEM_PANIC_GDBSTUB */ + /** * Set interrupt reason to GDB */ @@ -612,6 +632,14 @@ void update_breakpoints(void) #endif // CONFIG_IDF_TARGET_ARCH_XTENSA } +// Strong override of the weak hook in esp_system's crosscore_int.c. Called from +// the crosscore ISR on the target core to apply breakpoint/watchpoint changes +// requested from the other core. Placed in IRAM as it runs in interrupt context. +IRAM_ATTR void esp_crosscore_int_gdb_call_hook(void) +{ + update_breakpoints(); +} + /** Write breakpoint */ static void handle_Z0_command(const unsigned char *cmd, int len) { diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index 3e7be90fdeb..71d8dd8419f 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -141,18 +141,6 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_system_include_startup_ # [refactor-todo] requirements due to init code, should be removable # once link-time registration of component init functions is used. -if(CONFIG_ESP_TRACE_ENABLE) - idf_component_optional_requires(PRIVATE esp_trace) -endif() - -if(CONFIG_ESP_COREDUMP_ENABLE) - idf_component_optional_requires(PRIVATE espcoredump) -endif() - -# [refactor-todo] requirement from the panic handler, -# need to introduce panic "event" concept to remove this dependency (IDF-2194) -idf_component_optional_requires(PRIVATE esp_gdbstub) - if(NOT CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT) idf_component_optional_requires(PRIVATE esp_app_format) endif() diff --git a/components/esp_system/crosscore_int.c b/components/esp_system/crosscore_int.c index 2394a4d427c..860c8d8e6be 100644 --- a/components/esp_system/crosscore_int.c +++ b/components/esp_system/crosscore_int.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,6 +10,7 @@ #include "esp_cpu.h" #include "esp_intr_alloc.h" #include "esp_debug_helpers.h" +#include "esp_private/crosscore_int.h" #include "soc/periph_defs.h" #include "soc/system_intr.h" #include "hal/crosscore_int_ll.h" @@ -17,10 +18,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/portmacro.h" -#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME -#include "esp_gdbstub.h" -#endif - #define REASON_YIELD BIT(0) #define REASON_FREQ_SWITCH BIT(1) #define REASON_PRINT_BACKTRACE BIT(2) @@ -30,6 +27,15 @@ static portMUX_TYPE reason_spinlock = portMUX_INITIALIZER_UNLOCKED; static volatile uint32_t reason[CONFIG_FREERTOS_NUMBER_OF_CORES]; +/* Weak no-op hook for the REASON_GDB_CALL crosscore interrupt. esp_gdbstub + * provides a strong override (see gdbstub.c) when the runtime gdbstub is + * enabled. Keeping the default here lets esp_system trigger the gdb-call + * handling without taking any dependency on the esp_gdbstub component. Runs in + * interrupt context, hence placed in IRAM. */ +void __attribute__((weak)) ESP_SYSTEM_IRAM_ATTR esp_crosscore_int_gdb_call_hook(void) +{ +} + /* ToDo: There is a small chance the CPU already has yielded when this ISR is serviced. In that case, it's running the intended task but the ISR will cause it to switch _away_ from it. portYIELD_FROM_ISR will probably just schedule the task again, but have to check that. @@ -64,11 +70,9 @@ static void ESP_SYSTEM_IRAM_ATTR esp_crosscore_isr(void *arg) * to allow DFS features without the extra latency of the ISR hook. */ } -#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME if (my_reason_val & REASON_GDB_CALL) { - update_breakpoints(); + esp_crosscore_int_gdb_call_hook(); } -#endif // !CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME if (my_reason_val & REASON_PRINT_BACKTRACE) { esp_backtrace_print(100); diff --git a/components/esp_system/include/esp_private/crosscore_int.h b/components/esp_system/include/esp_private/crosscore_int.h index b05c3c5022b..7a074999ca9 100644 --- a/components/esp_system/include/esp_private/crosscore_int.h +++ b/components/esp_system/include/esp_private/crosscore_int.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +48,15 @@ void esp_crosscore_int_send_freq_switch(int core_id); void esp_crosscore_int_send_gdb_call(int core_id); +/** + * Hook invoked from the crosscore ISR when a REASON_GDB_CALL interrupt is + * received on this core. esp_system provides a weak no-op default; esp_gdbstub + * supplies a strong override that updates this core's hardware breakpoints and + * watchpoints. Runs in interrupt context (possibly with cache disabled), so any + * override must be placed in IRAM. + */ +void esp_crosscore_int_gdb_call_hook(void); + #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE /** * Send an interrupt to a CPU indicating it should print its current backtrace diff --git a/components/esp_system/include/esp_private/esp_sys_event_panic.h b/components/esp_system/include/esp_private/esp_sys_event_panic.h new file mode 100644 index 00000000000..434c6cb45cf --- /dev/null +++ b/components/esp_system/include/esp_private/esp_sys_event_panic.h @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_sys_event.h" +#include "esp_private/panic_internal.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file esp_sys_event_panic.h + * @brief Panic event using esp_sys_event framework + * + * This header provides macros for registering panic handlers that are + * called when the system panics. Panic handlers receive information about + * the panic via panic_info_t and can perform actions like logging, core + * dump preparation, or custom diagnostics. + * + * Note: Panic handlers run in a very restricted context. They must: + * - Be placed in IRAM if they access any non-IRAM data + * - Not allocate memory + * - Not use FreeRTOS APIs + * - Complete quickly to avoid triggering watchdog timeout + */ + +// Context passed to panic handlers +typedef struct { + const panic_info_t *info; /*!< Pointer to panic info */ +} esp_panic_ctx_t; + +/** + * @brief Register a static (link-time) panic handler + * + * Handlers registered with this macro are called during panic processing + * in priority order (lower priority values run first). The watchdog is + * fed before and after each handler to prevent timeout during handler + * execution. + * + * @param fn Handler function name + * @param prio Priority (lower runs first) + */ +#define ESP_PANIC_HANDLER_REGISTER(fn, prio) \ + _ESP_SYS_EVENT_REGISTER(PANIC, prio, fn) + +/** + * @brief Register a static (link-time) early panic breakpoint handler + * + * Handlers registered with this macro are called before + * panic handler breaks with debugger attached. + * + * @param fn Handler function name + * @param prio Priority (lower runs first) + */ +#define ESP_PANIC_EARLY_BREAK_HANDLER_REGISTER(fn, prio) \ + _ESP_SYS_EVENT_REGISTER(PANIC_EARLY_BREAK, prio, fn) + +#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 3cb356f54c8..170ee3fd65d 100644 --- a/components/esp_system/include/esp_private/panic_internal.h +++ b/components/esp_system/include/esp_private/panic_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -90,6 +90,15 @@ void panic_prepare_frame_from_ctx(void* frame); void panic_clear_active_interrupts(const void* frame); +/** + * @brief Disable all watchdog timers + * + * This function disables all watchdog timers (Timer Group WDTs and RTC WDT). + * It is intended for use by panic handlers that take over execution (e.g., gdbstub) + * or that halt the system. + */ +void panic_disable_all_wdts(void); + #ifdef __cplusplus } #endif diff --git a/components/esp_system/include/esp_sys_event_list.inc b/components/esp_system/include/esp_sys_event_list.inc index aa20ddf56ef..8c3e34d3cd6 100644 --- a/components/esp_system/include/esp_sys_event_list.inc +++ b/components/esp_system/include/esp_sys_event_list.inc @@ -34,9 +34,13 @@ #define _ESP_SYS_EVENT_SECTION_SHUTDOWN esysev_shdn #define _ESP_SYS_EVENT_SECTION_SYSTEM_INIT_CORE esysev_initc #define _ESP_SYS_EVENT_SECTION_SYSTEM_INIT_SECONDARY esysev_inits +#define _ESP_SYS_EVENT_SECTION_PANIC esysev_panic +#define _ESP_SYS_EVENT_SECTION_PANIC_EARLY_BREAK esysev_paneb #endif /* ESP_SYS_EVENT_DEF(ENUM_SUFFIX) */ ESP_SYS_EVENT_DEF(SHUTDOWN) ESP_SYS_EVENT_DEF(SYSTEM_INIT_CORE) ESP_SYS_EVENT_DEF(SYSTEM_INIT_SECONDARY) +ESP_SYS_EVENT_DEF(PANIC) +ESP_SYS_EVENT_DEF(PANIC_EARLY_BREAK) diff --git a/components/esp_system/ld/linux/sections.ld b/components/esp_system/ld/linux/sections.ld index d97f773b8cc..2fac1da58ca 100644 --- a/components/esp_system/ld/linux/sections.ld +++ b/components/esp_system/ld/linux/sections.ld @@ -21,6 +21,16 @@ SECTIONS PROVIDE(_esysev_inits_start = .); KEEP(*(SORT_BY_INIT_PRIORITY(.esysev_inits.*))) PROVIDE(_esysev_inits_end = .); + + . = ALIGN(4); + PROVIDE(_esysev_panic_start = .); + KEEP(*(SORT_BY_INIT_PRIORITY(.esysev_panic.*))) + PROVIDE(_esysev_panic_end = .); + + . = ALIGN(4); + PROVIDE(_esysev_paneb_start = .); + KEEP(*(SORT_BY_INIT_PRIORITY(.esysev_paneb.*))) + PROVIDE(_esysev_paneb_end = .); } } INSERT AFTER .data; diff --git a/components/esp_system/linker.lf b/components/esp_system/linker.lf index 051fc57cffa..52fc3d4133f 100644 --- a/components/esp_system/linker.lf +++ b/components/esp_system/linker.lf @@ -12,12 +12,22 @@ entries: entries: .esysev_inits+ +[sections:esysev_panic] +entries: + .esysev_panic+ + +[sections:esysev_paneb] +entries: + .esysev_paneb+ + # Default placements (overridden below with ALIGN/SURROUND flags) [scheme:esp_sys_event_default] entries: esysev_shdn -> flash_rodata esysev_initc -> flash_rodata esysev_inits -> flash_rodata + esysev_panic -> flash_rodata + esysev_paneb -> flash_rodata [mapping:esp_sys_event] archive: * @@ -25,7 +35,9 @@ entries: * (esp_sys_event_default); esysev_shdn -> flash_rodata ALIGN(4, pre) KEEP() SORT(init_priority) SURROUND(esysev_shdn), esysev_initc -> flash_rodata ALIGN(4, pre) KEEP() SORT(init_priority) SURROUND(esysev_initc), - esysev_inits -> flash_rodata ALIGN(4, pre) KEEP() SORT(init_priority) SURROUND(esysev_inits) + esysev_inits -> flash_rodata ALIGN(4, pre) KEEP() SORT(init_priority) SURROUND(esysev_inits), + esysev_panic -> flash_rodata ALIGN(4, pre) KEEP() SORT(init_priority) SURROUND(esysev_panic), + esysev_paneb -> flash_rodata ALIGN(4, pre) KEEP() SORT(init_priority) SURROUND(esysev_paneb) # ============== esp_system component mappings ============== diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index ee4639c717a..e3c9ac16f96 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -23,6 +23,8 @@ #include "esp_private/esp_int_wdt.h" #include "esp_private/panic_internal.h" +#include "esp_private/esp_sys_event_panic.h" +#include "esp_private/esp_sys_event_internal.h" #include "port/panic_funcs.h" #include "esp_rom_sys.h" @@ -35,22 +37,10 @@ #endif #endif // CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT -#if CONFIG_ESP_COREDUMP_ENABLE -#include "esp_core_dump.h" -#endif - -#if CONFIG_ESP_TRACE_ENABLE -#include "esp_trace.h" -#endif - #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT #include "hal/uart_hal.h" #endif -#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB -#include "esp_gdbstub.h" -#endif - #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG || CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG #include "hal/usb_serial_jtag_ll.h" #endif @@ -270,9 +260,20 @@ void esp_panic_handler_feed_wdts(void) } #endif /* SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED */ +/********************** esp_sys_event panic trigger **********************/ + +static void esp_panic_trigger_event(esp_sys_event_id_t id, esp_panic_ctx_t *ctx) +{ + ESP_SYS_EVENT_FOREACH(h, id) { + esp_panic_handler_feed_wdts(); + h->handler(NULL, ctx); + } + esp_panic_handler_feed_wdts(); +} + #if SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED /* This function disables all the watchdogs */ -static inline void disable_all_wdts(void) +void panic_disable_all_wdts(void) { #if SOC_WDT_SUPPORTED //Disable Timer Group WDTs @@ -286,7 +287,7 @@ static inline void disable_all_wdts(void) #endif /* SOC_RTC_WDT_SUPPORTED */ } #else /* SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED */ -static inline void disable_all_wdts(void) +void panic_disable_all_wdts(void) { } #endif /* SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED */ @@ -395,11 +396,14 @@ void esp_panic_handler(panic_info_t *info) panic_print_hex((uint32_t)info->addr); panic_print_str(" and returning...\r\n"); -#if CONFIG_ESP_TRACE_ENABLE - esp_trace_panic_handler(info); -#endif + // Trigger early breakpoint handlers before returning to debugger. + // This allows trace to dump info before breaking + esp_panic_ctx_t panic_ctx = { + .info = info, + }; + esp_panic_trigger_event(ESP_SYS_EVENT_PANIC_EARLY_BREAK, &panic_ctx); - disable_all_wdts(); + panic_disable_all_wdts(); esp_cpu_set_breakpoint(0, info->addr); // use breakpoint 0 return; } @@ -432,28 +436,16 @@ void esp_panic_handler(panic_info_t *info) panic_print_str("\r\n"); -#if CONFIG_ESP_TRACE_ENABLE - esp_panic_handler_feed_wdts(); - esp_trace_panic_handler(info); -#endif + // Trigger esp_sys_event panic handlers (includes trace, coredump, gdbstub if enabled) + // If gdbstub is enabled and registered, it will take over and never return. + // If we return here, proceed to reboot/halt. + { + esp_panic_ctx_t panic_ctx = { + .info = info, + }; + esp_panic_trigger_event(ESP_SYS_EVENT_PANIC, &panic_ctx); -#if CONFIG_ESP_COREDUMP_ENABLE - esp_panic_handler_feed_wdts(); - static bool s_dumping_core = false; - if (s_dumping_core) { - panic_print_str("Re-entered core dump! Exception happened during core dump!\r\n"); - } else { - s_dumping_core = true; - esp_core_dump_write(info); - s_dumping_core = false; } -#endif /* CONFIG_ESP_COREDUMP_ENABLE */ - -#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB - panic_print_str("Entering gdb stub now.\r\n"); - disable_all_wdts(); - esp_gdbstub_panic_handler((void *)info->frame); -#else #if CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS esp_panic_handler_feed_wdts(); @@ -488,10 +480,9 @@ void esp_panic_handler(panic_info_t *info) #else /* CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT */ esp_panic_handler_feed_wdts(); panic_print_str("CPU halted.\r\n"); - disable_all_wdts(); + panic_disable_all_wdts(); esp_panic_handler_reset_modules_on_exit_and_halt(); #endif /* CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT */ -#endif /* CONFIG_ESP_SYSTEM_PANIC_GDBSTUB */ } void __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *details) @@ -499,10 +490,6 @@ void __attribute__((noreturn, no_sanitize_undefined)) panic_abort(const char *de g_panic_abort = true; g_panic_abort_details = (char *) details; -#if CONFIG_ESP_TRACE_ENABLE - esp_trace_panic_handler(NULL); -#endif - #ifdef __XTENSA__ asm("ill"); // should be an invalid operation on xtensa targets #elif __riscv diff --git a/components/esp_trace/CMakeLists.txt b/components/esp_trace/CMakeLists.txt index 937b664d110..c976fc497ba 100644 --- a/components/esp_trace/CMakeLists.txt +++ b/components/esp_trace/CMakeLists.txt @@ -30,6 +30,7 @@ set(priv_requires "esp_hal_usb" "esp_driver_usb_serial_jtag" "esp_timer" + "esp_system" ) set(priv_includes "") set(requires "app_trace") diff --git a/components/esp_trace/src/core/esp_trace_core.c b/components/esp_trace/src/core/esp_trace_core.c index 7fd81c5a544..47e76b946a8 100644 --- a/components/esp_trace/src/core/esp_trace_core.c +++ b/components/esp_trace/src/core/esp_trace_core.c @@ -23,6 +23,8 @@ #include "esp_trace.h" #include "esp_trace_port_transport.h" #include "esp_private/startup_internal.h" +#include "esp_private/esp_sys_event_system_init.h" +#include "esp_private/esp_sys_event_panic.h" static const char *TAG = "esp_trace_core"; @@ -231,6 +233,26 @@ void esp_trace_panic_handler(const void *info) } } +static esp_err_t esp_trace_panic_event_handler(void *user_arg, void *ctx) +{ + (void)user_arg; + esp_panic_ctx_t *panic_ctx = (esp_panic_ctx_t *)ctx; + esp_trace_panic_handler(panic_ctx->info); + return ESP_OK; +} + +// Panic event handler - flushes trace buffers on panic +ESP_PANIC_HANDLER_REGISTER(esp_trace_panic, 100) +{ + return esp_trace_panic_event_handler(user_arg, ctx); +} + +// Early breakpoint event handler - flushes trace before returning to debugger +ESP_PANIC_EARLY_BREAK_HANDLER_REGISTER(esp_trace_panic_early_break, 100) +{ + return esp_trace_panic_event_handler(user_arg, ctx); +} + esp_trace_open_params_t __attribute__((weak)) esp_trace_get_user_params(void) { esp_trace_open_params_t trace_params = { diff --git a/components/espcoredump/src/core_dump_init.c b/components/espcoredump/src/core_dump_init.c index 79f473a165a..d3befe0dd3c 100644 --- a/components/espcoredump/src/core_dump_init.c +++ b/components/espcoredump/src/core_dump_init.c @@ -1,11 +1,14 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #include "sdkconfig.h" #include "esp_private/startup_internal.h" +#include "esp_private/esp_sys_event_system_init.h" +#include "esp_private/esp_sys_event_panic.h" +#include "esp_private/panic_internal.h" #include "esp_core_dump.h" // Hook to force the linker to include this file @@ -18,3 +21,20 @@ ESP_SYSTEM_INIT_FN(init_coredump, SECONDARY, BIT(0), 130) esp_core_dump_init(); return ESP_OK; } + +// Panic event handler - writes core dump on panic +ESP_PANIC_HANDLER_REGISTER(esp_coredump_panic, 200) +{ + (void)user_arg; + esp_panic_ctx_t *panic_ctx = (esp_panic_ctx_t *)ctx; + + static bool s_dumping_core = false; + if (s_dumping_core) { + panic_print_str("Re-entered core dump! Exception happened during core dump!\r\n"); + return ESP_ERR_INVALID_STATE; + } + s_dumping_core = true; + esp_core_dump_write((panic_info_t *)panic_ctx->info); + s_dumping_core = false; + return ESP_OK; +}