#if defined(ESP_PLATFORM) && defined(CONFIG_IDF_TARGET_ARCH_XTENSA) #include "Tactility/kernel/PanicHandler.h" #include #include #include #include #include #include extern "C" { /** * This static variable survives a crash reboot. * It is reset by the Boot app. */ static RTC_NOINIT_ATTR CrashData crashData; void __real_esp_panic_handler(void* info); void __wrap_esp_panic_handler(void* info) { esp_backtrace_frame_t frame = { .pc = 0, .sp = 0, .next_pc = 0, .exc_frame = nullptr }; crashData.callstackLength = 0; esp_backtrace_get_start(&frame.pc, &frame.sp, &frame.next_pc); crashData.callstack[0].pc = frame.pc; #if CRASH_DATA_INCLUDES_SP crashData.callstack[0].sp = frame.sp; #endif crashData.callstackLength++; uint32_t processed_pc = esp_cpu_process_stack_pc(frame.pc); bool pc_is_valid = esp_ptr_executable((void *)processed_pc); /* Ignore the first corrupted PC in case of InstrFetchProhibited on Xtensa */ if (frame.exc_frame && ((XtExcFrame *)frame.exc_frame)->exccause == EXCCAUSE_INSTR_PROHIBITED) { pc_is_valid = true; } crashData.callstackCorrupted = !(esp_stack_ptr_is_sane(frame.sp) && pc_is_valid); while ( frame.next_pc != 0 && !crashData.callstackCorrupted && crashData.callstackLength < CRASH_DATA_CALLSTACK_LIMIT ) { if (esp_backtrace_get_next_frame(&frame)) { // Validate the current frame uint32_t processed_frame_pc = esp_cpu_process_stack_pc(frame.pc); bool frame_pc_is_valid = esp_ptr_executable((void *)processed_frame_pc); if (!esp_stack_ptr_is_sane(frame.sp) || !frame_pc_is_valid) { crashData.callstackCorrupted = true; break; } crashData.callstack[crashData.callstackLength].pc = frame.pc; #if CRASH_DATA_INCLUDES_SP crashData.callstack[crashData.callstackLength].sp = frame.sp; #endif crashData.callstackLength++; } else { crashData.callstackCorrupted = true; break; } } // TODO: Handle corrupted logic __real_esp_panic_handler(info); } } const CrashData& getRtcCrashData() { return crashData; } #elif defined(ESP_PLATFORM) // Stub implementation for RISC-V and other architectures // TODO: Implement crash data collection for RISC-V using frame pointer or EH frame #include static CrashData emptyCrashData = {}; const CrashData& getRtcCrashData() { return emptyCrashData; } #endif