Selaa lähdekoodia

Feed the task watchdog during GxEPD2's busy-wait spin

GxEPD2_EPD::_waitWhileBusy() polls the busy pin via delay()/yield() for
up to _busy_timeout (30-50s for the color panels) - deliberately long,
since a real refresh can legitimately take that many seconds. Neither
esphome::delay() nor esphome::yield() resets the ESP-IDF task watchdog,
so a busy-wait anywhere near that long - a real slow refresh, or busy
read with inverted polarity so it never appears to release - overruns
the watchdog and reboots the device before the loop's own timeout ever
gets a chance to break out and log "Busy Timeout!".
ZiB 1 kuukausi sitten
vanhempi
sitoutus
d3314558a7
1 muutettua tiedostoa jossa 18 lisäystä ja 2 poistoa
  1. 18 2
      components/gxepd2/arduino_compat/Arduino.h

+ 18 - 2
components/gxepd2/arduino_compat/Arduino.h

@@ -10,6 +10,7 @@
 #include <sstream>
 #include <string>
 
+#include "esphome/core/application.h"
 #include "esphome/core/hal.h"
 #include "esphome/core/log.h"
 #include "esphome/components/gxepd2/pin_registry.h"
@@ -36,9 +37,24 @@ inline int digitalRead(int16_t pin) {
   return (p != nullptr && p->digital_read()) ? HIGH : LOW;
 }
 
-inline void delay(uint32_t ms) { esphome::delay(ms); }
+// GxEPD2_EPD::_waitWhileBusy() spins on these two (delay() in its main
+// branch, yield() right after) for as long as the busy pin stays asserted -
+// deliberately up to tens of seconds (_busy_timeout), since a real 3/4-color
+// refresh can legitimately take that long. Neither esphome::delay() nor
+// esphome::yield() resets the ESP-IDF task watchdog on their own, so
+// without an explicit feed here, a real (or a misconfigured-polarity, thus
+// permanently "busy") wait outlasts the watchdog and the whole device
+// reboots mid-refresh instead of the loop's own timeout ever getting a
+// chance to fire.
+inline void delay(uint32_t ms) {
+  esphome::App.feed_wdt();
+  esphome::delay(ms);
+}
 inline uint32_t micros() { return esphome::micros(); }
-inline void yield() { esphome::yield(); }
+inline void yield() {
+  esphome::App.feed_wdt();
+  esphome::yield();
+}
 
 #define pgm_read_byte(addr) (*reinterpret_cast<const uint8_t *>(addr))