From 7e8d3ba13e65a7e62dafbe798697d8f965168edc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 4 Apr 2026 11:08:41 -1000 Subject: [PATCH] Inline RP2040 wakeable_delay using function-local static + lambda callback --- esphome/core/wake.cpp | 40 +--------------------------------------- esphome/core/wake.h | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 41 deletions(-) diff --git a/esphome/core/wake.cpp b/esphome/core/wake.cpp index ef78d01950..a42801e5be 100644 --- a/esphome/core/wake.cpp +++ b/esphome/core/wake.cpp @@ -31,50 +31,12 @@ void IRAM_ATTR wake_loop_any_context() { wake_loop_impl_(); } #endif // USE_ESP8266 -// === RP2040 — wakeable_delay (wake functions are inline in wake.h) === +// === RP2040 — g_main_loop_woke definition (wake functions + wakeable_delay are inline in wake.h) === #ifdef USE_RP2040 // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) volatile bool g_main_loop_woke = false; -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -static volatile bool s_delay_expired = false; - -static int64_t alarm_callback_(alarm_id_t id, void *user_data) { - (void) id; - (void) user_data; - s_delay_expired = true; - __sev(); // Wake from __wfe() — timeout expired. - return 0; // One-shot -} - -namespace internal { -void wakeable_delay(uint32_t ms) { - if (ms == 0) { - yield(); - return; - } - // If a wake was already signalled, consume it and return immediately - if (g_main_loop_woke) { - g_main_loop_woke = false; - return; - } - s_delay_expired = false; - alarm_id_t alarm = add_alarm_in_ms(ms, alarm_callback_, nullptr, true); - if (alarm <= 0) { - delay(ms); - return; - } - // Sleep until woken by either the timer alarm or wake_loop_any_context()/wake_loop_threadsafe() - while (!g_main_loop_woke && !s_delay_expired) { - __wfe(); - } - if (!s_delay_expired) - cancel_alarm(alarm); - g_main_loop_woke = false; -} -} // namespace internal - #endif // USE_RP2040 // === Host (UDP loopback socket) === diff --git a/esphome/core/wake.h b/esphome/core/wake.h index dd2f9ab6b8..3806e2734e 100644 --- a/esphome/core/wake.h +++ b/esphome/core/wake.h @@ -26,6 +26,7 @@ #include #elif defined(USE_RP2040) #include +#include #endif namespace esphome { @@ -111,8 +112,35 @@ inline void wake_loop_threadsafe() { } namespace internal { -/// Delay that can be woken early. Uses hardware timer + __wfe()/__sev(). Defined in wake.cpp. -void wakeable_delay(uint32_t ms); +inline void wakeable_delay(uint32_t ms) { + // Function-local statics — safe because this is only called from the main loop. + static volatile bool s_delay_expired = false; + if (ms == 0) { + yield(); + return; + } + if (g_main_loop_woke) { + g_main_loop_woke = false; + return; + } + s_delay_expired = false; + auto alarm_cb = [](alarm_id_t, void *) -> int64_t { + s_delay_expired = true; + __sev(); + return 0; + }; + alarm_id_t alarm = add_alarm_in_ms(ms, alarm_cb, nullptr, true); + if (alarm <= 0) { + delay(ms); + return; + } + while (!g_main_loop_woke && !s_delay_expired) { + __wfe(); + } + if (!s_delay_expired) + cancel_alarm(alarm); + g_main_loop_woke = false; +} } // namespace internal // === Host (UDP loopback socket) ===