fix(13e6): partition + SPI corruption + bootstrap stay-awake
Three problems surfaced during the first 13.3" end-to-end run: 1) LittleFS IntegerDivideByZero on 200 → write /img.bin. Cause: the ~3.5 MB SPIFFS in default_16MB.csv can't fit three 960 KB setup screens + a 960 KB cached image (~3.84 MB). Switching to a custom partitions_13e6.csv with 24 MB LittleFS on the 32 MB flash. 2) Yellow wash across the panel on long SPI bursts. Cause: SPI DMA from a PSRAM-backed scratch buffer hits a cache-coherency window — the CPU's writes hadn't reached PSRAM yet when DMA read it. Push each half in 8 KB chunks through an internal-SRAM (DMA-coherent) scratch, and drop the bus clock to 4 MHz to match the 7.3" production speed. 3) Bootstrap window (no image yet) was deep-sleeping for 15 s between polls — each cycle a ~5 s ROM-boot + Wi-Fi reconnect, so the user waited ~20 s × N retries between scanning the setup QR and seeing their first photo land. Now normal_operation_impl returns early during bootstrap and main.cpp's normal_operation loops with a 2 s delay, keeping Wi-Fi up. Once the first image arrives, the normal scheduled deep sleep takes over. Also fixes a related bug Matt called out: a transient TLS hiccup during bootstrap was hitting the 5xx fallback path and painting a full yellow fill over the green setup QR, leaving the user with no claim path. Criterion is now "does /img.bin exist?" (panel has something worth showing with a border) rather than "is currentImgId set?", so a fresh device with no cached image preserves the setup screen through transient network errors. Diagnostic prints in the panel driver + [op] start/code lines in normal_operation_impl that proved invaluable during bringup; leaving them in for now. Tests updated for the new bootstrap semantics (deep sleep no longer arms on bootstrap-cycle 204/404/5xx); 43/43 native tests pass, 7.3" production build stays byte-identical. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -209,6 +209,9 @@ static void ensure_dma_scratch() {
|
||||
if (!g_dma_scratch) {
|
||||
g_dma_scratch = (uint8_t*)heap_caps_malloc(
|
||||
DMA_CHUNK, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA);
|
||||
Serial.printf("[epd13e6] dma_scratch=%p (free internal=%u)\n",
|
||||
g_dma_scratch,
|
||||
(unsigned)heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +238,12 @@ static void push_half(int cs_pin, const uint8_t* half_fb, size_t bytes) {
|
||||
static void push_full_frame(const uint8_t* fb) {
|
||||
constexpr size_t HALF_BYTES = (size_t)HALF_BYTES_ROW * H;
|
||||
uint8_t* slice = (uint8_t*)heap_caps_malloc(HALF_BYTES, MALLOC_CAP_SPIRAM);
|
||||
if (!slice) return;
|
||||
if (!slice) {
|
||||
Serial.printf("[epd13e6] push_full_frame: slice alloc FAILED (free PSRAM=%u)\n",
|
||||
(unsigned)ESP.getFreePsram());
|
||||
return;
|
||||
}
|
||||
Serial.println("[epd13e6] push_full_frame: pushing halves");
|
||||
|
||||
for (uint16_t y = 0; y < H; y++) {
|
||||
memcpy(slice + (size_t)y * HALF_BYTES_ROW,
|
||||
@@ -252,6 +260,7 @@ static void push_full_frame(const uint8_t* fb) {
|
||||
push_half(PIN_CS_S, slice, HALF_BYTES);
|
||||
|
||||
heap_caps_free(slice);
|
||||
Serial.println("[epd13e6] push_full_frame: done");
|
||||
}
|
||||
|
||||
// ── epd.h surface ──────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user