ESPHome 2026.5.1
Loading...
Searching...
No Matches
wake.h
Go to the documentation of this file.
1#pragma once
2
10
12#include "esphome/core/hal.h"
13
14#ifdef ESPHOME_THREAD_MULTI_ATOMICS
15#include <atomic>
16#endif
17
18namespace esphome {
19
20// === Wake flag for ESP8266/RP2040 ===
21#if defined(USE_ESP8266) || defined(USE_RP2040)
22// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
23extern volatile bool g_main_loop_woke;
24#endif
25
26// === wake_request flag — signals Application::loop() that a producer queued
27// work for some component's loop() to drain (MQTT RX, USB RX, BLE event, etc.)
28// and the component phase should run this tick instead of being held off by
29// the loop_interval_ gate. Set by every wake_loop_* entry point; consumed
30// (via exchange-and-clear) at the gate in Application::loop(). ===
31//
32// std::atomic<uint8_t> rather than std::atomic<bool> because GCC on Xtensa
33// generates an indirect function call for atomic<bool> ops instead of inlining
34// them — same workaround applied in scheduler.h for the SchedulerItem::remove
35// flag. On non-atomic platforms a volatile uint8_t suffices: 8-bit aligned
36// loads/stores are atomic on every supported MCU, and the platform signal
37// that follows wake_request_set() (FreeRTOS task-notify, esp_schedule, socket
38// send) provides the cross-thread/cross-core memory barrier.
39#ifdef ESPHOME_THREAD_MULTI_ATOMICS
40// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
41extern std::atomic<uint8_t> g_wake_requested;
42
43__attribute__((always_inline)) inline void wake_request_set() { g_wake_requested.store(1, std::memory_order_release); }
44__attribute__((always_inline)) inline bool wake_request_take() {
45 return g_wake_requested.exchange(0, std::memory_order_acquire) != 0;
46}
47#else
48// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
49extern volatile uint8_t g_wake_requested;
50
51__attribute__((always_inline)) inline void wake_request_set() { g_wake_requested = 1; }
52__attribute__((always_inline)) inline bool wake_request_take() {
53 uint8_t v = g_wake_requested;
55 return v != 0;
56}
57#endif
58
59} // namespace esphome
60
61// Per-platform implementations. Each header re-enters namespace esphome {} and
62// guards its body with the matching USE_* check, so only one contributes code
63// for the active target.
64#if defined(USE_ESP32) || defined(USE_LIBRETINY)
66#elif defined(USE_ESP8266)
68#elif defined(USE_RP2040)
70#elif defined(USE_HOST)
72#elif defined(USE_ZEPHYR)
74#else
75#error "wake.h: wake_loop_threadsafe() is not implemented for this platform"
76#endif
struct @65::@66 __attribute__
Wake the main loop task from an ISR. ISR-safe.
Definition main_task.h:32
std::atomic< uint8_t > g_wake_requested
Definition wake.h:49
volatile bool g_main_loop_woke