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.
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.
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
- 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
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.
Use the ESP-IDF UART driver's uart_set_select_notif_callback() to wake
the main loop directly from the UART ISR via vTaskNotifyGiveFromISR(),
eliminating the FreeRTOS trampoline task and event queue that were
previously needed when wake_loop_threadsafe() used a UDP loopback socket.
With fast lwip select, the main loop sleeps on ulTaskNotifyTake(), so
the ISR-safe vTaskNotifyGiveFromISR() can wake it directly.
Saves ~2.6KB RAM per UART instance with wake-on-RX enabled:
- 2,240 bytes FreeRTOS task stack
- ~340 bytes event queue (20 entries + control block)
- 8 bytes QueueHandle_t + TaskHandle_t fields
Also adds Application::wake_loop_isrsafe() as the ISR-safe counterpart
to wake_loop_threadsafe(), backed by esphome_lwip_wake_main_loop_from_isr().