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.
This commit is contained in:
Marius Vikhammer
2026-06-10 11:21:47 +08:00
parent 4135057bee
commit f7344e0a46
14 changed files with 233 additions and 69 deletions
+6 -1
View File
@@ -28,4 +28,9 @@ idf_component_register(SRCS ${srcs}
PRIV_INCLUDE_DIRS ${priv_includes} PRIV_INCLUDE_DIRS ${priv_includes}
LDFRAGMENTS "linker.lf" LDFRAGMENTS "linker.lf"
REQUIRES "freertos" 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()
+28
View File
@@ -24,6 +24,10 @@
#include "hal/wdt_hal.h" #include "hal/wdt_hal.h"
#endif #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 #if GDBSTUB_QXFER_FEATURES_ENABLED
#define GDBSTUB_QXFER_SUPPORTED_STR ";qXfer:features:read+" #define GDBSTUB_QXFER_SUPPORTED_STR ";qXfer:features:read+"
#else #else
@@ -55,6 +59,7 @@ static void send_reason(void);
esp_gdbstub_scratch_t s_scratch; esp_gdbstub_scratch_t s_scratch;
esp_gdbstub_gdb_regfile_t *gdb_local_regfile = &s_scratch.regfile; esp_gdbstub_gdb_regfile_t *gdb_local_regfile = &s_scratch.regfile;
/** /**
* @brief panic handler * @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 * Set interrupt reason to GDB
*/ */
@@ -612,6 +632,14 @@ void update_breakpoints(void)
#endif // CONFIG_IDF_TARGET_ARCH_XTENSA #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 */ /** Write breakpoint */
static void handle_Z0_command(const unsigned char *cmd, int len) static void handle_Z0_command(const unsigned char *cmd, int len)
{ {
-12
View File
@@ -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 # [refactor-todo] requirements due to init code, should be removable
# once link-time registration of component init functions is used. # 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) if(NOT CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT)
idf_component_optional_requires(PRIVATE esp_app_format) idf_component_optional_requires(PRIVATE esp_app_format)
endif() endif()
+12 -8
View File
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -10,6 +10,7 @@
#include "esp_cpu.h" #include "esp_cpu.h"
#include "esp_intr_alloc.h" #include "esp_intr_alloc.h"
#include "esp_debug_helpers.h" #include "esp_debug_helpers.h"
#include "esp_private/crosscore_int.h"
#include "soc/periph_defs.h" #include "soc/periph_defs.h"
#include "soc/system_intr.h" #include "soc/system_intr.h"
#include "hal/crosscore_int_ll.h" #include "hal/crosscore_int_ll.h"
@@ -17,10 +18,6 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/portmacro.h" #include "freertos/portmacro.h"
#if CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME
#include "esp_gdbstub.h"
#endif
#define REASON_YIELD BIT(0) #define REASON_YIELD BIT(0)
#define REASON_FREQ_SWITCH BIT(1) #define REASON_FREQ_SWITCH BIT(1)
#define REASON_PRINT_BACKTRACE BIT(2) #define REASON_PRINT_BACKTRACE BIT(2)
@@ -30,6 +27,15 @@
static portMUX_TYPE reason_spinlock = portMUX_INITIALIZER_UNLOCKED; static portMUX_TYPE reason_spinlock = portMUX_INITIALIZER_UNLOCKED;
static volatile uint32_t reason[CONFIG_FREERTOS_NUMBER_OF_CORES]; 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 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. 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. * 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) { 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) { if (my_reason_val & REASON_PRINT_BACKTRACE) {
esp_backtrace_print(100); esp_backtrace_print(100);
@@ -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 * 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); 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 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
/** /**
* Send an interrupt to a CPU indicating it should print its current backtrace * Send an interrupt to a CPU indicating it should print its current backtrace
@@ -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
@@ -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 * 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); 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 #ifdef __cplusplus
} }
#endif #endif
@@ -34,9 +34,13 @@
#define _ESP_SYS_EVENT_SECTION_SHUTDOWN esysev_shdn #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_CORE esysev_initc
#define _ESP_SYS_EVENT_SECTION_SYSTEM_INIT_SECONDARY esysev_inits #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 #endif
/* ESP_SYS_EVENT_DEF(ENUM_SUFFIX) */ /* ESP_SYS_EVENT_DEF(ENUM_SUFFIX) */
ESP_SYS_EVENT_DEF(SHUTDOWN) ESP_SYS_EVENT_DEF(SHUTDOWN)
ESP_SYS_EVENT_DEF(SYSTEM_INIT_CORE) ESP_SYS_EVENT_DEF(SYSTEM_INIT_CORE)
ESP_SYS_EVENT_DEF(SYSTEM_INIT_SECONDARY) ESP_SYS_EVENT_DEF(SYSTEM_INIT_SECONDARY)
ESP_SYS_EVENT_DEF(PANIC)
ESP_SYS_EVENT_DEF(PANIC_EARLY_BREAK)
@@ -21,6 +21,16 @@ SECTIONS
PROVIDE(_esysev_inits_start = .); PROVIDE(_esysev_inits_start = .);
KEEP(*(SORT_BY_INIT_PRIORITY(.esysev_inits.*))) KEEP(*(SORT_BY_INIT_PRIORITY(.esysev_inits.*)))
PROVIDE(_esysev_inits_end = .); 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; INSERT AFTER .data;
+13 -1
View File
@@ -12,12 +12,22 @@ entries:
entries: entries:
.esysev_inits+ .esysev_inits+
[sections:esysev_panic]
entries:
.esysev_panic+
[sections:esysev_paneb]
entries:
.esysev_paneb+
# Default placements (overridden below with ALIGN/SURROUND flags) # Default placements (overridden below with ALIGN/SURROUND flags)
[scheme:esp_sys_event_default] [scheme:esp_sys_event_default]
entries: entries:
esysev_shdn -> flash_rodata esysev_shdn -> flash_rodata
esysev_initc -> flash_rodata esysev_initc -> flash_rodata
esysev_inits -> flash_rodata esysev_inits -> flash_rodata
esysev_panic -> flash_rodata
esysev_paneb -> flash_rodata
[mapping:esp_sys_event] [mapping:esp_sys_event]
archive: * archive: *
@@ -25,7 +35,9 @@ entries:
* (esp_sys_event_default); * (esp_sys_event_default);
esysev_shdn -> flash_rodata ALIGN(4, pre) KEEP() SORT(init_priority) SURROUND(esysev_shdn), 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_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 ============== # ============== esp_system component mappings ==============
+31 -44
View File
@@ -23,6 +23,8 @@
#include "esp_private/esp_int_wdt.h" #include "esp_private/esp_int_wdt.h"
#include "esp_private/panic_internal.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 "port/panic_funcs.h"
#include "esp_rom_sys.h" #include "esp_rom_sys.h"
@@ -35,22 +37,10 @@
#endif #endif
#endif // CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT #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 #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
#include "hal/uart_hal.h" #include "hal/uart_hal.h"
#endif #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 #if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG || CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG
#include "hal/usb_serial_jtag_ll.h" #include "hal/usb_serial_jtag_ll.h"
#endif #endif
@@ -270,9 +260,20 @@ void esp_panic_handler_feed_wdts(void)
} }
#endif /* SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED */ #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 #if SOC_WDT_SUPPORTED || SOC_RTC_WDT_SUPPORTED
/* This function disables all the watchdogs */ /* This function disables all the watchdogs */
static inline void disable_all_wdts(void) void panic_disable_all_wdts(void)
{ {
#if SOC_WDT_SUPPORTED #if SOC_WDT_SUPPORTED
//Disable Timer Group WDTs //Disable Timer Group WDTs
@@ -286,7 +287,7 @@ static inline void disable_all_wdts(void)
#endif /* SOC_RTC_WDT_SUPPORTED */ #endif /* SOC_RTC_WDT_SUPPORTED */
} }
#else /* SOC_WDT_SUPPORTED || 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 */ #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_hex((uint32_t)info->addr);
panic_print_str(" and returning...\r\n"); panic_print_str(" and returning...\r\n");
#if CONFIG_ESP_TRACE_ENABLE // Trigger early breakpoint handlers before returning to debugger.
esp_trace_panic_handler(info); // This allows trace to dump info before breaking
#endif 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 esp_cpu_set_breakpoint(0, info->addr); // use breakpoint 0
return; return;
} }
@@ -432,28 +436,16 @@ void esp_panic_handler(panic_info_t *info)
panic_print_str("\r\n"); panic_print_str("\r\n");
#if CONFIG_ESP_TRACE_ENABLE // Trigger esp_sys_event panic handlers (includes trace, coredump, gdbstub if enabled)
esp_panic_handler_feed_wdts(); // If gdbstub is enabled and registered, it will take over and never return.
esp_trace_panic_handler(info); // If we return here, proceed to reboot/halt.
#endif {
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 #if CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS
esp_panic_handler_feed_wdts(); 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 */ #else /* CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT || CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT */
esp_panic_handler_feed_wdts(); esp_panic_handler_feed_wdts();
panic_print_str("CPU halted.\r\n"); panic_print_str("CPU halted.\r\n");
disable_all_wdts(); panic_disable_all_wdts();
esp_panic_handler_reset_modules_on_exit_and_halt(); 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_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) 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 = true;
g_panic_abort_details = (char *) details; g_panic_abort_details = (char *) details;
#if CONFIG_ESP_TRACE_ENABLE
esp_trace_panic_handler(NULL);
#endif
#ifdef __XTENSA__ #ifdef __XTENSA__
asm("ill"); // should be an invalid operation on xtensa targets asm("ill"); // should be an invalid operation on xtensa targets
#elif __riscv #elif __riscv
+1
View File
@@ -30,6 +30,7 @@ set(priv_requires
"esp_hal_usb" "esp_hal_usb"
"esp_driver_usb_serial_jtag" "esp_driver_usb_serial_jtag"
"esp_timer" "esp_timer"
"esp_system"
) )
set(priv_includes "") set(priv_includes "")
set(requires "app_trace") set(requires "app_trace")
@@ -23,6 +23,8 @@
#include "esp_trace.h" #include "esp_trace.h"
#include "esp_trace_port_transport.h" #include "esp_trace_port_transport.h"
#include "esp_private/startup_internal.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"; 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 __attribute__((weak)) esp_trace_get_user_params(void)
{ {
esp_trace_open_params_t trace_params = { esp_trace_open_params_t trace_params = {
+21 -1
View File
@@ -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 * SPDX-License-Identifier: Apache-2.0
*/ */
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_private/startup_internal.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" #include "esp_core_dump.h"
// Hook to force the linker to include this file // 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(); esp_core_dump_init();
return ESP_OK; 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;
}