From 36d2b78c18119a95d582eb8b3a20cf61b218ec3b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 4 Apr 2026 11:34:10 -1000 Subject: [PATCH] Unify ESP32/LibreTiny wake: always use g_main_task_handle, remove lwip_fast_select dependency --- esphome/core/application.cpp | 8 +++++--- esphome/core/wake.cpp | 14 ++++++-------- esphome/core/wake.h | 33 ++++++--------------------------- 3 files changed, 17 insertions(+), 38 deletions(-) diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index c389f1c342..1d01d6ff0b 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -114,10 +114,12 @@ void Application::setup() { clear_setup_priority_overrides(); #endif +#if defined(USE_ESP32) || defined(USE_LIBRETINY) + // Save main loop task handle for wake_loop_*() FreeRTOS notifications. + g_main_task_handle = xTaskGetCurrentTaskHandle(); +#endif #ifdef USE_LWIP_FAST_SELECT - // Initialize fast select: saves main loop task handle for xTaskNotifyGive wake. - // The fast path (rcvevent reads + ulTaskNotifyTake) is used unconditionally - // when USE_LWIP_FAST_SELECT is enabled (ESP32 and LibreTiny). + // Initialize fast select: hooks socket monitoring for direct rcvevent reads. esphome_lwip_fast_select_init(); #endif #ifdef USE_HOST diff --git a/esphome/core/wake.cpp b/esphome/core/wake.cpp index 0a8e1f870f..18fbbfd4f4 100644 --- a/esphome/core/wake.cpp +++ b/esphome/core/wake.cpp @@ -12,22 +12,20 @@ namespace esphome { +// === ESP32/LibreTiny — FreeRTOS task handle === +#if defined(USE_ESP32) || defined(USE_LIBRETINY) +// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) +TaskHandle_t g_main_task_handle = nullptr; +#endif + // === 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 -// === FreeRTOS task handle for non-fast-select ESP32/LibreTiny === -#if (defined(USE_ESP32) || defined(USE_LIBRETINY)) && !defined(USE_LWIP_FAST_SELECT) -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -TaskHandle_t g_main_task_handle = nullptr; -#endif - // === ESP8266 / RP2040 === #if defined(USE_ESP8266) || defined(USE_RP2040) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) diff --git a/esphome/core/wake.h b/esphome/core/wake.h index 7fa5ecb6a6..6c3343e135 100644 --- a/esphome/core/wake.h +++ b/esphome/core/wake.h @@ -7,9 +7,6 @@ #include "esphome/core/defines.h" #include "esphome/core/hal.h" -#ifdef USE_LWIP_FAST_SELECT -#include "esphome/core/lwip_fast_select.h" -#endif #if defined(USE_ESP32) || defined(USE_LIBRETINY) #ifdef USE_ESP32 #include @@ -34,8 +31,8 @@ namespace esphome { extern volatile bool g_main_loop_woke; #endif -// === ESP32/LibreTiny — FreeRTOS task handle for non-fast-select path === -#if (defined(USE_ESP32) || defined(USE_LIBRETINY)) && !defined(USE_LWIP_FAST_SELECT) +// === ESP32/LibreTiny — FreeRTOS task handle for wake notifications === +#if defined(USE_ESP32) || defined(USE_LIBRETINY) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) extern TaskHandle_t g_main_task_handle; #endif @@ -43,19 +40,14 @@ extern TaskHandle_t g_main_task_handle; // === ESP32 === #if defined(USE_ESP32) -#ifdef USE_LWIP_FAST_SELECT +/// Inline impl — ISR callers inline this into IRAM. inline void ESPHOME_ALWAYS_INLINE wake_loop_isrsafe_inline_(int *px_higher_priority_task_woken) { - esphome_lwip_wake_main_loop_from_isr(px_higher_priority_task_woken); + if (g_main_task_handle != nullptr) + vTaskNotifyGiveFromISR(g_main_task_handle, (BaseType_t *) px_higher_priority_task_woken); } /// IRAM_ATTR entry point — defined in wake.cpp. void wake_loop_isrsafe(int *px_higher_priority_task_woken); -inline void ESPHOME_ALWAYS_INLINE wake_loop_any_context_inline_() { esphome_lwip_wake_main_loop_any_context(); } -/// IRAM_ATTR entry point — defined in wake.cpp. -void wake_loop_any_context(); - -inline void wake_loop_threadsafe() { esphome_lwip_wake_main_loop(); } -#else /// 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) @@ -75,14 +67,9 @@ inline void wake_loop_threadsafe() { if (g_main_task_handle != nullptr) xTaskNotifyGive(g_main_task_handle); } -#endif namespace internal { inline void wakeable_delay(uint32_t ms) { -#ifndef USE_LWIP_FAST_SELECT - if (g_main_task_handle == nullptr) - g_main_task_handle = xTaskGetCurrentTaskHandle(); -#endif if (ms == 0) { yield(); return; @@ -94,26 +81,18 @@ inline void wakeable_delay(uint32_t ms) { // === LibreTiny === #elif defined(USE_LIBRETINY) -#ifdef USE_LWIP_FAST_SELECT -inline void wake_loop_any_context() { esphome_lwip_wake_main_loop(); } -inline void wake_loop_threadsafe() { esphome_lwip_wake_main_loop(); } -#else inline void wake_loop_any_context() { if (g_main_task_handle != nullptr) xTaskNotifyGive(g_main_task_handle); } + inline void wake_loop_threadsafe() { if (g_main_task_handle != nullptr) xTaskNotifyGive(g_main_task_handle); } -#endif namespace internal { inline void wakeable_delay(uint32_t ms) { -#ifndef USE_LWIP_FAST_SELECT - if (g_main_task_handle == nullptr) - g_main_task_handle = xTaskGetCurrentTaskHandle(); -#endif if (ms == 0) { yield(); return;