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>