The LX106 (ESP8266) has no MMU, TLB, PIF, or privilege levels, so
exception causes 1, 5, 7, 8, 12-18, and 24-26 can never occur.
Remove them and shorten remaining cause names. Also drop Syscall,
Alloca, PCValue, Privileged which are unreachable on this core.
GCC's ROM divide routine triggers IllegalInstruction (exccause=0) at
ROM addresses 0x4000dce5/0x4000dd3d instead of IntegerDivideByZero
(exccause=6). Patch exccause to match the Arduino core's postmortem
handler behavior.
WDT resets also populate exccause in rst_info (e.g. Level1Interrupt
for stack overflow soft WDT). Show the cause string for all crash
reasons, not just REASON_EXCEPTION_RST. Also simplify PC logging
to a single line for all crash types.
resetInfo is a global that persists until next reset — no need to
cache the crash validity in a separate bool. Check resetInfo.reason
directly in crash_handler_has_data() and crash_handler_log().
This eliminates the only RAM byte from the crash handler and removes
the now-empty crash_handler_read_and_clear() function and its call
from arch_init().
Remove EPC2/EPC3 (always 0 on LX106, no level 2/3 interrupts) and
DEPC (extremely rare double exception). Combine PC and EXCVADDR into
one log line for exception resets. Shrink hint buffer 256->220.
Saves ~36 bytes flash in crash_handler_log.
Switch statements generate CSWTCH jump tables in RAM on ESP8266.
PROGMEM_STRING_TABLE causes LoadStoreError from flash cache conflicts
in API subscribe paths. If-else with LOG_STR avoids both: strings
stay in flash via PSTR, and comparison branches don't need a data
table. Zero RAM overhead confirmed via nm.
Reading IROM addresses from IROM code causes LoadStoreError on ESP8266
due to the direct-mapped flash cache — the reading code and target
address can share a cache line, evicting the function mid-execution.
Remove is_return_addr() and rely on linker-symbol IROM bounds
(_irom0_text_start/_end) to eliminate false positives instead. This
is less precise but crash-safe.
Two issues:
1. safe_read_code_byte used volatile cast which prevented the compiler
from using flash-safe l32i instructions, causing LoadStoreError on
IROM addresses. Replace with progmem_read_byte.
2. IROM upper bound (0x40400000 = 2MB) was too generous for devices
with smaller flash (e.g. 1MB), causing both false positives in the
backtrace and faults when is_return_addr tried to verify CALL
instructions at unmapped addresses. Use _irom0_text_start/end
linker symbols for precise firmware code bounds.
GCC generates CSWTCH jump tables in RAM rodata on ESP8266 for switch
statements. Convert exception cause and reset reason lookups to
PROGMEM_STRING_TABLE which keeps data in flash. Exception causes are
split into two tables (0-9 and 12-29) to stay under the 255-byte
blob limit. Added static_asserts on reset reason enum values.
- Verify each candidate is a real return address by checking that the
instruction at addr-3 is a CALL/CALLX (Xtensa 3-byte call opcodes).
This filtering happens at log time when flash is readable, similar
to the ESP32 RISC-V handler's is_return_addr() approach.
- Scan the entire stack instead of just 64 words — with filtering,
false positives from stale stack data are eliminated.
- Skip epc1 during scanning (already reported as fault PC).
- Increase to 16 RTC slots (72 bytes) for broader capture before
filtering. Bump hint buffer to 256 for more addresses.
A null EXCVADDR (0x00000000) is the key diagnostic for null pointer
crashes (LoadProhibited/StoreProhibited). Suppressing it when zero
hides the most useful information.
Add a crash handler for ESP8266 that captures and logs crash data
from previous boots, matching the existing ESP32 and RP2040
implementations. Uses the SDK's rst_info (always available after
reboot) for basic crash info and Arduino's custom_crash_callback
to scan the stack for return addresses stored in RTC user memory.
Co-authored-by: J. Nick Koston <nick@home-assistant.io>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>