Răsfoiți Sursa

Document unresolved watchdog crash on gxepd2_update and a bigger alternative

Still crashes on real hardware with "gxepd2_update" named as the task
that didn't reset in time, despite the task being subscribed to the
watchdog and every long-running spot found so far (Arduino.h's
busy-wait, SPI.h's per-256-byte throttle) resetting it directly. Not
chased further this session - there's evidently another GxEPD2 call
path that runs long without passing through either of those two spots.

Also noting, for a future session: the real value GxEPD2 gives us is
its per-panel database and reference implementation, not its
synchronous, no-yield-points control flow - which is exactly what's
fighting the task/watchdog model here. Extracting just the per-device
data and reimplementing the drawing/refresh loop natively in esphome's
chunked loop() style (like epaper_spi) would drop this task, and the
fragility that comes with it, entirely. A real rewrite, not a patch -
worth weighing before sinking more time into this shape.
ZiB 1 lună în urmă
părinte
comite
4c83aa16f1
1 a modificat fișierele cu 25 adăugiri și 0 ștergeri
  1. 25 0
      components/gxepd2/gxepd2_display.h

+ 25 - 0
components/gxepd2/gxepd2_display.h

@@ -138,6 +138,31 @@ class GxEPD2Display : public display::DisplayBuffer {
     //    shared spi: bus should mostly be fine - but that's about the
     //    write phase, not this task boundary, and hasn't been stress-tested
     //    against another device on the same bus mid-refresh.
+    //
+    // KNOWN ISSUE, unresolved as of this comment: on real hardware,
+    // "gxepd2_update" itself still sometimes trips the ESP-IDF task
+    // watchdog (confirmed via the panic naming it directly), despite: (1)
+    // being explicitly subscribed to it (see update_task_loop_), and (2)
+    // every long-running spot we've found - the busy-wait in
+    // arduino_compat/Arduino.h, the per-256-byte throttle in
+    // arduino_compat/SPI.h - calling esp_task_wdt_reset() directly rather
+    // than through esphome's globally-rate-limited App.feed_wdt(). Not
+    // chased further this session; likely another GxEPD2 call path that
+    // runs long without hitting either of those two spots.
+    //
+    // Bigger-picture option worth weighing before sinking more time into
+    // patching this shape further: the actual value GxEPD2 gives us is its
+    // per-panel database (dimensions, init sequences, LUTs, quirks like
+    // 579c's master/slave split) and a reference implementation to check
+    // against - not really its control flow, which is exactly what's
+    // fighting us here (synchronous, no yield points, not built for
+    // esphome's cooperative loop() model). A future pass could extract
+    // just the per-device data/sequences and reimplement the actual
+    // drawing/refresh loop natively in esphome's chunked loop() style
+    // (like epaper_spi), dropping this task entirely along with whatever
+    // watchdog and thread-safety fragility comes with it. That's a real
+    // rewrite, not a patch - worth a dedicated pass, not a continuation of
+    // this one.
     this->lambda_done_sem_ = xSemaphoreCreateBinary();
     xTaskCreate(&GxEPD2Display::update_task_trampoline_, "gxepd2_update", 4096, this, 1, &this->update_task_);
   }