mirror of
https://github.com/esphome/esphome.git
synced 2026-05-27 20:53:46 +08:00
[rp2040] Use native time_us_64() for millis_64() (#14356)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,19 +3,19 @@
|
|||||||
#include "core.h"
|
#include "core.h"
|
||||||
#include "esphome/core/defines.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/hal.h"
|
||||||
#include "esphome/core/application.h"
|
|
||||||
#include "esphome/core/helpers.h"
|
#include "esphome/core/helpers.h"
|
||||||
|
|
||||||
|
#include "hardware/timer.h"
|
||||||
#include "hardware/watchdog.h"
|
#include "hardware/watchdog.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
void HOT yield() { ::yield(); }
|
void HOT yield() { ::yield(); }
|
||||||
uint32_t IRAM_ATTR HOT millis() { return ::millis(); }
|
uint64_t millis_64() { return time_us_64() / 1000ULL; }
|
||||||
uint64_t millis_64() { return App.scheduler.millis_64_impl_(::millis()); }
|
uint32_t HOT millis() { return static_cast<uint32_t>(millis_64()); }
|
||||||
void HOT delay(uint32_t ms) { ::delay(ms); }
|
void HOT delay(uint32_t ms) { ::delay(ms); }
|
||||||
uint32_t IRAM_ATTR HOT micros() { return ::micros(); }
|
uint32_t HOT micros() { return ::micros(); }
|
||||||
void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); }
|
void HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); }
|
||||||
void arch_restart() {
|
void arch_restart() {
|
||||||
watchdog_reboot(0, 0, 10);
|
watchdog_reboot(0, 0, 10);
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -34,7 +34,7 @@ void HOT arch_feed_wdt() { watchdog_update(); }
|
|||||||
uint8_t progmem_read_byte(const uint8_t *addr) {
|
uint8_t progmem_read_byte(const uint8_t *addr) {
|
||||||
return pgm_read_byte(addr); // NOLINT
|
return pgm_read_byte(addr); // NOLINT
|
||||||
}
|
}
|
||||||
uint32_t IRAM_ATTR HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); }
|
uint32_t HOT arch_get_cpu_cycle_count() { return ulMainGetRunTimeCounterValue(); }
|
||||||
uint32_t arch_get_cpu_freq_hz() { return RP2040::f_cpu(); }
|
uint32_t arch_get_cpu_freq_hz() { return RP2040::f_cpu(); }
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ static constexpr size_t MAX_POOL_SIZE = 5;
|
|||||||
// Set to 5 to match the pool size - when we have as many cancelled items as our
|
// Set to 5 to match the pool size - when we have as many cancelled items as our
|
||||||
// pool can hold, it's time to clean up and recycle them.
|
// pool can hold, it's time to clean up and recycle them.
|
||||||
static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5;
|
static constexpr uint32_t MAX_LOGICALLY_DELETED_ITEMS = 5;
|
||||||
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR)
|
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040)
|
||||||
// Half the 32-bit range - used to detect rollovers vs normal time progression
|
// Half the 32-bit range - used to detect rollovers vs normal time progression
|
||||||
static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2;
|
static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits<uint32_t>::max() / 2;
|
||||||
#endif
|
#endif
|
||||||
@@ -475,12 +475,13 @@ void HOT Scheduler::call(uint32_t now) {
|
|||||||
if (now_64 - last_print > 2000) {
|
if (now_64 - last_print > 2000) {
|
||||||
last_print = now_64;
|
last_print = now_64;
|
||||||
std::vector<SchedulerItemPtr> old_items;
|
std::vector<SchedulerItemPtr> old_items;
|
||||||
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && defined(ESPHOME_THREAD_MULTI_ATOMICS)
|
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040) && \
|
||||||
|
defined(ESPHOME_THREAD_MULTI_ATOMICS)
|
||||||
const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed);
|
const auto last_dbg = this->last_millis_.load(std::memory_order_relaxed);
|
||||||
const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed);
|
const auto major_dbg = this->millis_major_.load(std::memory_order_relaxed);
|
||||||
ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(),
|
ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(),
|
||||||
this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg);
|
this->scheduler_item_pool_.size(), now_64, major_dbg, last_dbg);
|
||||||
#elif !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR)
|
#elif !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040)
|
||||||
ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(),
|
ESP_LOGD(TAG, "Items: count=%zu, pool=%zu, now=%" PRIu64 " (%" PRIu16 ", %" PRIu32 ")", this->items_.size(),
|
||||||
this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_);
|
this->scheduler_item_pool_.size(), now_64, this->millis_major_, this->last_millis_);
|
||||||
#else
|
#else
|
||||||
@@ -714,7 +715,7 @@ bool HOT Scheduler::cancel_item_locked_(Component *component, NameType name_type
|
|||||||
return total_cancelled > 0;
|
return total_cancelled > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR)
|
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040)
|
||||||
uint64_t Scheduler::millis_64_impl_(uint32_t now) {
|
uint64_t Scheduler::millis_64_impl_(uint32_t now) {
|
||||||
// THREAD SAFETY NOTE:
|
// THREAD SAFETY NOTE:
|
||||||
// This function has three implementations, based on the precompiler flags
|
// This function has three implementations, based on the precompiler flags
|
||||||
@@ -872,7 +873,7 @@ uint64_t Scheduler::millis_64_impl_(uint32_t now) {
|
|||||||
"No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined."
|
"No platform threading model defined. One of ESPHOME_THREAD_SINGLE, ESPHOME_THREAD_MULTI_NO_ATOMICS, or ESPHOME_THREAD_MULTI_ATOMICS must be defined."
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif // !USE_ESP32 && !USE_HOST && !USE_ZEPHYR
|
#endif // !USE_ESP32 && !USE_HOST && !USE_ZEPHYR && !USE_RP2040
|
||||||
|
|
||||||
bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) {
|
bool HOT Scheduler::SchedulerItem::cmp(const SchedulerItemPtr &a, const SchedulerItemPtr &b) {
|
||||||
// High bits are almost always equal (change only on 32-bit rollover ~49 days)
|
// High bits are almost always equal (change only on 32-bit rollover ~49 days)
|
||||||
|
|||||||
@@ -284,10 +284,10 @@ class Scheduler {
|
|||||||
bool cancel_retry_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id);
|
bool cancel_retry_(Component *component, NameType name_type, const char *static_name, uint32_t hash_or_id);
|
||||||
|
|
||||||
// Extend a 32-bit millis() value to 64-bit. Use when the caller already has a fresh now.
|
// Extend a 32-bit millis() value to 64-bit. Use when the caller already has a fresh now.
|
||||||
// On ESP32, ignores now and uses esp_timer_get_time() directly (native 64-bit).
|
// On ESP32, Host, Zephyr, and RP2040, ignores now and uses the native 64-bit time source via millis_64().
|
||||||
// On non-ESP32, extends now to 64-bit using rollover tracking.
|
// On other platforms, extends now to 64-bit using rollover tracking.
|
||||||
uint64_t millis_64_from_(uint32_t now) {
|
uint64_t millis_64_from_(uint32_t now) {
|
||||||
#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_ZEPHYR)
|
#if defined(USE_ESP32) || defined(USE_HOST) || defined(USE_ZEPHYR) || defined(USE_RP2040)
|
||||||
(void) now;
|
(void) now;
|
||||||
return millis_64();
|
return millis_64();
|
||||||
#else
|
#else
|
||||||
@@ -295,7 +295,7 @@ class Scheduler {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR)
|
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040)
|
||||||
// On platforms without native 64-bit time, millis_64() HAL function delegates to this
|
// On platforms without native 64-bit time, millis_64() HAL function delegates to this
|
||||||
// method which tracks 32-bit millis() rollover using millis_major_ and last_millis_.
|
// method which tracks 32-bit millis() rollover using millis_major_ and last_millis_.
|
||||||
friend uint64_t millis_64();
|
friend uint64_t millis_64();
|
||||||
@@ -567,8 +567,8 @@ class Scheduler {
|
|||||||
// to synchronize between tasks (see https://github.com/esphome/backlog/issues/52)
|
// to synchronize between tasks (see https://github.com/esphome/backlog/issues/52)
|
||||||
std::vector<SchedulerItemPtr> scheduler_item_pool_;
|
std::vector<SchedulerItemPtr> scheduler_item_pool_;
|
||||||
|
|
||||||
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR)
|
#if !defined(USE_ESP32) && !defined(USE_HOST) && !defined(USE_ZEPHYR) && !defined(USE_RP2040)
|
||||||
// On platforms with native 64-bit time (ESP32, Host, Zephyr), no rollover tracking needed.
|
// On platforms with native 64-bit time (ESP32, Host, Zephyr, RP2040), no rollover tracking needed.
|
||||||
// On other platforms, these fields track 32-bit millis() rollover for millis_64_impl_().
|
// On other platforms, these fields track 32-bit millis() rollover for millis_64_impl_().
|
||||||
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
#ifdef ESPHOME_THREAD_MULTI_ATOMICS
|
||||||
/*
|
/*
|
||||||
@@ -598,7 +598,7 @@ class Scheduler {
|
|||||||
#else /* not ESPHOME_THREAD_MULTI_ATOMICS */
|
#else /* not ESPHOME_THREAD_MULTI_ATOMICS */
|
||||||
uint16_t millis_major_{0};
|
uint16_t millis_major_{0};
|
||||||
#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */
|
#endif /* else ESPHOME_THREAD_MULTI_ATOMICS */
|
||||||
#endif /* !USE_ESP32 && !USE_HOST && !USE_ZEPHYR */
|
#endif /* !USE_ESP32 && !USE_HOST && !USE_ZEPHYR && !USE_RP2040 */
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|||||||
Reference in New Issue
Block a user