mirror of
https://github.com/esphome/esphome.git
synced 2026-05-30 23:54:04 +08:00
[libretiny] Inline xTaskGetTickCount() for millis() fast path (#15918)
This commit is contained in:
@@ -16,8 +16,29 @@ void loop();
|
|||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
void HOT yield() { ::yield(); }
|
void HOT yield() { ::yield(); }
|
||||||
|
// Inline the tick read so esphome::millis() matches MillisInternal::get()'s fast
|
||||||
|
// path instead of going through the Arduino core's out-of-line ::millis() wrapper.
|
||||||
|
//
|
||||||
|
// RTL87xx / LN882x (1 kHz): xTaskGetTickCount() is already ms. IRAM_ATTR + ISR
|
||||||
|
// dispatch are needed because ISR handlers (e.g. rotary_encoder) call millis().
|
||||||
|
//
|
||||||
|
// BK72xx (500 Hz): ticks * portTICK_PERIOD_MS (== 2). IRAM_ATTR and ISR dispatch
|
||||||
|
// are both unnecessary — the SDK masks FIQ + IRQ during flash writes (see hal.h),
|
||||||
|
// so no ISR runs while flash is stalled.
|
||||||
|
#if defined(USE_RTL87XX) || defined(USE_LN882X)
|
||||||
|
uint32_t IRAM_ATTR HOT millis() {
|
||||||
|
static_assert(configTICK_RATE_HZ == 1000, "millis() fast path requires 1 kHz FreeRTOS tick");
|
||||||
|
return in_isr_context() ? xTaskGetTickCountFromISR() : xTaskGetTickCount();
|
||||||
|
}
|
||||||
|
#elif defined(USE_BK72XX)
|
||||||
|
uint32_t HOT millis() {
|
||||||
|
static_assert(configTICK_RATE_HZ == 500, "BK72xx millis() fast path assumes 500 Hz FreeRTOS tick");
|
||||||
|
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||||
|
}
|
||||||
|
#else
|
||||||
uint32_t IRAM_ATTR HOT millis() { return ::millis(); }
|
uint32_t IRAM_ATTR HOT millis() { return ::millis(); }
|
||||||
uint64_t millis_64() { return Millis64Impl::compute(::millis()); }
|
#endif
|
||||||
|
uint64_t millis_64() { return Millis64Impl::compute(millis()); }
|
||||||
uint32_t IRAM_ATTR HOT micros() { return ::micros(); }
|
uint32_t IRAM_ATTR HOT micros() { return ::micros(); }
|
||||||
void HOT delay(uint32_t ms) { ::delay(ms); }
|
void HOT delay(uint32_t ms) { ::delay(ms); }
|
||||||
void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); }
|
void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); }
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include <sdkconfig.h>
|
#include <sdkconfig.h>
|
||||||
|
#elif defined(USE_LIBRETINY)
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
@@ -14,10 +17,11 @@ namespace esphome {
|
|||||||
// Friend-gated accessor for a fast millis() variant intended only for
|
// Friend-gated accessor for a fast millis() variant intended only for
|
||||||
// known task-context callers on the main loop hot path (Application::loop()
|
// known task-context callers on the main loop hot path (Application::loop()
|
||||||
// and WarnIfComponentBlockingGuard::finish()). It skips the ISR-context
|
// and WarnIfComponentBlockingGuard::finish()). It skips the ISR-context
|
||||||
// dispatch that the public esphome::millis() pays on ESP32.
|
// dispatch that the public esphome::millis() pays on ESP32 and libretiny.
|
||||||
//
|
//
|
||||||
// MUST NOT be called from ISR context: on ESP32 it calls the non-FromISR
|
// MUST NOT be called from ISR context: on ESP32 and libretiny it calls the
|
||||||
// FreeRTOS API directly, which is undefined behavior in ISR context.
|
// non-FromISR FreeRTOS API directly, which is undefined behavior in ISR
|
||||||
|
// context.
|
||||||
//
|
//
|
||||||
// Adding new callers requires adding a friend declaration here — that
|
// Adding new callers requires adding a friend declaration here — that
|
||||||
// is the review point. Do not relax the access (e.g. by making get()
|
// is the review point. Do not relax the access (e.g. by making get()
|
||||||
@@ -31,6 +35,16 @@ class MillisInternal {
|
|||||||
static ESPHOME_ALWAYS_INLINE uint32_t get() {
|
static ESPHOME_ALWAYS_INLINE uint32_t get() {
|
||||||
#if defined(USE_ESP32) && CONFIG_FREERTOS_HZ == 1000
|
#if defined(USE_ESP32) && CONFIG_FREERTOS_HZ == 1000
|
||||||
return xTaskGetTickCount();
|
return xTaskGetTickCount();
|
||||||
|
#elif defined(USE_LIBRETINY) && (defined(USE_RTL87XX) || defined(USE_LN882X))
|
||||||
|
// 1 kHz: xTaskGetTickCount() is already ms.
|
||||||
|
static_assert(configTICK_RATE_HZ == 1000, "MillisInternal fast path requires 1 kHz FreeRTOS tick");
|
||||||
|
return xTaskGetTickCount();
|
||||||
|
#elif defined(USE_BK72XX)
|
||||||
|
// 500 Hz: scale by portTICK_PERIOD_MS (== 2). Inlined to avoid the
|
||||||
|
// out-of-line call to esphome::millis() (IRAM_ATTR is a no-op on BK72xx —
|
||||||
|
// SDK masks FIQ + IRQ during flash writes, see hal.h).
|
||||||
|
static_assert(configTICK_RATE_HZ == 500, "BK72xx MillisInternal assumes 500 Hz FreeRTOS tick");
|
||||||
|
return xTaskGetTickCount() * portTICK_PERIOD_MS;
|
||||||
#else
|
#else
|
||||||
return millis();
|
return millis();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user