Merge remote-tracking branch 'upstream/fast-millis-esp32' into integration

This commit is contained in:
J. Nick Koston
2026-04-14 21:26:32 -10:00
3 changed files with 45 additions and 2 deletions
+1 -1
View File
@@ -583,7 +583,7 @@ inline void ESPHOME_ALWAYS_INLINE __attribute__((optimize("O2"))) Application::l
uint64_t loop_recorded_snap = ComponentRuntimeStats::global_recorded_us;
#endif
// Get the initial loop time at the start
uint32_t last_op_end_time = millis();
uint32_t last_op_end_time = MillisInternal::get();
this->before_loop_tasks_(last_op_end_time);
#ifdef USE_RUNTIME_STATS
+2 -1
View File
@@ -9,6 +9,7 @@
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#include "esphome/core/log.h"
#include "esphome/core/millis_internal.h"
#include "esphome/core/optional.h"
// Forward declarations for friend access from codegen-generated setup()
@@ -656,7 +657,7 @@ class WarnIfComponentBlockingGuard {
#ifdef USE_RUNTIME_STATS
this->component_->runtime_stats_.record_time(micros() - this->started_us_);
#endif
uint32_t curr_time = millis();
uint32_t curr_time = MillisInternal::get();
#ifndef USE_BENCHMARK
// Fast path: compare against constant threshold in ms (computed at compile time from centiseconds)
static constexpr uint32_t WARN_IF_BLOCKING_OVER_MS = static_cast<uint32_t>(WARN_IF_BLOCKING_OVER_CS) * 10U;
+42
View File
@@ -0,0 +1,42 @@
#pragma once
#include "esphome/core/hal.h"
#include "esphome/core/helpers.h"
#if defined(USE_ESP32)
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <sdkconfig.h>
#endif
namespace esphome {
// Friend-gated accessor for a fast millis() variant intended only for
// known task-context callers on the main loop hot path (Application::loop()
// and WarnIfComponentBlockingGuard::finish()). It skips the ISR-context
// dispatch that the public esphome::millis() pays on ESP32.
//
// MUST NOT be called from ISR context: on ESP32 it calls the non-FromISR
// FreeRTOS API directly, which is undefined behavior in ISR context.
//
// Adding new callers requires adding a friend declaration here — that
// is the review point. Do not relax the access (e.g. by making get()
// public) without considering the ISR-safety contract.
//
// Other platforms currently delegate to the public millis(); the friend
// gate still enforces the intent so platform-specific fast paths can be
// added later without changing call sites.
class MillisInternal {
private:
static ESPHOME_ALWAYS_INLINE uint32_t get() {
#if defined(USE_ESP32) && CONFIG_FREERTOS_HZ == 1000
return xTaskGetTickCount();
#else
return millis();
#endif
}
friend class Application;
friend class WarnIfComponentBlockingGuard;
};
} // namespace esphome