From ebbc3b57c779430234f922e2ce135301f37b2815 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 11 Apr 2026 23:34:14 -1000 Subject: [PATCH] [esp8266] Document delay() semantic difference from Arduino Arduino's delay() uses esp_suspend() with a one-shot os_timer for efficient single-suspension waiting. Our replacement polls millis() with optimistic_yield(), which also enters esp_schedule/esp_suspend via yield() but resumes repeatedly. Functionally correct for ESPHome (delay is cold path, SDK tasks run via yield), just less power- efficient for long delays. --- esphome/components/esp8266/core.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index 91854e3877d..c26cddea7eb 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -75,8 +75,14 @@ uint64_t millis_64() { return Millis64Impl::compute(millis()); } // Avoid calling ::delay() which pulls in __delay from core_esp8266_wiring.cpp. // __delay has an intra-object call to the original millis() that --wrap=millis // can't intercept, preventing the linker from garbage-collecting the expensive -// original millis body (~80 bytes IRAM). This yield loop achieves the same -// behavior: feeds the watchdog, processes SDK tasks, keeps WiFi alive. +// original millis body (~80 bytes IRAM). +// +// Semantic difference from Arduino's delay(): Arduino sets up a one-shot +// os_timer and calls esp_suspend() to suspend the continuation once for the +// full duration. Our loop polls millis() + optimistic_yield(1000) which still +// calls esp_schedule()/esp_suspend_within_cont() via yield(), so SDK tasks +// and WiFi run correctly. Less power-efficient for long delays, but ESPHome +// uses delay() only during setup and OTA — never on the hot path. void HOT delay(uint32_t ms) { if (ms == 0) { optimistic_yield(1000);