mirror of
https://github.com/esphome/esphome.git
synced 2025-07-27 13:46:48 +00:00
[core] Process pending loop enables during setup blocking phase (#9787)
This commit is contained in:
parent
f8777d3b66
commit
fc8c5a7438
@ -68,8 +68,11 @@ void Application::setup() {
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
uint8_t new_app_state = STATUS_LED_WARNING;
|
uint8_t new_app_state = STATUS_LED_WARNING;
|
||||||
this->scheduler.call();
|
uint32_t now = millis();
|
||||||
this->feed_wdt();
|
|
||||||
|
// Process pending loop enables to handle GPIO interrupts during setup
|
||||||
|
this->before_loop_tasks_(now);
|
||||||
|
|
||||||
for (uint32_t j = 0; j <= i; j++) {
|
for (uint32_t j = 0; j <= i; j++) {
|
||||||
// Update loop_component_start_time_ right before calling each component
|
// Update loop_component_start_time_ right before calling each component
|
||||||
this->loop_component_start_time_ = millis();
|
this->loop_component_start_time_ = millis();
|
||||||
@ -78,6 +81,8 @@ void Application::setup() {
|
|||||||
this->app_state_ |= new_app_state;
|
this->app_state_ |= new_app_state;
|
||||||
this->feed_wdt();
|
this->feed_wdt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->after_loop_tasks_();
|
||||||
this->app_state_ = new_app_state;
|
this->app_state_ = new_app_state;
|
||||||
yield();
|
yield();
|
||||||
} while (!component->can_proceed());
|
} while (!component->can_proceed());
|
||||||
@ -94,30 +99,10 @@ void Application::setup() {
|
|||||||
void Application::loop() {
|
void Application::loop() {
|
||||||
uint8_t new_app_state = 0;
|
uint8_t new_app_state = 0;
|
||||||
|
|
||||||
this->scheduler.call();
|
|
||||||
|
|
||||||
// Get the initial loop time at the start
|
// Get the initial loop time at the start
|
||||||
uint32_t last_op_end_time = millis();
|
uint32_t last_op_end_time = millis();
|
||||||
|
|
||||||
// Feed WDT with time
|
this->before_loop_tasks_(last_op_end_time);
|
||||||
this->feed_wdt(last_op_end_time);
|
|
||||||
|
|
||||||
// Process any pending enable_loop requests from ISRs
|
|
||||||
// This must be done before marking in_loop_ = true to avoid race conditions
|
|
||||||
if (this->has_pending_enable_loop_requests_) {
|
|
||||||
// Clear flag BEFORE processing to avoid race condition
|
|
||||||
// If ISR sets it during processing, we'll catch it next loop iteration
|
|
||||||
// This is safe because:
|
|
||||||
// 1. Each component has its own pending_enable_loop_ flag that we check
|
|
||||||
// 2. If we can't process a component (wrong state), enable_pending_loops_()
|
|
||||||
// will set this flag back to true
|
|
||||||
// 3. Any new ISR requests during processing will set the flag again
|
|
||||||
this->has_pending_enable_loop_requests_ = false;
|
|
||||||
this->enable_pending_loops_();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark that we're in the loop for safe reentrant modifications
|
|
||||||
this->in_loop_ = true;
|
|
||||||
|
|
||||||
for (this->current_loop_index_ = 0; this->current_loop_index_ < this->looping_components_active_end_;
|
for (this->current_loop_index_ = 0; this->current_loop_index_ < this->looping_components_active_end_;
|
||||||
this->current_loop_index_++) {
|
this->current_loop_index_++) {
|
||||||
@ -138,7 +123,7 @@ void Application::loop() {
|
|||||||
this->feed_wdt(last_op_end_time);
|
this->feed_wdt(last_op_end_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->in_loop_ = false;
|
this->after_loop_tasks_();
|
||||||
this->app_state_ = new_app_state;
|
this->app_state_ = new_app_state;
|
||||||
|
|
||||||
// Use the last component's end time instead of calling millis() again
|
// Use the last component's end time instead of calling millis() again
|
||||||
@ -400,6 +385,36 @@ void Application::enable_pending_loops_() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::before_loop_tasks_(uint32_t loop_start_time) {
|
||||||
|
// Process scheduled tasks
|
||||||
|
this->scheduler.call();
|
||||||
|
|
||||||
|
// Feed the watchdog timer
|
||||||
|
this->feed_wdt(loop_start_time);
|
||||||
|
|
||||||
|
// Process any pending enable_loop requests from ISRs
|
||||||
|
// This must be done before marking in_loop_ = true to avoid race conditions
|
||||||
|
if (this->has_pending_enable_loop_requests_) {
|
||||||
|
// Clear flag BEFORE processing to avoid race condition
|
||||||
|
// If ISR sets it during processing, we'll catch it next loop iteration
|
||||||
|
// This is safe because:
|
||||||
|
// 1. Each component has its own pending_enable_loop_ flag that we check
|
||||||
|
// 2. If we can't process a component (wrong state), enable_pending_loops_()
|
||||||
|
// will set this flag back to true
|
||||||
|
// 3. Any new ISR requests during processing will set the flag again
|
||||||
|
this->has_pending_enable_loop_requests_ = false;
|
||||||
|
this->enable_pending_loops_();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark that we're in the loop for safe reentrant modifications
|
||||||
|
this->in_loop_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::after_loop_tasks_() {
|
||||||
|
// Clear the in_loop_ flag to indicate we're done processing components
|
||||||
|
this->in_loop_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_SOCKET_SELECT_SUPPORT
|
#ifdef USE_SOCKET_SELECT_SUPPORT
|
||||||
bool Application::register_socket_fd(int fd) {
|
bool Application::register_socket_fd(int fd) {
|
||||||
// WARNING: This function is NOT thread-safe and must only be called from the main loop
|
// WARNING: This function is NOT thread-safe and must only be called from the main loop
|
||||||
|
@ -504,6 +504,8 @@ class Application {
|
|||||||
void enable_component_loop_(Component *component);
|
void enable_component_loop_(Component *component);
|
||||||
void enable_pending_loops_();
|
void enable_pending_loops_();
|
||||||
void activate_looping_component_(uint16_t index);
|
void activate_looping_component_(uint16_t index);
|
||||||
|
void before_loop_tasks_(uint32_t loop_start_time);
|
||||||
|
void after_loop_tasks_();
|
||||||
|
|
||||||
void feed_wdt_arch_();
|
void feed_wdt_arch_();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user