From c7fdd534bcdee71a448276088a5099d9d2abfcca Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 23 Apr 2026 04:44:05 -0500 Subject: [PATCH] [core] Raise WDT_FEED_INTERVAL_MS to 2000ms on BK72xx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BK72xx silicon requires a ~200us busy-wait (sctrl_dpll_delay200us) between two watchdog register key writes on every reload, making each arch_feed_wdt() call ~300us on BK7231T/N/BK7238. This is hardware errata in the BDK's wdt_ctrl (beken378/driver/wdt/wdt.c:WCMD_RELOAD_PERIOD) and cannot be worked around at the SDK level. LibreTiny initialises the BK72xx HW watchdog at 10000ms, but ESPHome's generic WDT_FEED_INTERVAL_MS of 300ms was sized for ESP8266's 1.6s soft watchdog. That left BK72xx over-servicing the watchdog ~33x per timeout window, paying ~60ms/min of main-loop overhead to no benefit. Raise the interval to 2000ms on BK72xx only, which keeps a 5x safety margin on the 10s HW WDT — matching the ESP8266 ratio that originally motivated the 300ms value — while cutting feed frequency ~6x. Measured on a NiceMCU XH-WB3S (BK7238) while testing libretiny-eu/libretiny#360: Before (300ms interval): wdt_slow_path: hits=195 (5.9% of iters, avg=315.97us/hit) main_loop_before_breakdown: sched=73.2ms, wdt=61.6ms, residual=0.0ms Other platforms retain the existing 300ms value. --- esphome/core/application.h | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/esphome/core/application.h b/esphome/core/application.h index 8280b3bd4b..9dc397f526 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -219,11 +219,22 @@ class Application { /// loops and scheduler items still feed after every op, so any op exceeding /// this threshold triggers a real feed naturally. /// Safety margins vs. platform watchdog timeouts: - /// - ESP32 task WDT default (5 s): ~16x - /// - ESP8266 soft WDT (~1.6 s): ~5x <-- floor case; any future change - /// must keep comfortable margin here - /// - ESP8266 HW WDT (~6 s): ~20x + /// - ESP32 task WDT default (5 s): ~16x + /// - ESP8266 soft WDT (~1.6 s): ~5x <-- floor case; any future change + /// must keep comfortable margin here + /// - ESP8266 HW WDT (~6 s): ~20x + /// - BK72xx HW WDT (10 s): ~5x <-- platform override below +#ifdef USE_BK72XX + /// BK72xx silicon requires a ~200 µs busy-wait between two watchdog register + /// key writes on every reload (sctrl_dpll_delay200us() in BDK wdt.c), making + /// each arch_feed_wdt() ~300 µs. LibreTiny initialises the HW WDT at 10 s, + /// so 2000 ms keeps a 5x safety margin — matching the ESP8266 ratio that + /// motivated the generic 300 ms value — while cutting feed frequency ~6x + /// and recovering ~50 ms/min of main-loop overhead on typical configs. + static constexpr uint32_t WDT_FEED_INTERVAL_MS = 2000; +#else static constexpr uint32_t WDT_FEED_INTERVAL_MS = 300; +#endif /// Feed the task watchdog. Cold entry — callers without a millis() /// timestamp in hand. Out of line to keep call sites tiny.