110#ifdef USE_LWIP_FAST_SELECT
114#include <lwip/priv/sockets_priv.h>
117#include <freertos/FreeRTOS.h>
118#include <freertos/task.h>
140_Static_assert(
sizeof(TaskHandle_t) <= 4,
"TaskHandle_t must be <= 4 bytes for atomic access");
141_Static_assert(
sizeof(netconn_callback) <= 4,
"netconn_callback must be <= 4 bytes for atomic access");
144_Static_assert(
sizeof(((
struct lwip_sock *) 0)->rcvevent) <= 4,
"rcvevent must be <= 4 bytes for atomic access");
148_Static_assert(offsetof(
struct netconn, callback) %
sizeof(netconn_callback) == 0,
149 "netconn.callback must be naturally aligned for atomic access");
150_Static_assert(offsetof(
struct lwip_sock, rcvevent) %
sizeof(((
struct lwip_sock *) 0)->rcvevent) == 0,
151 "lwip_sock.rcvevent must be naturally aligned for atomic access");
154static TaskHandle_t s_main_loop_task = NULL;
157static netconn_callback s_original_callback = NULL;
161static void esphome_socket_event_callback(
struct netconn *conn,
enum netconn_evt evt, u16_t
len) {
166 s_original_callback(conn, evt,
len);
172 if (evt == NETCONN_EVT_RCVPLUS) {
173 TaskHandle_t task = s_main_loop_task;
175 xTaskNotifyGive(task);
190static inline struct lwip_sock *get_sock(
int fd) {
191 struct lwip_sock *sock = lwip_socket_dbg_get_socket(fd);
192 if (sock == NULL || sock->conn == NULL)
198 struct lwip_sock *sock = get_sock(fd);
206 return *(
volatile s16_t *) &sock->rcvevent > 0;
210 struct lwip_sock *sock = get_sock(fd);
216 if (s_original_callback == NULL) {
217 s_original_callback = sock->conn->callback;
222 sock->conn->callback = esphome_socket_event_callback;
227 TaskHandle_t task = s_main_loop_task;
229 xTaskNotifyGive(task);
235 TaskHandle_t task = s_main_loop_task;
237 vTaskNotifyGiveFromISR(task, (BaseType_t *) px_higher_priority_task_woken);
246 if (xPortInIsrContext()) {
247 int px_higher_priority_task_woken = 0;
249 portYIELD_FROM_ISR(px_higher_priority_task_woken);
void IRAM_ATTR esphome_lwip_wake_main_loop_any_context(void)
Wake the main loop task from any context (ISR, thread, or main loop).
void esphome_lwip_fast_select_init(void)
Initialize fast select — must be called from the main loop task during setup().
bool esphome_lwip_socket_has_data(int fd)
Check if a LwIP socket has data ready via direct rcvevent read (~215 ns per socket).
void IRAM_ATTR esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken)
Wake the main loop task from an ISR — costs <1 us.
void esphome_lwip_hook_socket(int fd)
Hook a socket's netconn callback to notify the main loop task on receive events.
void esphome_lwip_wake_main_loop(void)
Wake the main loop task from another FreeRTOS task — costs <1 us.