From 580a99d3ba2e6674948564f4b36d904b7fc06068 Mon Sep 17 00:00:00 2001 From: Matt Edholm Date: Sun, 17 May 2026 15:19:41 -0400 Subject: [PATCH] fix(13e6): yield to scheduler during bit-banged SPI push MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bit-banged SPI runs a multi-second tight loop (~480000 byte sends per half × 8 GPIO toggles per byte). Without periodic scheduler yields the interrupt watchdog can bite during a full-frame push, especially with PSRAM-backed reads adding cache-miss latency. Adds esp_task_wdt_reset() + vTaskDelay(0) every ~4 KB in epd_fill and every 8 rows in push_full_frame so the WDT stays fed and other FreeRTOS tasks get a turn. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/panels/waveshare13e6/v1/epd_driver.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/panels/waveshare13e6/v1/epd_driver.cpp b/src/panels/waveshare13e6/v1/epd_driver.cpp index 5b8df9c..bea217f 100644 --- a/src/panels/waveshare13e6/v1/epd_driver.cpp +++ b/src/panels/waveshare13e6/v1/epd_driver.cpp @@ -243,9 +243,13 @@ static void push_full_frame(const uint8_t* fb) { for (uint16_t x = 0; x < HALF_BYTES_ROW; x++) { spi_write_byte(row[x]); } - // Yield to the watchdog every ~16 rows so it doesn't reset us - // during the multi-second per-half push. - if ((y & 0x0F) == 0) esp_task_wdt_reset(); + // Yield to scheduler (and feed the watchdog) every 8 rows + // so neither the task WDT nor the interrupt WDT bites during + // the multi-second bit-banged push. + if ((y & 0x07) == 0) { + esp_task_wdt_reset(); + vTaskDelay(0); + } } cs(cs_pin, HIGH); } @@ -263,7 +267,10 @@ void epd_fill(uint8_t color) { begin_cmd(p, 0x10); for (size_t i = 0; i < (size_t)HALF_BYTES_ROW * H; i++) { spi_write_byte(byte); - if ((i & 0x1FFF) == 0) esp_task_wdt_reset(); + if ((i & 0x0FFF) == 0) { + esp_task_wdt_reset(); + vTaskDelay(0); + } } cs(p, HIGH); }