diff --git a/esphome/core/application.cpp b/esphome/core/application.cpp index 8373c672ed..9b7091f59a 100644 --- a/esphome/core/application.cpp +++ b/esphome/core/application.cpp @@ -453,7 +453,7 @@ void Application::enable_pending_loops_() { // Called from the LwIP TCP/IP task via esphome_socket_event_callback() on NETCONN_EVT_RCVPLUS. // Only marks the OTA component as pending loop-enable; the fast-select callback itself has // already woken the main task via xTaskNotifyGive(). -extern "C" void IRAM_ATTR esphome_wake_ota_component_any_context() { App.wake_ota_component_any_context(); } +extern "C" void esphome_wake_ota_component_any_context() { App.wake_ota_component_any_context(); } #endif #ifdef USE_LWIP_FAST_SELECT diff --git a/esphome/core/application.h b/esphome/core/application.h index 100ff3440d..67ef1d666f 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -564,13 +564,14 @@ class Application { /// a new connection arrives on the listening socket. OTA disables its own /// loop while idle to avoid per-tick dispatch overhead. void set_ota_wake_component(Component *component) { this->ota_wake_component_ = component; } - /// Mark the registered OTA component (if any) for loop re-enable from any - /// context. Intentionally does NOT call wake_loop_any_context() — every - /// caller (lwip fast-select callback, raw-tcp accept callback, host - /// select() return path) has already woken the main loop, so a second wake - /// here would be redundant. Application is a friend of Component, so we - /// set the pending-enable flags directly. - void IRAM_ATTR wake_ota_component_any_context() { + /// Mark the registered OTA component (if any) for loop re-enable. Intentionally + /// does NOT call wake_loop_any_context() — every caller (lwip fast-select + /// callback, raw-tcp accept callback, host select() return path) has already + /// woken the main loop, so a second wake here would be redundant. Application + /// is a friend of Component, so we set the pending-enable flags directly. + /// Not IRAM_ATTR: all callers run in task / user-IRQ context, not a real ISR, + /// and the LwIP event callbacks that invoke this are not IRAM-resident either. + void wake_ota_component_any_context() { if (this->ota_wake_component_ != nullptr) { this->ota_wake_component_->pending_enable_loop_ = true; this->has_pending_enable_loop_requests_ = true;