mirror of
https://github.com/esphome/esphome.git
synced 2026-07-10 17:05:36 +00:00
Move task notification helpers to main_task.c/h, deduplicate ESP32/LibreTiny in wake.h
This commit is contained in:
@@ -127,12 +127,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// IRAM_ATTR is defined by esp_attr.h (included via FreeRTOS headers) on ESP32.
|
||||
// On LibreTiny it's not defined — provide a no-op fallback.
|
||||
#ifndef IRAM_ATTR
|
||||
#define IRAM_ATTR
|
||||
#endif
|
||||
|
||||
// Compile-time verification of thread safety assumptions.
|
||||
// On ESP32 (Xtensa/RISC-V) and LibreTiny (ARM Cortex-M), naturally-aligned
|
||||
// reads/writes up to 32 bits are atomic.
|
||||
@@ -230,35 +224,4 @@ bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wake the main loop from another FreeRTOS task. NOT ISR-safe.
|
||||
void esphome_lwip_wake_main_loop(void) {
|
||||
TaskHandle_t task = esphome_main_task_handle;
|
||||
if (task != NULL) {
|
||||
xTaskNotifyGive(task);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake the main loop from an ISR. ISR-safe variant.
|
||||
void IRAM_ATTR esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken) {
|
||||
TaskHandle_t task = esphome_main_task_handle;
|
||||
if (task != NULL) {
|
||||
vTaskNotifyGiveFromISR(task, (BaseType_t *) px_higher_priority_task_woken);
|
||||
}
|
||||
}
|
||||
|
||||
// Wake the main loop from any context (ISR, thread, or main loop).
|
||||
// ESP32-only: uses xPortInIsrContext() to detect ISR context.
|
||||
// LibreTiny is excluded because it lacks IRAM_ATTR support needed for ISR-safe paths.
|
||||
#ifdef USE_ESP32
|
||||
void IRAM_ATTR esphome_lwip_wake_main_loop_any_context(void) {
|
||||
if (xPortInIsrContext()) {
|
||||
int px_higher_priority_task_woken = 0;
|
||||
esphome_lwip_wake_main_loop_from_isr(&px_higher_priority_task_woken);
|
||||
portYIELD_FROM_ISR(px_higher_priority_task_woken);
|
||||
} else {
|
||||
esphome_lwip_wake_main_loop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // USE_LWIP_FAST_SELECT
|
||||
|
||||
@@ -53,15 +53,6 @@ static inline bool esphome_lwip_socket_has_data(struct lwip_sock *sock) {
|
||||
/// The sock pointer must have been obtained from esphome_lwip_get_sock().
|
||||
void esphome_lwip_hook_socket(struct lwip_sock *sock);
|
||||
|
||||
/// Wake the main loop task from another FreeRTOS task — costs <1 us.
|
||||
/// NOT ISR-safe — must only be called from task context.
|
||||
void esphome_lwip_wake_main_loop(void);
|
||||
|
||||
/// Wake the main loop task from an ISR — costs <1 us.
|
||||
/// ISR-safe variant using vTaskNotifyGiveFromISR().
|
||||
/// @param px_higher_priority_task_woken Set to pdTRUE if a context switch is needed.
|
||||
void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken);
|
||||
|
||||
/// Set or clear TCP_NODELAY on a socket's tcp_pcb directly.
|
||||
/// Must be called with the TCPIP core lock held (LwIPLock in C++).
|
||||
/// This bypasses lwip_setsockopt() overhead (socket lookups, switch cascade,
|
||||
@@ -69,13 +60,6 @@ void esphome_lwip_wake_main_loop_from_isr(int *px_higher_priority_task_woken);
|
||||
/// Returns true if successful, false if sock/conn/pcb is NULL or the socket is not TCP.
|
||||
bool esphome_lwip_set_nodelay(struct lwip_sock *sock, bool enable);
|
||||
|
||||
/// Wake the main loop task from any context (ISR, thread, or main loop).
|
||||
/// ESP32-only: uses xPortInIsrContext() to detect ISR context.
|
||||
/// LibreTiny lacks IRAM_ATTR support needed for ISR-safe paths.
|
||||
#ifdef USE_ESP32
|
||||
void esphome_lwip_wake_main_loop_any_context(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,39 @@
|
||||
#include "esphome/core/main_task.h"
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
TaskHandle_t esphome_main_task_handle = NULL;
|
||||
|
||||
// IRAM_ATTR is defined by esp_attr.h (included via FreeRTOS headers) on ESP32.
|
||||
// On LibreTiny it's not reliably available — provide a no-op fallback.
|
||||
#ifndef IRAM_ATTR
|
||||
#define IRAM_ATTR
|
||||
#endif
|
||||
|
||||
TaskHandle_t esphome_main_task_handle = NULL;
|
||||
|
||||
void esphome_main_task_notify(void) {
|
||||
TaskHandle_t task = esphome_main_task_handle;
|
||||
if (task != NULL) {
|
||||
xTaskNotifyGive(task);
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR esphome_main_task_notify_from_isr(int *px_higher_priority_task_woken) {
|
||||
TaskHandle_t task = esphome_main_task_handle;
|
||||
if (task != NULL) {
|
||||
vTaskNotifyGiveFromISR(task, (BaseType_t *) px_higher_priority_task_woken);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32
|
||||
void IRAM_ATTR esphome_main_task_notify_any_context(void) {
|
||||
if (xPortInIsrContext()) {
|
||||
int px_higher_priority_task_woken = 0;
|
||||
esphome_main_task_notify_from_isr(&px_higher_priority_task_woken);
|
||||
portYIELD_FROM_ISR(px_higher_priority_task_woken);
|
||||
} else {
|
||||
esphome_main_task_notify();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // USE_ESP32 || USE_LIBRETINY
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
/// Main loop task handle — shared between wake.h (C++) and lwip_fast_select.c (C).
|
||||
/// Set once during Application::setup() via xTaskGetCurrentTaskHandle().
|
||||
/// Main loop task handle and wake helpers — shared between wake.h (C++) and lwip_fast_select.c (C).
|
||||
/// esphome_main_task_handle is set once during Application::setup() via xTaskGetCurrentTaskHandle().
|
||||
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#elif defined(USE_LIBRETINY)
|
||||
#else
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#endif
|
||||
@@ -17,6 +19,19 @@ extern "C" {
|
||||
|
||||
extern TaskHandle_t esphome_main_task_handle;
|
||||
|
||||
/// Wake the main loop task from another FreeRTOS task. NOT ISR-safe.
|
||||
void esphome_main_task_notify(void);
|
||||
|
||||
/// Wake the main loop task from an ISR. ISR-safe.
|
||||
void esphome_main_task_notify_from_isr(int *px_higher_priority_task_woken);
|
||||
|
||||
#ifdef USE_ESP32
|
||||
/// Wake the main loop from any context (ISR or task). ESP32-only (needs xPortInIsrContext).
|
||||
void esphome_main_task_notify_any_context(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // USE_ESP32 || USE_LIBRETINY
|
||||
|
||||
+11
-43
@@ -25,59 +25,27 @@ namespace esphome {
|
||||
extern volatile bool g_main_loop_woke;
|
||||
#endif
|
||||
|
||||
// === ESP32 ===
|
||||
#if defined(USE_ESP32)
|
||||
// === ESP32 / LibreTiny (FreeRTOS) ===
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
|
||||
#ifdef USE_ESP32
|
||||
/// Inline impl — ISR callers inline this into IRAM.
|
||||
inline void ESPHOME_ALWAYS_INLINE wake_loop_isrsafe_inline_(int *px_higher_priority_task_woken) {
|
||||
if (esphome_main_task_handle != nullptr)
|
||||
vTaskNotifyGiveFromISR(esphome_main_task_handle, (BaseType_t *) px_higher_priority_task_woken);
|
||||
esphome_main_task_notify_from_isr(px_higher_priority_task_woken);
|
||||
}
|
||||
/// IRAM_ATTR entry point — defined in wake.cpp.
|
||||
void wake_loop_isrsafe(int *px_higher_priority_task_woken);
|
||||
|
||||
/// Inline impl — ISR callers inline this into IRAM. Uses xPortInIsrContext() to pick safe API.
|
||||
inline void ESPHOME_ALWAYS_INLINE wake_loop_any_context_inline_() {
|
||||
if (esphome_main_task_handle == nullptr)
|
||||
return;
|
||||
if (xPortInIsrContext()) {
|
||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||
vTaskNotifyGiveFromISR(esphome_main_task_handle, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
} else {
|
||||
xTaskNotifyGive(esphome_main_task_handle);
|
||||
}
|
||||
}
|
||||
/// Inline impl — ISR callers inline this into IRAM.
|
||||
inline void ESPHOME_ALWAYS_INLINE wake_loop_any_context_inline_() { esphome_main_task_notify_any_context(); }
|
||||
/// IRAM_ATTR entry point — defined in wake.cpp.
|
||||
void wake_loop_any_context();
|
||||
#else
|
||||
/// LibreTiny: no working IRAM_ATTR, no ISR callers.
|
||||
inline void wake_loop_any_context() { esphome_main_task_notify(); }
|
||||
#endif
|
||||
|
||||
inline void wake_loop_threadsafe() {
|
||||
if (esphome_main_task_handle != nullptr)
|
||||
xTaskNotifyGive(esphome_main_task_handle);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
inline void wakeable_delay(uint32_t ms) {
|
||||
if (ms == 0) {
|
||||
yield();
|
||||
return;
|
||||
}
|
||||
ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(ms));
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
// === LibreTiny ===
|
||||
#elif defined(USE_LIBRETINY)
|
||||
|
||||
inline void wake_loop_any_context() {
|
||||
if (esphome_main_task_handle != nullptr)
|
||||
xTaskNotifyGive(esphome_main_task_handle);
|
||||
}
|
||||
|
||||
inline void wake_loop_threadsafe() {
|
||||
if (esphome_main_task_handle != nullptr)
|
||||
xTaskNotifyGive(esphome_main_task_handle);
|
||||
}
|
||||
inline void wake_loop_threadsafe() { esphome_main_task_notify(); }
|
||||
|
||||
namespace internal {
|
||||
inline void wakeable_delay(uint32_t ms) {
|
||||
|
||||
Reference in New Issue
Block a user