diff --git a/esphome/core/lwip_fast_select.c b/esphome/core/lwip_fast_select.c index 82b68aa738b..bb3acbafcb1 100644 --- a/esphome/core/lwip_fast_select.c +++ b/esphome/core/lwip_fast_select.c @@ -63,12 +63,12 @@ // // Shared state and safety rationale: // -// esphome_main_task_handle (TaskHandle_t, 4 bytes): -// Written once by main loop in init(). Read by TCP/IP thread (in callback) -// and background tasks (in wake). -// Safe: write-once-then-read pattern. Socket hooks may run before init(), +// esphome_main_task_handle (TaskHandle_t, 4 bytes, defined in main_task.c): +// Written once by main loop in Application::setup(). Read by TCP/IP thread +// (in callback) and background tasks (in wake). +// Safe: write-once-then-read pattern. Socket hooks may run before setup(), // but the NULL check on esphome_main_task_handle in the callback provides correct -// degraded behavior — notifications are simply skipped until init() completes. +// degraded behavior — notifications are simply skipped until setup() completes. // // s_original_callback (netconn_callback, 4-byte function pointer): // Written by main loop in hook_socket() (only when NULL — set once). diff --git a/esphome/core/wake.h b/esphome/core/wake.h index 7f4fcd60da7..bed1d64561d 100644 --- a/esphome/core/wake.h +++ b/esphome/core/wake.h @@ -34,8 +34,15 @@ void wake_loop_isrsafe(int *px_higher_priority_task_woken); /// IRAM_ATTR entry point — defined in wake.cpp. void wake_loop_any_context(); #else -/// LibreTiny: no working IRAM_ATTR, no ISR callers. -inline void wake_loop_any_context() { esphome_main_task_notify(); } +/// LibreTiny: GPIO ISRs are real hardware interrupts, so use ISR-safe API. +/// vTaskNotifyGiveFromISR is safe from both ISR and task context on ARM Cortex-M. +inline void wake_loop_any_context() { + if (esphome_main_task_handle != NULL) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + vTaskNotifyGiveFromISR(esphome_main_task_handle, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); + } +} #endif inline void wake_loop_threadsafe() { esphome_main_task_notify(); }