Summary
HT_st7735::st7735_write_data() passes a pointer to read-only flash (DROM) to SPI.transfer(), which uses the buffer bidirectionally (it writes received SPI data back into the same buffer). On ESP32 core 3.x with stricter memory protection, this causes an immediate crash on boot:
Guru Meditation Error: Core 1 panic'ed (Cache error).
Dbus write to cache rejected, error address: 0x3c0c22xx
The device reboots in a loop every ~3 seconds, making it completely unusable.
Root cause
In HT_st7735.cpp, st7735_execute_cmd_list() calls:
st7735_write_data((uint8_t*)addr, numArgs);
where addr is a const uint8_t* pointing into the display init table stored in DROM (read-only flash). This is passed to:
void HT_st7735::st7735_write_data(uint8_t* buff, size_t buff_size) {
digitalWrite(_dc_pin, HIGH);
st7735_spi.transfer(buff, buff_size); // ← writes received SPI data back to buff
}
SPI.transfer(buf, size) is bidirectional — it reads from buf AND writes the received bytes back into buf. Since buf points to DROM, the write causes a StoreProhibited / Cache error exception.
This was confirmed by decoding the backtrace with xtensa-esp32s3-elf-addr2line:
__spiTransferBytes @ esp32-hal-spi.c:1227
spiTransferBytes @ esp32-hal-spi.c:1247
SPIClass::transferBytes @ SPI.cpp:307
SPIClass::transfer @ SPI.cpp:282
HT_st7735::st7735_write_data @ HT_st7735.cpp:137
HT_st7735::st7735_execute_cmd_list @ HT_st7735.cpp:155
HT_st7735::st7735_init @ HT_st7735.cpp:208
setup()
Affected boards / versions
Fix
Replace SPI.transfer() with SPI.writeBytes() in st7735_write_data(). writeBytes() is write-only and does not attempt to write received data back to the source buffer:
void HT_st7735::st7735_write_data(uint8_t* buff, size_t buff_size) {
digitalWrite(_dc_pin, HIGH);
st7735_spi.writeBytes(buff, buff_size); // write-only, safe with DROM pointers
}
One-line change, confirmed working.
Reported by michiel@bruijn.nu — diagnosed and fixed with assistance from Claude (Anthropic).
Summary
HT_st7735::st7735_write_data()passes a pointer to read-only flash (DROM) toSPI.transfer(), which uses the buffer bidirectionally (it writes received SPI data back into the same buffer). On ESP32 core 3.x with stricter memory protection, this causes an immediate crash on boot:The device reboots in a loop every ~3 seconds, making it completely unusable.
Root cause
In
HT_st7735.cpp,st7735_execute_cmd_list()calls:where
addris aconst uint8_t*pointing into the display init table stored in DROM (read-only flash). This is passed to:SPI.transfer(buf, size)is bidirectional — it reads frombufAND writes the received bytes back intobuf. Sincebufpoints to DROM, the write causes aStoreProhibited/Cache errorexception.This was confirmed by decoding the backtrace with
xtensa-esp32s3-elf-addr2line:Affected boards / versions
Fix
Replace
SPI.transfer()withSPI.writeBytes()inst7735_write_data().writeBytes()is write-only and does not attempt to write received data back to the source buffer:One-line change, confirmed working.
Reported by michiel@bruijn.nu — diagnosed and fixed with assistance from Claude (Anthropic).