89static const char *
const TAG =
"esp32.crash";
92 if (s_raw_crash_data.magic == CRASH_MAGIC && s_raw_crash_data.version == CRASH_DATA_VERSION) {
93 s_crash_data_valid =
true;
95 if (s_raw_crash_data.backtrace_count > MAX_BACKTRACE)
96 s_raw_crash_data.backtrace_count = MAX_BACKTRACE;
97 if (s_raw_crash_data.reg_frame_count > s_raw_crash_data.backtrace_count)
98 s_raw_crash_data.reg_frame_count = s_raw_crash_data.backtrace_count;
99 if (s_raw_crash_data.exception > 4)
100 s_raw_crash_data.exception = 4;
101 if (s_raw_crash_data.pseudo_excause > 1)
102 s_raw_crash_data.pseudo_excause = 0;
105 s_raw_crash_data.magic = 0;
113static const char *get_exception_reason() {
114#if CONFIG_IDF_TARGET_ARCH_XTENSA
115 if (s_raw_crash_data.pseudo_excause) {
118 static const char *
const PSEUDO_REASON[] = {
120 "Unhandled debug exception",
122 "Unhandled kernel exception",
123 "Coprocessor exception",
124 "Interrupt wdt timeout on CPU0",
125 "Interrupt wdt timeout on CPU1",
128 uint32_t cause = s_raw_crash_data.cause;
129 if (cause <
sizeof(PSEUDO_REASON) /
sizeof(PSEUDO_REASON[0]))
130 return PSEUDO_REASON[cause];
131 return PSEUDO_REASON[0];
134 static const char *
const REASON[] = {
135 "IllegalInstruction",
137 "InstructionFetchError",
141 "IntegerDivideByZero",
144 "LoadStoreAlignment",
148 "LoadStorePIFDataError",
150 "LoadStorePIFAddrError",
153 "InstFetchPrivilege",
155 "InstrFetchProhibited",
160 "LoadStoreTLBMultihit",
161 "LoadStorePrivilege",
166 uint32_t cause = s_raw_crash_data.cause;
167 if (cause <
sizeof(REASON) /
sizeof(REASON[0]) && REASON[cause] !=
nullptr)
168 return REASON[cause];
169#elif CONFIG_IDF_TARGET_ARCH_RISCV
173 if (s_raw_crash_data.pseudo_excause)
175 static const char *
const REASON[] = {
176 "Instruction address misaligned",
177 "Instruction access fault",
178 "Illegal instruction",
180 "Load address misaligned",
182 "Store address misaligned",
183 "Store access fault",
184 "Environment call from U-mode",
185 "Environment call from S-mode",
187 "Environment call from M-mode",
188 "Instruction page fault",
193 uint32_t cause = s_raw_crash_data.cause;
194 if (cause <
sizeof(REASON) /
sizeof(REASON[0]) && REASON[cause] !=
nullptr)
195 return REASON[cause];
201static const char *get_exception_type() {
202 static const char *
const TYPES[] = {
209 uint8_t exc = s_raw_crash_data.exception;
210 if (exc <
sizeof(TYPES) /
sizeof(TYPES[0]))
221 if (!s_crash_data_valid)
224 ESP_LOGE(TAG,
"*** CRASH DETECTED ON PREVIOUS BOOT ***");
225 const char *reason = get_exception_reason();
226 if (reason !=
nullptr) {
227 ESP_LOGE(TAG,
" Reason: %s - %s", get_exception_type(), reason);
229 ESP_LOGE(TAG,
" Reason: %s", get_exception_type());
231 ESP_LOGE(TAG,
" PC: 0x%08" PRIX32
" (fault location)", s_raw_crash_data.pc);
233 for (uint8_t i = 0; i < s_raw_crash_data.backtrace_count; i++) {
234 uint32_t addr = s_raw_crash_data.backtrace[i];
235#if CONFIG_IDF_TARGET_ARCH_RISCV
237 if (i >= s_raw_crash_data.reg_frame_count && !is_return_addr(addr))
240#if CONFIG_IDF_TARGET_ARCH_RISCV
241 const char *
source = (i < s_raw_crash_data.reg_frame_count) ?
"backtrace" :
"stack scan";
243 const char *
source =
"backtrace";
245 ESP_LOGE(TAG,
" BT%d: 0x%08" PRIX32
" (%s)", bt_num++, addr,
source);
249 int pos = snprintf(hint,
sizeof(hint),
"Use: addr2line -pfiaC -e firmware.elf 0x%08" PRIX32, s_raw_crash_data.pc);
250 for (uint8_t i = 0; i < s_raw_crash_data.backtrace_count &&
pos < (int)
sizeof(hint) - 12; i++) {
251 uint32_t addr = s_raw_crash_data.backtrace[i];
252#if CONFIG_IDF_TARGET_ARCH_RISCV
253 if (i >= s_raw_crash_data.reg_frame_count && !is_return_addr(addr))
256 pos += snprintf(hint +
pos,
sizeof(hint) -
pos,
" 0x%08" PRIX32, addr);
258 ESP_LOGE(TAG,
"%s", hint);
274 s_raw_crash_data.pc = (
uint32_t) info->addr;
275 s_raw_crash_data.backtrace_count = 0;
276 s_raw_crash_data.reg_frame_count = 0;
277 s_raw_crash_data.exception = (uint8_t) info->exception;
278 s_raw_crash_data.pseudo_excause = info->pseudo_excause ? 1 : 0;
280#if CONFIG_IDF_TARGET_ARCH_XTENSA
282 if (info->frame !=
nullptr) {
283 auto *xt_frame = (XtExcFrame *) info->frame;
284 s_raw_crash_data.cause = xt_frame->exccause;
285 esp_backtrace_frame_t bt_frame = {
289 .exc_frame = xt_frame,
294 uint32_t first_pc = esp_cpu_process_stack_pc(bt_frame.pc);
295 if (is_code_addr(first_pc)) {
296 s_raw_crash_data.backtrace[count++] = first_pc;
299 while (count < MAX_BACKTRACE && bt_frame.next_pc != 0) {
300 if (!esp_backtrace_get_next_frame(&bt_frame)) {
303 uint32_t pc = esp_cpu_process_stack_pc(bt_frame.pc);
304 if (is_code_addr(
pc)) {
305 s_raw_crash_data.backtrace[count++] =
pc;
308 s_raw_crash_data.backtrace_count = count;
311#elif CONFIG_IDF_TARGET_ARCH_RISCV
313 if (info->frame !=
nullptr) {
314 auto *rv_frame = (RvExcFrame *) info->frame;
315 s_raw_crash_data.cause = rv_frame->mcause;
319 if (is_code_addr(rv_frame->mepc)) {
320 s_raw_crash_data.backtrace[count++] = rv_frame->mepc;
322 if (is_code_addr(rv_frame->ra) && rv_frame->ra != rv_frame->mepc) {
323 s_raw_crash_data.backtrace[count++] = rv_frame->ra;
328 s_raw_crash_data.reg_frame_count = count;
333 for (
uint32_t i = 0; i < 64 && count < MAX_BACKTRACE; i++) {
335 if (is_code_addr(
val) &&
val != rv_frame->mepc &&
val != rv_frame->ra) {
336 s_raw_crash_data.backtrace[count++] =
val;
339 s_raw_crash_data.backtrace_count = count;
344 s_raw_crash_data.version = CRASH_DATA_VERSION;
345 s_raw_crash_data.magic = CRASH_MAGIC;