Repository navigation
Description
Found on the first hardware run of any PlatformIO-built Field Compass image (um_feather, um_feathers3 @ 253f7af, 2026-09-07 evening, #283). The board boot-loops:
Initializing ST7796U TFT... Guru Meditation Error: Core 1 panic'ed (StoreProhibited)
EXCVADDR: 0x00000010 PC 0x42004363 = TFT_eSPI::begin_tft_write() TFT_eSPI.cpp:81 (SET_BUS_WRITE_MODE), from TFT_eSPI::init() <- initTFT() display.cpp:18 <- setup()
Verified with addr2line and objdump against the flashed ELF (sha 1905d2e7f): the faulting instruction is 's32i a9, a8, 0' with a8 = 16 and a9 = 1<<27 (SPI_USR_MOSI), i.e. a write to address 0x10 = SPI_USER_REG(SPI_PORT) with the register base evaluating to 0.
Cause, all verified in the pinned toolchain (platform 55.03.38-1, core 3.3.8, TFT_eSPI 2.5.43):
- Processors/TFT_eSPI_ESP32_S3.h line 83: for ESP32-S3 with neither USE_HSPI_PORT nor USE_FSPI_PORT, SPI_PORT is FSPI.
- cores/esp32/esp32-hal-spi.h line 35: on ESP32-S3, FSPI is 0 (bus index), not a GPSPI number.
- esp32s3 soc.h line 36: REG_SPI_BASE(i) is 0 for i < 2 (only GPSPI2 and GPSPI3 exist). TFT_eSPI's own fallback definition is under #ifndef REG_SPI_BASE, so it never applies.
- Result: _spi_cmd/_spi_user/_spi_mosi_dlen/_spi_w are NULL + offset; the first SPI write faults.
The feather_s3 (Adafruit) image built from the same flags has the identical instruction sequence (checked in both the #280 baseline ELF and the #283 build), so the Adafruit PlatformIO image has never worked either. C:\Dev.field_compass\flash-history.jsonl confirms no feather_s3 PlatformIO image was ever flashed; the #193 'first complete PlatformIO build' (#184/#185) was verified by compiling and linking, not on hardware. This is not a pin or wiring problem and not specific to the UM board.
Upstream TFT_eSPI master has since changed the ESP32-S3 default to 'SPI_PORT 2' (GPSPI2). In 2.5.43 the equivalent is -D USE_FSPI_PORT=1: SPI_PORT becomes 2 and TFT_eSPI instantiates its own SPIClass(FSPI), which is SPI2_HOST, the same controller the Arduino SPI object (SD, FRAM) uses. The alternative, USE_HSPI_PORT, would put the TFT on GPSPI3 while SD/FRAM stay on GPSPI2 with both routed to GPIO 36/35/37; the later SPI.begin for the SD card would steal the pin matrix from the TFT. The design comment at src.ino:575 says the TFT shares the FSPI bus, so USE_FSPI_PORT matches the design.
Fix: add -D USE_FSPI_PORT=1 to the shared build_flags in platformio.ini (both envs) with this rationale. Test, falsifiable: after re-flash the boot log prints 'Initializing ST7796U TFT... OK', the panel flashes red then shows the init screen, and the SD/FRAM init lines that follow SPI.begin still report their devices; if the panel goes dark after 'Initializing hardware...', the second SPIClass on the shared bus is the next suspect.
Consequence for the record: the PlatformIO migration (Epic #154, B2 #184) has not had a hardware-verified image until this is fixed; B6 #188 parity work should note it.
Activity
Strycher commentedon Sep 8, 2026
Hardware result, um_feather, 2026-09-08 00:11 EDT, image d6fa305 (USE_FSPI_PORT + SD/FRAM on TFT_eSPI::getSPIinstance()): tft.init() no longer faults, 'Initializing SD card... OK (30436 MB)', 'Initializing FRAM... OK (mfg:0x04 prod:0x4803, 256KB)'. On 8af7ce5 (USE_FSPI_PORT alone) the first SD.begin never returned. Same board, same wiring, only change = one SPIClass per controller. The SD hang was the second driver on GPSPI2. Remaining on this branch: the TFT panel shows backlight only (SPI bus proven by SD/FRAM; CS/DC/RST wiring or panel power still open, tracked in #283).
Strycher commentedon Sep 8, 2026
In PR #288 (8af7ce5 + d6fa305). Verified on um_feather across every boot from 2026-09-08 00:11 on: tft.init() completes, SD mounts, FRAM answers, TFT draws. Both root causes stand as written: SPI_PORT = FSPI = 0 in TFT_eSPI 2.5.43 on the S3 (fixed by USE_FSPI_PORT), and a second SPIClass on GPSPI2 hanging the first SD mount (fixed by SD/FRAM using TFT_eSPI::getSPIinstance()). CLAUDE.md now says so in the Display row.
fix(#284): select GPSPI2 for TFT_eSPI on ESP32-S3 (USE_FSPI_PORT)
fix(#284): one SPI driver per bus; scan both I2C buses on the Feather…
fix(#284): select GPSPI2 for TFT_eSPI on ESP32-S3 (USE_FSPI_PORT)
fix(#284): one SPI driver per bus; scan both I2C buses on the Feather…