Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.
Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
LibreTiny lacks IRAM_ATTR support needed for ISR-safe paths,
and BK72xx doesn't support the mrs ipsr instruction in Thumb mode.
The existing fast select functionality on LibreTiny is unaffected.
Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.
Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.
Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
LibreTiny's FreeRTOS port does not provide portYIELD_FROM_ISR.
On ARM Cortex-M, FreeRTOS internally sets the PendSV bit when
vTaskNotifyGiveFromISR wakes a higher-priority task, so the
context switch happens automatically when the ISR returns.
Wire Application::wake_loop_any_context() to socket::socket_wake()
on ESP8266. This allows any component calling wake_loop_any_context()
from an ISR or callback to immediately wake the main loop from
esp_delay() sleep, instead of waiting up to 16ms for the timeout.
Changes:
- Add IRAM_ATTR to socket_wake() so it's safe to call from ISR context
- Add ESP8266 wake_loop_any_context() backed by socket::socket_wake()
- Extend enable_loop_soon_any_context() to wake the loop on ESP8266
Now that the ISR callback mechanism (from #14382) costs essentially
zero — just a function pointer registration, no task or queue — enable
wake-on-RX by default for all ESP32 UART instances.
This reduces RX buffer overflow risk by waking the main loop
immediately when data arrives instead of waiting for the ~16ms
select timeout.
Remove the opt-in request_wake_loop_on_rx() API since all ESP32
UART instances now get this automatically.
The fast select code paths and wake_loop_any_context() require
USE_SOCKET_SELECT_SUPPORT. Gate USE_LWIP_FAST_SELECT on not using
lwip_tcp implementation which does not provide select() support.
- Update ISR safety comment: point 3 now reflects that
wake_loop_any_context() is called (ISR-safe)
- Initialize ipsr = 0 as safety net before inline asm
- Update ISR safety comment: point 3 now reflects that
wake_loop_any_context() is called (ISR-safe)
- Initialize ipsr = 0 as safety net before inline asm
- Replace __get_IPSR() with inline asm to avoid CMSIS header dependency
on LibreTiny chip families that may not declare it (e.g. beken-72xx)
- Pass local variable to wake_from_isr and call portYIELD_FROM_ISR for
immediate context switch instead of passing NULL
- Update comment in component.cpp to mention both ESP32 and LibreTiny
platform-specific context detection
- Switch USE_LWIP_FAST_SELECT from cg.add_define to cg.add_build_flag
so it is visible in .c translation units, aligning guards across all
source files
Replace acosf(y/distance) + sign flip with atan2f(-x, y) which
computes the angle from the Y axis directly. This eliminates the
division by distance, the acosf call, the sign branch, and the
calculate_angle helper function entirely.
atan2f also handles all quadrants correctly by definition, avoiding
the edge-case guard that silently returned 0 when y was negative.
Merge the two separate count_targets_in_zone_ calls (one for still,
one for moving) into a single pass that counts both simultaneously.
This halves the number of iterations through the target list per zone
(from 6 calls to 3 for 3 zones).
Replace per-frame string comparison with Deduplicator<uint8_t> on
the direction enum value. The previous code called get_state() and
compared std::string against const char* on every frame for each
target (~75 times/sec). The new approach does a single uint8_t
comparison and only looks up the direction string and publishes
when the direction actually changes.
Also use MAX_TARGETS instead of hardcoded 3 for direction_text_sensors_
array size for consistency with all other sensor arrays.
The check-and-set pattern for status LED flags was duplicated across
all status_set_warning and status_set_error overloads. Extract a
set_status_flag_ helper that sets the flag on both the component
and the app, returning whether the flag was newly set.
Co-Authored-By: J. Nick Koston <nick@koston.org>
enable_loop_soon_any_context() sets volatile flags but does not wake
the main loop from ulTaskNotifyTake() sleep. This means components
using ISR-driven state changes (e.g. GPIO binary sensors) wait up
to ~16ms for the select timeout before their loop runs.
Add wake_loop_any_context() that detects the calling context (ISR vs
task) using xPortInIsrContext() (ESP32) or __get_IPSR() (LibreTiny)
and calls the appropriate FreeRTOS API. This is safe from ISR, thread,
and main loop contexts.
Also relax the wake_loop_isrsafe() guard from requiring both
USE_WAKE_LOOP_THREADSAFE and USE_LWIP_FAST_SELECT to just
USE_LWIP_FAST_SELECT, since the ISR wake path uses
vTaskNotifyGiveFromISR directly and does not depend on the
UDP socket mechanism.
IRAM_ATTR is defined by esp_attr.h on ESP32 but not on LibreTiny.
Add a no-op fallback in the C file since hal.h (which defines it
for C++) cannot be included from C.