Inline RP2040 wakeable_delay using function-local static + lambda callback

This commit is contained in:
J. Nick Koston
2026-04-04 11:08:41 -10:00
parent 0bf0fc7eb8
commit 7e8d3ba13e
2 changed files with 31 additions and 41 deletions
+1 -39
View File
@@ -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) ===
+30 -2
View File
@@ -26,6 +26,7 @@
#include <coredecls.h>
#elif defined(USE_RP2040)
#include <hardware/sync.h>
#include <pico/time.h>
#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) ===