Select one of the symbols to view example projects that use it.
 
Outline
#include <stdlib.h>
#include "esp_macros.h"
#include "esp_ipc_isr.h"
#include "esp_private/system_internal.h"
#include "esp_private/cache_utils.h"
#include "soc/soc_memory_layout.h"
#include "esp_cpu.h"
#include "soc/soc_caps.h"
#include "soc/rtc.h"
#include "hal/soc_hal.h"
#include "esp_private/cache_err_int.h"
#include "sdkconfig.h"
#include "esp_rom_sys.h"
#include "esp32s2/memprot.h"
#include "esp_memprot.h"
#include "esp_private/panic_internal.h"
#include "esp_private/panic_reason.h"
#include "hal/wdt_types.h"
#include "hal/wdt_hal.h"
#include "esp_private/hw_stack_guard.h"
wdt0_context
g_exc_frames
print_state_for_core(const void *, int)
print_state(const void *)
frame_to_panic_info(void *, panic_info_t *, bool)
busy_wait()
panic_handler(void *, bool)
panic_enable_cache()
panicHandler(void *)
xt_unhandled_exception(void *)
panic_restart()
Files
loading (1/5)...
SourceVuESP-IDF Framework and ExamplesESP-IDFcomponents/esp_system/port/panic_handler.c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 *//* ... */ #include <stdlib.h> #include "esp_macros.h" #include "esp_ipc_isr.h" #include "esp_private/system_internal.h" #include "esp_private/cache_utils.h" #include "soc/soc_memory_layout.h" #include "esp_cpu.h" #include "soc/soc_caps.h" #include "soc/rtc.h" #include "hal/soc_hal.h" #include "esp_private/cache_err_int.h" #include "sdkconfig.h" #include "esp_rom_sys.h"13 includes #if CONFIG_ESP_SYSTEM_MEMPROT_FEATURE #ifdef CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/memprot.h" #else #include "esp_memprot.h" #endif/* ... */ #endif #include "esp_private/panic_internal.h" #include "esp_private/panic_reason.h" #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); extern void esp_panic_handler(panic_info_t *); static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0}; void *g_exc_frames[SOC_CPU_CORES_NUM] = {NULL}; /* Panic handlers; these get called when an unhandled exception occurs or the assembly-level task switching / interrupt code runs into an unrecoverable error. The default task stack overflow handler and abort handler are also in here. *//* ... */ /* Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled. *//* ... */ static void print_state_for_core(const void *f, int core) { /* On Xtensa (with Window ABI), register dump is not required for backtracing. * Don't print it on abort to reduce clutter. * On other architectures, register values need to be known for backtracing. *//* ... */ #if (CONFIG_IDF_TARGET_ARCH_XTENSA && defined(XCHAL_HAVE_WINDOWED)) || \ (CONFIG_IDF_TARGET_ARCH_RISCV && CONFIG_ESP_SYSTEM_USE_EH_FRAME) if (!g_panic_abort) { #else if (true) { #endif panic_print_registers(f, core); panic_print_str("\r\n"); }{...} panic_print_backtrace(f, core); }{ ... } static void print_state(const void *f) { #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE int err_core = f == g_exc_frames[0] ? 0 : 1; #else int err_core = 0; #endif print_state_for_core(f, err_core); panic_print_str("\r\n"); #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE // If there are other frame info, print them as well for (int i = 0; i < SOC_CPU_CORES_NUM; i++) { // `f` is the frame for the offending core, see note above. if (err_core != i && g_exc_frames[i] != NULL) { print_state_for_core(g_exc_frames[i], i); panic_print_str("\r\n"); }{...} }{...} #endif/* ... */ }{ ... } static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_excause) { info->core = esp_cpu_get_core_id(); info->exception = PANIC_EXCEPTION_FAULT; info->details = NULL; info->reason = "Unknown"; info->pseudo_excause = panic_soc_check_pseudo_cause(frame, info) | pseudo_excause; if (info->pseudo_excause) { panic_soc_fill_info(frame, info); }{...} else { panic_arch_fill_info(frame, info); }{...} info->state = print_state; info->frame = frame; }{ ... } #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE FORCE_INLINE_ATTR __attribute__((__noreturn__)) void busy_wait(void) { ESP_INFINITE_LOOP(); }{ ... } /* ... */#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE static void panic_handler(void *frame, bool pseudo_excause) { panic_info_t info = { 0 }; /* * Setup environment and perform necessary architecture/chip specific * steps here prior to the system panic handler. * *//* ... */ int core_id = esp_cpu_get_core_id(); // If multiple cores arrive at panic handler, save frames for all of them g_exc_frames[core_id] = frame; #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE // 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) { // 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) { // The invalid cache access interrupt calls to the panic handler. // When the cache interrupt happens, we can not determine the CPU where the // invalid cache access has occurred. if (esp_cache_err_get_cpuid() == -1) { // We can not determine the CPU where the invalid cache access has occurred. // Print backtraces for both CPUs. if (core_id != 0) { busy_wait(); }{...} }{...} else if (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 esp_panic_handler_reconfigure_wdts(1000); esp_rom_delay_us(1); // Stall all other cores for (uint32_t i = 0; i < SOC_CPU_CORES_NUM; i++) { if (i != core_id) { esp_cpu_stall(i); }{...} }{...} #endif/* ... */ // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE esp_ipc_isr_stall_abort(); if (esp_cpu_dbgr_is_attached()) { #if __XTENSA__ if (!(esp_ptr_executable(esp_cpu_pc_to_addr(panic_get_address(frame))) && (panic_get_address(frame) & 0xC0000000U))) { /* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size * In case the PC is invalid, GDB will fail to translate addresses to function names * Hence replacing the PC to a placeholder address in case of invalid PC *//* ... */ panic_set_address(frame, (uint32_t)&_invalid_pc_placeholder); }{...} #endif/* ... */ if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE || panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 #endif ) { wdt_hal_write_protect_disable(&wdt0_context); wdt_hal_handle_intr(&wdt0_context); wdt_hal_write_protect_enable(&wdt0_context); }{...} }{...} // Convert architecture exception frame into abstracted panic info frame_to_panic_info(frame, &info, pseudo_excause); // Call the system panic handler esp_panic_handler(&info); }{ ... } /** * This function must always be in IRAM as it is required to * re-enable the flash cache. *//* ... */ #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP static void IRAM_ATTR panic_enable_cache(void) { int core_id = esp_cpu_get_core_id(); if (!spi_flash_cache_enabled()) { esp_ipc_isr_stall_abort(); spi_flash_enable_cache(core_id); }{...} }{ ... } /* ... */#endif void IRAM_ATTR panicHandler(void *frame) { #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP panic_enable_cache(); #endif // This panic handler gets called for when the double exception vector, // kernel exception vector gets used; as well as handling interrupt-based // faults cache error, wdt expiry. EXCAUSE register gets written with // one of PANIC_RSN_* values. panic_handler(frame, true); }{ ... } void IRAM_ATTR xt_unhandled_exception(void *frame) { #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP panic_enable_cache(); #endif panic_handler(frame, false); }{ ... } void __attribute__((noreturn)) panic_restart(void) { #ifdef CONFIG_IDF_TARGET_ESP32 // On the ESP32, cache error status can only be cleared by system reset if (esp_cache_err_get_cpuid() != -1) { esp_restart_noos_dig(); }{...} #endif/* ... */ esp_restart_noos(); }{ ... }
Details
Show:
from
Types: Columns:
This file uses the notable symbols shown below. Click anywhere in the file to view more details.