diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 7b5e1cdba5..6deb3d2341 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -70,15 +70,23 @@ static int64_t alarm_callback(alarm_id_t id, void *user_data) { } void socket_delay(uint32_t ms) { - if (ms == 0) + if (ms == 0) { + yield(); return; + } s_socket_woke = false; s_delay_expired = false; // Set a one-shot timer to wake us after the timeout. // add_alarm_in_ms returns >0 on success, 0 if time already passed, <0 on error. alarm_id_t alarm = add_alarm_in_ms(ms, alarm_callback, nullptr, true); - if (alarm <= 0) - return; // Timer already fired or no alarm slots available + if (alarm <= 0) { + // Fallback: honor the requested delay even if the alarm could not be scheduled. + absolute_time_t deadline = make_timeout_time_ms(ms); + while (!s_socket_woke && !time_reached(deadline)) { + __wfe(); + } + return; + } // Sleep until woken by either the timer alarm or socket_wake(). // __wfe() may return spuriously (stale event register, other interrupts), // so we loop checking both flags. diff --git a/esphome/components/socket/socket.h b/esphome/components/socket/socket.h index 65f1b9a4c3..a21bd64730 100644 --- a/esphome/components/socket/socket.h +++ b/esphome/components/socket/socket.h @@ -124,7 +124,7 @@ size_t format_sockaddr_to(const struct sockaddr *addr_ptr, socklen_t len, std::s /// Delay that can be woken early by socket activity. /// On ESP8266, uses esp_delay() with a callback that checks socket activity. /// On RP2040, uses __wfe() (Wait For Event) to truly sleep until an interrupt -/// (CYW43 GPIO, timer alarm) fires, then processes pending async_context work. +/// (for example, CYW43 GPIO or a timer alarm) fires and wakes the CPU. void socket_delay(uint32_t ms); /// Signal socket/IO activity and wake the main loop early.