diff --git a/esphome/core/wake.cpp b/esphome/core/wake.cpp index b95af3734e..0a8e1f870f 100644 --- a/esphome/core/wake.cpp +++ b/esphome/core/wake.cpp @@ -12,11 +12,13 @@ namespace esphome { -// === ESP32 — IRAM_ATTR entry points (fast-select only) === -#if defined(USE_ESP32) && defined(USE_LWIP_FAST_SELECT) +// === ESP32 — IRAM_ATTR entry points === +#ifdef USE_ESP32 +#ifdef USE_LWIP_FAST_SELECT void IRAM_ATTR wake_loop_isrsafe(int *px_higher_priority_task_woken) { wake_loop_isrsafe_inline_(px_higher_priority_task_woken); } +#endif void IRAM_ATTR wake_loop_any_context() { wake_loop_any_context_inline_(); } #endif diff --git a/esphome/core/wake.h b/esphome/core/wake.h index 352c50e45a..7fa5ecb6a6 100644 --- a/esphome/core/wake.h +++ b/esphome/core/wake.h @@ -56,10 +56,21 @@ void wake_loop_any_context(); inline void wake_loop_threadsafe() { esphome_lwip_wake_main_loop(); } #else -inline void wake_loop_any_context() { - if (g_main_task_handle != nullptr) +/// Inline impl — ISR callers inline this into IRAM. Uses xPortInIsrContext() to pick safe API. +inline void ESPHOME_ALWAYS_INLINE wake_loop_any_context_inline_() { + if (g_main_task_handle == nullptr) + return; + if (xPortInIsrContext()) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(g_main_task_handle, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } else { xTaskNotifyGive(g_main_task_handle); + } } +/// IRAM_ATTR entry point — defined in wake.cpp. +void wake_loop_any_context(); + inline void wake_loop_threadsafe() { if (g_main_task_handle != nullptr) xTaskNotifyGive(g_main_task_handle); @@ -69,7 +80,6 @@ inline void wake_loop_threadsafe() { namespace internal { inline void wakeable_delay(uint32_t ms) { #ifndef USE_LWIP_FAST_SELECT - // Cache main task handle on first call if (g_main_task_handle == nullptr) g_main_task_handle = xTaskGetCurrentTaskHandle(); #endif