mirror of
https://github.com/esphome/esphome.git
synced 2026-05-28 13:37:24 +08:00
Merge remote-tracking branch 'upstream/followup/hal-esp32' into integration
This commit is contained in:
@@ -1,17 +1,8 @@
|
|||||||
#ifdef USE_ESP32
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
#include "esphome/core/defines.h"
|
|
||||||
#include "crash_handler.h"
|
|
||||||
#include "esphome/core/application.h"
|
#include "esphome/core/application.h"
|
||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/defines.h"
|
||||||
#include "esphome/core/helpers.h"
|
|
||||||
#include "preferences.h"
|
#include "preferences.h"
|
||||||
#include <esp_clk_tree.h>
|
|
||||||
#include <esp_cpu.h>
|
|
||||||
#include <esp_idf_version.h>
|
|
||||||
#include <esp_ota_ops.h>
|
|
||||||
#include <esp_task_wdt.h>
|
|
||||||
#include <esp_timer.h>
|
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
|
|
||||||
@@ -22,54 +13,7 @@ extern "C" __attribute__((weak)) void initArduino() {}
|
|||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
// yield(), delay(), micros(), millis_64() inlined in hal.h.
|
// HAL functions live in hal.cpp. This file keeps only the loop task setup.
|
||||||
// Use xTaskGetTickCount() when tick rate is 1 kHz (ESPHome's default via sdkconfig),
|
|
||||||
// falling back to esp_timer for non-standard rates. IRAM_ATTR is required because
|
|
||||||
// Wiegand and ZyAura call millis() from IRAM_ATTR ISR handlers on ESP32.
|
|
||||||
// xTaskGetTickCountFromISR() is used in ISR context to satisfy the FreeRTOS API contract.
|
|
||||||
uint32_t IRAM_ATTR HOT millis() {
|
|
||||||
#if CONFIG_FREERTOS_HZ == 1000
|
|
||||||
if (xPortInIsrContext()) [[unlikely]] {
|
|
||||||
return xTaskGetTickCountFromISR();
|
|
||||||
}
|
|
||||||
return xTaskGetTickCount();
|
|
||||||
#else
|
|
||||||
return micros_to_millis(static_cast<uint64_t>(esp_timer_get_time()));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); }
|
|
||||||
void arch_restart() {
|
|
||||||
esp_restart();
|
|
||||||
// restart() doesn't always end execution
|
|
||||||
while (true) { // NOLINT(clang-diagnostic-unreachable-code)
|
|
||||||
yield();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void arch_init() {
|
|
||||||
#ifdef USE_ESP32_CRASH_HANDLER
|
|
||||||
// Read crash data from previous boot before anything else
|
|
||||||
esp32::crash_handler_read_and_clear();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Enable the task watchdog only on the loop task (from which we're currently running)
|
|
||||||
esp_task_wdt_add(nullptr);
|
|
||||||
|
|
||||||
// Handle OTA rollback: mark partition valid immediately unless USE_OTA_ROLLBACK is enabled,
|
|
||||||
// in which case safe_mode will mark it valid after confirming successful boot.
|
|
||||||
#ifndef USE_OTA_ROLLBACK
|
|
||||||
esp_ota_mark_app_valid_cancel_rollback();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
void HOT arch_feed_wdt() { esp_task_wdt_reset(); }
|
|
||||||
|
|
||||||
uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); }
|
|
||||||
uint32_t arch_get_cpu_freq_hz() {
|
|
||||||
uint32_t freq = 0;
|
|
||||||
esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_CPU, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &freq);
|
|
||||||
return freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
TaskHandle_t loop_task_handle = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
TaskHandle_t loop_task_handle = nullptr; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
static StaticTask_t loop_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
static StaticTask_t loop_task_tcb; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
static StackType_t
|
static StackType_t
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#ifdef USE_ESP32
|
||||||
|
|
||||||
|
// defines.h must come before crash_handler.h so USE_ESP32_CRASH_HANDLER is set
|
||||||
|
// before crash_handler.h's #ifdef-guarded namespace block is parsed.
|
||||||
|
#include "esphome/core/defines.h"
|
||||||
|
#include "crash_handler.h"
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
|
||||||
|
#include <esp_clk_tree.h>
|
||||||
|
#include <esp_ota_ops.h>
|
||||||
|
#include <esp_system.h>
|
||||||
|
#include <esp_task_wdt.h>
|
||||||
|
#include <esp_timer.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
|
||||||
|
// Empty esp32 namespace block to satisfy ci-custom's lint_namespace check.
|
||||||
|
// HAL functions live in namespace esphome (root) — they are not part of the
|
||||||
|
// esp32 component's API.
|
||||||
|
namespace esphome::esp32 {} // namespace esphome::esp32
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
|
||||||
|
// Use xTaskGetTickCount() when tick rate is 1 kHz (ESPHome's default via sdkconfig),
|
||||||
|
// falling back to esp_timer for non-standard rates. IRAM_ATTR is required because
|
||||||
|
// Wiegand and ZyAura call millis() from IRAM_ATTR ISR handlers on ESP32.
|
||||||
|
// xTaskGetTickCountFromISR() is used in ISR context to satisfy the FreeRTOS API contract.
|
||||||
|
uint32_t IRAM_ATTR HOT millis() {
|
||||||
|
#if CONFIG_FREERTOS_HZ == 1000
|
||||||
|
if (xPortInIsrContext()) [[unlikely]] {
|
||||||
|
return xTaskGetTickCountFromISR();
|
||||||
|
}
|
||||||
|
return xTaskGetTickCount();
|
||||||
|
#else
|
||||||
|
return micros_to_millis(static_cast<uint64_t>(esp_timer_get_time()));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_restart() {
|
||||||
|
esp_restart();
|
||||||
|
// restart() doesn't always end execution
|
||||||
|
while (true) { // NOLINT(clang-diagnostic-unreachable-code)
|
||||||
|
yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void arch_init() {
|
||||||
|
#ifdef USE_ESP32_CRASH_HANDLER
|
||||||
|
// Read crash data from previous boot before anything else
|
||||||
|
esp32::crash_handler_read_and_clear();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Enable the task watchdog only on the loop task (from which we're currently running)
|
||||||
|
esp_task_wdt_add(nullptr);
|
||||||
|
|
||||||
|
// Handle OTA rollback: mark partition valid immediately unless USE_OTA_ROLLBACK is enabled,
|
||||||
|
// in which case safe_mode will mark it valid after confirming successful boot.
|
||||||
|
#ifndef USE_OTA_ROLLBACK
|
||||||
|
esp_ota_mark_app_valid_cancel_rollback();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t arch_get_cpu_freq_hz() {
|
||||||
|
uint32_t freq = 0;
|
||||||
|
esp_clk_tree_src_get_freq_hz(SOC_MOD_CLK_CPU, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &freq);
|
||||||
|
return freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // USE_ESP32
|
||||||
@@ -164,7 +164,7 @@ class RemoteTransmitterBase : public RemoteComponentBase {
|
|||||||
return TransmitCall(this);
|
return TransmitCall(this);
|
||||||
}
|
}
|
||||||
template<typename Protocol>
|
template<typename Protocol>
|
||||||
void transmit(const typename Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
|
void transmit(const Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
|
||||||
auto call = this->transmit();
|
auto call = this->transmit();
|
||||||
Protocol().encode(call.get_data(), data);
|
Protocol().encode(call.get_data(), data);
|
||||||
call.set_send_times(send_times);
|
call.set_send_times(send_times);
|
||||||
@@ -250,10 +250,10 @@ template<typename T> class RemoteReceiverBinarySensor : public RemoteReceiverBin
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_data(typename T::ProtocolData data) { data_ = data; }
|
void set_data(T::ProtocolData data) { data_ = data; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typename T::ProtocolData data_;
|
T::ProtocolData data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -278,7 +278,7 @@ class RemoteTransmittable {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
template<typename Protocol>
|
template<typename Protocol>
|
||||||
void transmit_(const typename Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
|
void transmit_(const Protocol::ProtocolData &data, uint32_t send_times = 1, uint32_t send_wait = 0) {
|
||||||
this->transmitter_->transmit<Protocol>(data, send_times, send_wait);
|
this->transmitter_->transmit<Protocol>(data, send_times, send_wait);
|
||||||
}
|
}
|
||||||
RemoteTransmitterBase *transmitter_;
|
RemoteTransmitterBase *transmitter_;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ template<typename ValueType, int MaxBits> struct DefaultBitPolicy {
|
|||||||
///
|
///
|
||||||
template<typename ValueType, typename BitPolicy = DefaultBitPolicy<ValueType, 16>> class FiniteSetMask {
|
template<typename ValueType, typename BitPolicy = DefaultBitPolicy<ValueType, 16>> class FiniteSetMask {
|
||||||
public:
|
public:
|
||||||
using bitmask_t = typename BitPolicy::mask_t;
|
using bitmask_t = BitPolicy::mask_t;
|
||||||
|
|
||||||
constexpr FiniteSetMask() = default;
|
constexpr FiniteSetMask() = default;
|
||||||
|
|
||||||
|
|||||||
+3
-7
@@ -30,15 +30,11 @@
|
|||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
// ESP8266 inlines delayMicroseconds() and arch_feed_wdt() in hal/hal_esp8266.h;
|
// Cross-platform declarations. delayMicroseconds(), arch_feed_wdt(),
|
||||||
// every other platform keeps them out-of-line in components/<platform>/core.cpp.
|
// arch_get_cpu_cycle_count() vary per platform (some inline, some
|
||||||
#ifndef USE_ESP8266
|
// out-of-line) so they live in hal/hal_<platform>.h.
|
||||||
void delayMicroseconds(uint32_t us); // NOLINT(readability-identifier-naming)
|
|
||||||
void arch_feed_wdt();
|
|
||||||
#endif
|
|
||||||
void __attribute__((noreturn)) arch_restart();
|
void __attribute__((noreturn)) arch_restart();
|
||||||
void arch_init();
|
void arch_init();
|
||||||
uint32_t arch_get_cpu_cycle_count();
|
|
||||||
uint32_t arch_get_cpu_freq_hz();
|
uint32_t arch_get_cpu_freq_hz();
|
||||||
|
|
||||||
#ifndef USE_ESP8266
|
#ifndef USE_ESP8266
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <esp_attr.h>
|
#include <esp_attr.h>
|
||||||
|
#include <esp_cpu.h>
|
||||||
|
#include <esp_task_wdt.h>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
|
|
||||||
@@ -15,6 +17,11 @@
|
|||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
|
// Forward decl from helpers.h (esphome/core/helpers.h) — kept here so this
|
||||||
|
// header does not need to pull the rest of helpers.h.
|
||||||
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
|
void delay_microseconds_safe(uint32_t us);
|
||||||
|
|
||||||
/// Returns true when executing inside an interrupt handler.
|
/// Returns true when executing inside an interrupt handler.
|
||||||
__attribute__((always_inline)) inline bool in_isr_context() { return xPortInIsrContext() != 0; }
|
__attribute__((always_inline)) inline bool in_isr_context() { return xPortInIsrContext() != 0; }
|
||||||
|
|
||||||
@@ -30,6 +37,11 @@ __attribute__((always_inline)) inline uint64_t millis_64() {
|
|||||||
return micros_to_millis<uint64_t>(static_cast<uint64_t>(esp_timer_get_time()));
|
return micros_to_millis<uint64_t>(static_cast<uint64_t>(esp_timer_get_time()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(readability-identifier-naming)
|
||||||
|
__attribute__((always_inline)) inline void delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); }
|
||||||
|
__attribute__((always_inline)) inline void arch_feed_wdt() { esp_task_wdt_reset(); }
|
||||||
|
__attribute__((always_inline)) inline uint32_t arch_get_cpu_cycle_count() { return esp_cpu_get_cycle_count(); }
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ESP32
|
#endif // USE_ESP32
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ __attribute__((always_inline)) inline uint16_t progmem_read_uint16(const uint16_
|
|||||||
__attribute__((always_inline)) inline void delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); }
|
__attribute__((always_inline)) inline void delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); }
|
||||||
__attribute__((always_inline)) inline void arch_feed_wdt() { system_soft_wdt_feed(); }
|
__attribute__((always_inline)) inline void arch_feed_wdt() { system_soft_wdt_feed(); }
|
||||||
|
|
||||||
|
uint32_t arch_get_cpu_cycle_count();
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ESP8266
|
#endif // USE_ESP8266
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ uint32_t micros();
|
|||||||
uint32_t millis();
|
uint32_t millis();
|
||||||
uint64_t millis_64();
|
uint64_t millis_64();
|
||||||
|
|
||||||
|
void delayMicroseconds(uint32_t us); // NOLINT(readability-identifier-naming)
|
||||||
|
void arch_feed_wdt();
|
||||||
|
uint32_t arch_get_cpu_cycle_count();
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_HOST
|
#endif // USE_HOST
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ __attribute__((always_inline)) inline uint32_t millis() { return static_cast<uin
|
|||||||
#endif
|
#endif
|
||||||
__attribute__((always_inline)) inline uint64_t millis_64() { return Millis64Impl::compute(millis()); }
|
__attribute__((always_inline)) inline uint64_t millis_64() { return Millis64Impl::compute(millis()); }
|
||||||
|
|
||||||
|
void delayMicroseconds(uint32_t us); // NOLINT(readability-identifier-naming)
|
||||||
|
void arch_feed_wdt();
|
||||||
|
uint32_t arch_get_cpu_cycle_count();
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_LIBRETINY
|
#endif // USE_LIBRETINY
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ __attribute__((always_inline)) inline uint32_t micros() { return static_cast<uin
|
|||||||
__attribute__((always_inline)) inline uint32_t millis() { return micros_to_millis(::time_us_64()); }
|
__attribute__((always_inline)) inline uint32_t millis() { return micros_to_millis(::time_us_64()); }
|
||||||
__attribute__((always_inline)) inline uint64_t millis_64() { return micros_to_millis<uint64_t>(::time_us_64()); }
|
__attribute__((always_inline)) inline uint64_t millis_64() { return micros_to_millis<uint64_t>(::time_us_64()); }
|
||||||
|
|
||||||
|
void delayMicroseconds(uint32_t us); // NOLINT(readability-identifier-naming)
|
||||||
|
void arch_feed_wdt();
|
||||||
|
uint32_t arch_get_cpu_cycle_count();
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_RP2040
|
#endif // USE_RP2040
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ uint32_t micros();
|
|||||||
uint32_t millis();
|
uint32_t millis();
|
||||||
uint64_t millis_64();
|
uint64_t millis_64();
|
||||||
|
|
||||||
|
void delayMicroseconds(uint32_t us); // NOLINT(readability-identifier-naming)
|
||||||
|
void arch_feed_wdt();
|
||||||
|
uint32_t arch_get_cpu_cycle_count();
|
||||||
|
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
||||||
#endif // USE_ZEPHYR
|
#endif // USE_ZEPHYR
|
||||||
|
|||||||
Reference in New Issue
Block a user