mirror of
https://github.com/esphome/esphome.git
synced 2026-09-13 00:07:32 +00:00
Merge branch 'dev' into partition-table-ota
This commit is contained in:
+29
-4
@@ -5,24 +5,30 @@ Checks: >-
|
||||
-altera-*,
|
||||
-android-*,
|
||||
-boost-*,
|
||||
-bugprone-derived-method-shadowing-base-method,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-implicit-widening-of-multiplication-result,
|
||||
-bugprone-invalid-enum-default-initialization,
|
||||
-bugprone-multi-level-implicit-pointer-conversion,
|
||||
-bugprone-narrowing-conversions,
|
||||
-bugprone-tagged-union-member-count,
|
||||
-bugprone-signed-char-misuse,
|
||||
-bugprone-switch-missing-default-case,
|
||||
-cert-dcl50-cpp,
|
||||
-cert-err33-c,
|
||||
-cert-err58-cpp,
|
||||
-cert-int09-c,
|
||||
-cert-oop57-cpp,
|
||||
-cert-str34-c,
|
||||
-clang-analyzer-optin.core.EnumCastOutOfRange,
|
||||
-clang-analyzer-optin.cplusplus.UninitializedObject,
|
||||
-clang-analyzer-osx.*,
|
||||
-clang-analyzer-security.ArrayBound,
|
||||
-clang-diagnostic-delete-abstract-non-virtual-dtor,
|
||||
-clang-diagnostic-delete-non-abstract-non-virtual-dtor,
|
||||
-clang-diagnostic-deprecated-declarations,
|
||||
-clang-diagnostic-ignored-optimization-argument,
|
||||
-clang-diagnostic-missing-designated-field-initializers,
|
||||
-clang-diagnostic-missing-field-initializers,
|
||||
-clang-diagnostic-shadow-field,
|
||||
-clang-diagnostic-unused-const-variable,
|
||||
@@ -42,6 +48,7 @@ Checks: >-
|
||||
-cppcoreguidelines-owning-memory,
|
||||
-cppcoreguidelines-prefer-member-initializer,
|
||||
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||
-cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,
|
||||
-cppcoreguidelines-pro-bounds-constant-array-index,
|
||||
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||
-cppcoreguidelines-pro-type-const-cast,
|
||||
@@ -54,12 +61,13 @@ Checks: >-
|
||||
-cppcoreguidelines-rvalue-reference-param-not-moved,
|
||||
-cppcoreguidelines-special-member-functions,
|
||||
-cppcoreguidelines-use-default-member-init,
|
||||
-cppcoreguidelines-use-enum-class,
|
||||
-cppcoreguidelines-virtual-class-destructor,
|
||||
-fuchsia-default-arguments-calls,
|
||||
-fuchsia-default-arguments-declarations,
|
||||
-fuchsia-multiple-inheritance,
|
||||
-fuchsia-overloaded-operator,
|
||||
-fuchsia-statically-constructed-objects,
|
||||
-fuchsia-default-arguments-declarations,
|
||||
-fuchsia-default-arguments-calls,
|
||||
-google-build-using-namespace,
|
||||
-google-explicit-constructor,
|
||||
-google-readability-braces-around-statements,
|
||||
@@ -71,16 +79,23 @@ Checks: >-
|
||||
-llvm-else-after-return,
|
||||
-llvm-header-guard,
|
||||
-llvm-include-order,
|
||||
-llvm-prefer-static-over-anonymous-namespace,
|
||||
-llvm-qualified-auto,
|
||||
-llvm-use-ranges,
|
||||
-llvmlibc-*,
|
||||
-misc-const-correctness,
|
||||
-misc-include-cleaner,
|
||||
-misc-multiple-inheritance,
|
||||
-misc-no-recursion,
|
||||
-misc-non-private-member-variables-in-classes,
|
||||
-misc-override-with-different-visibility,
|
||||
-misc-unused-parameters,
|
||||
-misc-use-anonymous-namespace,
|
||||
-misc-use-internal-linkage,
|
||||
-modernize-avoid-bind,
|
||||
-modernize-avoid-variadic-functions,
|
||||
-modernize-avoid-c-arrays,
|
||||
-modernize-avoid-c-style-cast,
|
||||
-modernize-concat-nested-namespaces,
|
||||
-modernize-macro-to-enum,
|
||||
-modernize-return-braced-init-list,
|
||||
@@ -88,32 +103,42 @@ Checks: >-
|
||||
-modernize-use-auto,
|
||||
-modernize-use-constraints,
|
||||
-modernize-use-default-member-init,
|
||||
-modernize-use-designated-initializers,
|
||||
-modernize-use-equals-default,
|
||||
-modernize-use-integer-sign-comparison,
|
||||
-modernize-use-nodiscard,
|
||||
-modernize-use-nullptr,
|
||||
-modernize-use-nodiscard,
|
||||
-modernize-use-nullptr,
|
||||
-modernize-use-ranges,
|
||||
-modernize-use-trailing-return-type,
|
||||
-mpi-*,
|
||||
-objc-*,
|
||||
-performance-enum-size,
|
||||
-portability-avoid-pragma-once,
|
||||
-portability-template-virtual-member-function,
|
||||
-readability-ambiguous-smartptr-reset-call,
|
||||
-readability-avoid-nested-conditional-operator,
|
||||
-readability-container-contains,
|
||||
-readability-container-data-pointer,
|
||||
-readability-convert-member-functions-to-static,
|
||||
-readability-else-after-return,
|
||||
-readability-enum-initial-value,
|
||||
-readability-function-cognitive-complexity,
|
||||
-readability-implicit-bool-conversion,
|
||||
-readability-isolate-declaration,
|
||||
-readability-magic-numbers,
|
||||
-readability-make-member-function-const,
|
||||
-readability-math-missing-parentheses,
|
||||
-readability-named-parameter,
|
||||
-readability-redundant-casting,
|
||||
-readability-redundant-inline-specifier,
|
||||
-readability-redundant-member-init,
|
||||
-readability-redundant-parentheses,
|
||||
-readability-redundant-string-init,
|
||||
-readability-redundant-typename,
|
||||
-readability-uppercase-literal-suffix,
|
||||
-readability-use-anyofallof,
|
||||
-readability-use-std-min-max,
|
||||
-readability-use-concise-preprocessor-directives,
|
||||
WarningsAsErrors: '*'
|
||||
FormatStyle: google
|
||||
CheckOptions:
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1b1ce6324c50c4595703c7df0a8a479b4fe84b71ff1a8793cce1a16f17a33324
|
||||
0c7f309d70eca8e3efd510092ddb23c530f3934c49371717efa124b788d761f8
|
||||
|
||||
@@ -127,7 +127,7 @@ def validate_potentially_or_condition(value):
|
||||
return validate_condition(value)
|
||||
|
||||
|
||||
DelayAction = cg.esphome_ns.class_("DelayAction", Action, cg.Component)
|
||||
DelayAction = cg.esphome_ns.class_("DelayAction", Action)
|
||||
LambdaAction = cg.esphome_ns.class_("LambdaAction", Action)
|
||||
StatelessLambdaAction = cg.esphome_ns.class_("StatelessLambdaAction", Action)
|
||||
IfAction = cg.esphome_ns.class_("IfAction", Action)
|
||||
@@ -396,7 +396,6 @@ async def delay_action_to_code(
|
||||
args: TemplateArgsType,
|
||||
) -> MockObj:
|
||||
var = cg.new_Pvariable(action_id, template_arg)
|
||||
await cg.register_component(var, {})
|
||||
template_ = await cg.templatable(config, args, cg.uint32)
|
||||
cg.add(var.set_delay(template_))
|
||||
return var
|
||||
|
||||
@@ -129,7 +129,7 @@ AdalightLightEffect::Frame AdalightLightEffect::parse_frame_(light::AddressableL
|
||||
uint8_t *led_data = &frame_[6];
|
||||
|
||||
for (int led = 0; led < accepted_led_count; led++, led_data += 3) {
|
||||
auto white = std::min(std::min(led_data[0], led_data[1]), led_data[2]);
|
||||
auto white = std::min({led_data[0], led_data[1], led_data[2]});
|
||||
|
||||
it[led].set(Color(led_data[0], led_data[1], led_data[2], white));
|
||||
}
|
||||
|
||||
@@ -424,6 +424,7 @@ class ProtoEncode {
|
||||
if (len == 0 && !force)
|
||||
return;
|
||||
encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 2); // type 2: Length-delimited string
|
||||
// NOLINTNEXTLINE(readability-inconsistent-ifelse-braces) -- false positive on [[likely]] attribute
|
||||
if (len < VARINT_MAX_1_BYTE) [[likely]] {
|
||||
PROTO_ENCODE_CHECK_BOUNDS(pos, 1 + len);
|
||||
*pos++ = static_cast<uint8_t>(len);
|
||||
|
||||
@@ -374,7 +374,8 @@ void Climate::save_state_(const ClimateTraits &traits) {
|
||||
#define TEMP_IGNORE_MEMACCESS
|
||||
#endif
|
||||
ClimateDeviceRestoreState state{};
|
||||
// initialize as zero to prevent random data on stack triggering erase
|
||||
// initialize as zero (including padding) to prevent random data on stack triggering erase
|
||||
// NOLINTNEXTLINE(bugprone-raw-memory-call-on-non-trivial-type) -- intentional bytewise zero for RTC save
|
||||
memset(&state, 0, sizeof(ClimateDeviceRestoreState));
|
||||
#ifdef TEMP_IGNORE_MEMACCESS
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
@@ -17,11 +17,13 @@ constexpr std::uintptr_t MBR_PARAM_PAGE_ADDR = 0xFFC;
|
||||
constexpr std::uintptr_t MBR_BOOTLOADER_ADDR = 0xFF8;
|
||||
|
||||
static inline uint32_t read_mem_u32(uintptr_t addr) {
|
||||
return *reinterpret_cast<volatile uint32_t *>(addr); // NOLINT(performance-no-int-to-ptr)
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr,clang-analyzer-core.FixedAddressDereference)
|
||||
return *reinterpret_cast<volatile uint32_t *>(addr);
|
||||
}
|
||||
|
||||
static inline uint8_t read_mem_u8(uintptr_t addr) {
|
||||
return *reinterpret_cast<volatile uint8_t *>(addr); // NOLINT(performance-no-int-to-ptr)
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr,clang-analyzer-core.FixedAddressDereference)
|
||||
return *reinterpret_cast<volatile uint8_t *>(addr);
|
||||
}
|
||||
|
||||
// defines from https://github.com/adafruit/Adafruit_nRF52_Bootloader which prints those information
|
||||
@@ -98,6 +100,7 @@ void DebugComponent::log_partition_info_() {
|
||||
#define NRF_PERIPH_ENABLED(periph, reg) \
|
||||
YESNO(((reg)->ENABLE & periph##_ENABLE_ENABLE_Msk) == (periph##_ENABLE_ENABLE_Enabled << periph##_ENABLE_ENABLE_Pos))
|
||||
|
||||
// NOLINTBEGIN(clang-analyzer-core.FixedAddressDereference) -- nRF peripheral registers are MMIO at fixed addresses
|
||||
static void log_peripherals_info() {
|
||||
// most peripherals are enabled only when in use so ESP_LOGV is enough
|
||||
ESP_LOGV(TAG, "Peripherals status:");
|
||||
@@ -131,6 +134,7 @@ static void log_peripherals_info() {
|
||||
YESNO((NRF_CRYPTOCELL->ENABLE & CRYPTOCELL_ENABLE_ENABLE_Msk) ==
|
||||
(CRYPTOCELL_ENABLE_ENABLE_Enabled << CRYPTOCELL_ENABLE_ENABLE_Pos)));
|
||||
}
|
||||
// NOLINTEND(clang-analyzer-core.FixedAddressDereference)
|
||||
#undef NRF_PERIPH_ENABLED
|
||||
#endif
|
||||
|
||||
@@ -159,8 +163,9 @@ size_t DebugComponent::get_device_info_(std::span<char, DEVICE_INFO_BUFFER_SIZE>
|
||||
char *buf = buffer.data();
|
||||
|
||||
// Main supply status
|
||||
const char *supply_status =
|
||||
(nrf_power_mainregstatus_get(NRF_POWER) == NRF_POWER_MAINREGSTATUS_NORMAL) ? "Normal voltage." : "High voltage.";
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.FixedAddressDereference) -- NRF_POWER is MMIO at a fixed address
|
||||
auto regstatus = nrf_power_mainregstatus_get(NRF_POWER);
|
||||
const char *supply_status = (regstatus == NRF_POWER_MAINREGSTATUS_NORMAL) ? "Normal voltage." : "High voltage.";
|
||||
ESP_LOGD(TAG, "Main supply status: %s", supply_status);
|
||||
pos = buf_append_str(buf, size, pos, "|Main supply status: ");
|
||||
pos = buf_append_str(buf, size, pos, supply_status);
|
||||
|
||||
@@ -56,8 +56,7 @@ bool E131AddressableLightEffect::process_(int universe, const E131Packet &packet
|
||||
// limit amount of lights per universe and received
|
||||
// packet.count is the number of DMX bytes including start code; divide by channels to get the number of lights
|
||||
int lights_in_packet = (packet.count > 0) ? (packet.count - 1) / channels_ : 0;
|
||||
int output_end =
|
||||
std::min(it->size(), std::min(output_offset + get_lights_per_universe(), output_offset + lights_in_packet));
|
||||
int output_end = std::min({it->size(), output_offset + get_lights_per_universe(), output_offset + lights_in_packet});
|
||||
auto *input_data = packet.values + 1;
|
||||
|
||||
auto effect_name = get_name();
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include "esphome/core/defines.h"
|
||||
#include "crash_handler.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/defines.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/task.h>
|
||||
|
||||
@@ -22,54 +13,7 @@ extern "C" __attribute__((weak)) void initArduino() {}
|
||||
|
||||
namespace esphome {
|
||||
|
||||
// yield(), delay(), micros(), millis_64() inlined in hal.h.
|
||||
// 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;
|
||||
}
|
||||
|
||||
// HAL functions live in hal.cpp. This file keeps only the loop task setup.
|
||||
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 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
|
||||
@@ -140,6 +140,7 @@ void IRAM_ATTR ISRInternalGPIOPin::digital_write(bool value) {
|
||||
|
||||
void IRAM_ATTR ISRInternalGPIOPin::clear_interrupt() {
|
||||
auto *arg = reinterpret_cast<ISRPinArg *>(arg_);
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.FixedAddressDereference) -- GPIO_REG_WRITE is MMIO at a fixed address
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1UL << arg->pin);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ static inline bool esp_rtc_user_mem_read(uint32_t index, uint32_t *dest) {
|
||||
if (index >= ESP_RTC_USER_MEM_SIZE_WORDS) {
|
||||
return false;
|
||||
}
|
||||
*dest = ESP_RTC_USER_MEM[index]; // NOLINT(performance-no-int-to-ptr)
|
||||
*dest = ESP_RTC_USER_MEM[index]; // NOLINT(performance-no-int-to-ptr,clang-analyzer-core.FixedAddressDereference)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ static inline bool esp_rtc_user_mem_write(uint32_t index, uint32_t value) {
|
||||
}
|
||||
|
||||
auto *ptr = &ESP_RTC_USER_MEM[index]; // NOLINT(performance-no-int-to-ptr)
|
||||
*ptr = value;
|
||||
*ptr = value; // NOLINT(clang-analyzer-core.FixedAddressDereference)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ int HttpContainerArduino::read(uint8_t *buf, size_t max_len) {
|
||||
// Non-chunked path
|
||||
int available_data = stream_ptr->available();
|
||||
size_t remaining = (this->content_length > 0) ? (this->content_length - this->bytes_read_) : max_len;
|
||||
int bufsize = std::min(max_len, std::min(remaining, (size_t) available_data));
|
||||
int bufsize = std::min({max_len, remaining, (size_t) available_data});
|
||||
|
||||
if (bufsize == 0) {
|
||||
this->duration_ms += (millis() - start);
|
||||
|
||||
@@ -11,6 +11,7 @@ void nvmc_wait();
|
||||
nrfx_err_t nrfx_nvmc_uicr_erase();
|
||||
}
|
||||
|
||||
// NOLINTBEGIN(clang-analyzer-core.FixedAddressDereference) -- NRF_UICR / NRF_TIMER2 are MMIO at fixed addresses
|
||||
namespace esphome::nrf52 {
|
||||
|
||||
enum class StatusFlags : uint8_t {
|
||||
@@ -113,6 +114,7 @@ static int board_esphome_init() {
|
||||
return 0;
|
||||
}
|
||||
} // namespace esphome::nrf52
|
||||
// NOLINTEND(clang-analyzer-core.FixedAddressDereference)
|
||||
|
||||
static int board_esphome_init() { return esphome::nrf52::board_esphome_init(); }
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ OTAResponseTypes ESP8266OTABackend::begin(size_t image_size) {
|
||||
|
||||
// Check boot mode - if boot mode is UART download mode,
|
||||
// we will not be able to reset into normal mode once update is done
|
||||
// NOLINTNEXTLINE(clang-analyzer-core.FixedAddressDereference) -- GPI is MMIO at a fixed address
|
||||
int boot_mode = (GPI >> BOOT_MODE_SHIFT) & BOOT_MODE_MASK;
|
||||
if (boot_mode == BOOT_MODE_UART_DOWNLOAD) {
|
||||
return OTA_RESPONSE_ERROR_INVALID_BOOTSTRAPPING;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "ota_backend_esp_idf.h"
|
||||
|
||||
#include "esphome/components/md5/md5.h"
|
||||
#include "esphome/components/watchdog/watchdog.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
@@ -57,29 +58,9 @@ OTAResponseTypes IDFOTABackend::begin(size_t image_size) {
|
||||
return OTA_RESPONSE_ERROR_NO_UPDATE_PARTITION;
|
||||
}
|
||||
|
||||
#if CONFIG_ESP_TASK_WDT_TIMEOUT_S < 15
|
||||
// The following function takes longer than the 5 seconds timeout of WDT
|
||||
esp_task_wdt_config_t wdtc;
|
||||
wdtc.idle_core_mask = 0;
|
||||
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
|
||||
wdtc.idle_core_mask |= (1 << 0);
|
||||
#endif
|
||||
#if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
|
||||
wdtc.idle_core_mask |= (1 << 1);
|
||||
#endif
|
||||
wdtc.timeout_ms = 15000;
|
||||
wdtc.trigger_panic = false;
|
||||
esp_task_wdt_reconfigure(&wdtc);
|
||||
#endif
|
||||
|
||||
watchdog::WatchdogManager watchdog(15000);
|
||||
esp_err_t err = esp_ota_begin(this->partition_, image_size, &this->update_handle_);
|
||||
|
||||
#if CONFIG_ESP_TASK_WDT_TIMEOUT_S < 15
|
||||
// Set the WDT back to the configured timeout
|
||||
wdtc.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000;
|
||||
esp_task_wdt_reconfigure(&wdtc);
|
||||
#endif
|
||||
|
||||
if (err != ESP_OK) {
|
||||
esp_ota_abort(this->update_handle_);
|
||||
this->update_handle_ = 0;
|
||||
|
||||
@@ -669,7 +669,7 @@ uint32_t Sprinkler::valve_run_duration_adjusted(const size_t valve_number) {
|
||||
// run_duration must not be less than any of these
|
||||
if ((run_duration < this->start_delay_) || (run_duration < this->stop_delay_) ||
|
||||
(run_duration < this->switching_delay_.value_or(0) * 2)) {
|
||||
return std::max(this->switching_delay_.value_or(0) * 2, std::max(this->start_delay_, this->stop_delay_));
|
||||
return std::max({this->switching_delay_.value_or(0) * 2, this->start_delay_, this->stop_delay_});
|
||||
}
|
||||
return run_duration;
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ class ProjectUpdateTrigger : public Trigger<std::string>, public Component {
|
||||
};
|
||||
#endif
|
||||
|
||||
template<typename... Ts> class DelayAction : public Action<Ts...>, public Component {
|
||||
template<typename... Ts> class DelayAction : public Action<Ts...> {
|
||||
public:
|
||||
explicit DelayAction() = default;
|
||||
|
||||
@@ -198,8 +198,8 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, public Compon
|
||||
// to avoid overhead from capturing arguments by value
|
||||
if constexpr (sizeof...(Ts) == 0) {
|
||||
App.scheduler.set_timer_common_(
|
||||
this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::NUMERIC_ID_INTERNAL, nullptr,
|
||||
static_cast<uint32_t>(InternalSchedulerID::DELAY_ACTION), this->delay_.value(),
|
||||
/* component= */ nullptr, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::SELF_POINTER,
|
||||
/* static_name= */ reinterpret_cast<const char *>(this), /* hash_or_id= */ 0, this->delay_.value(),
|
||||
[this]() { this->play_next_(); },
|
||||
/* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1);
|
||||
} else {
|
||||
@@ -208,18 +208,18 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, public Compon
|
||||
// `mutable` is required so captured copies of non-const reference args (e.g. std::string&)
|
||||
// are passed as non-const lvalues to play_next_(const Ts&...) where Ts may be `T&`
|
||||
auto f = [this, x...]() mutable { this->play_next_(x...); };
|
||||
App.scheduler.set_timer_common_(this, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::NUMERIC_ID_INTERNAL,
|
||||
nullptr, static_cast<uint32_t>(InternalSchedulerID::DELAY_ACTION),
|
||||
this->delay_.value(x...), std::move(f),
|
||||
/* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1);
|
||||
App.scheduler.set_timer_common_(
|
||||
/* component= */ nullptr, Scheduler::SchedulerItem::TIMEOUT, Scheduler::NameType::SELF_POINTER,
|
||||
/* static_name= */ reinterpret_cast<const char *>(this), /* hash_or_id= */ 0, this->delay_.value(x...),
|
||||
std::move(f),
|
||||
/* is_retry= */ false, /* skip_cancel= */ this->num_running_ > 1);
|
||||
}
|
||||
}
|
||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
||||
|
||||
void play(const Ts &...x) override { /* ignore - see play_complex */
|
||||
}
|
||||
|
||||
void stop() override { this->cancel_timeout(InternalSchedulerID::DELAY_ACTION); }
|
||||
void stop() override { App.scheduler.cancel_timeout(this); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class LambdaAction : public Action<Ts...> {
|
||||
|
||||
@@ -169,7 +169,7 @@ struct Color {
|
||||
uint8_t r = rand >> 16;
|
||||
uint8_t g = rand >> 8;
|
||||
uint8_t b = rand >> 0;
|
||||
const uint16_t max_rgb = std::max(r, std::max(g, b));
|
||||
const uint16_t max_rgb = std::max({r, g, b});
|
||||
return Color(uint8_t((uint16_t(r) * 255U / max_rgb)), uint8_t((uint16_t(g) * 255U / max_rgb)),
|
||||
uint8_t((uint16_t(b) * 255U / max_rgb)), w);
|
||||
}
|
||||
|
||||
+3
-7
@@ -30,15 +30,11 @@
|
||||
|
||||
namespace esphome {
|
||||
|
||||
// ESP8266 inlines delayMicroseconds() and arch_feed_wdt() in hal/hal_esp8266.h;
|
||||
// every other platform keeps them out-of-line in components/<platform>/core.cpp.
|
||||
#ifndef USE_ESP8266
|
||||
void delayMicroseconds(uint32_t us); // NOLINT(readability-identifier-naming)
|
||||
void arch_feed_wdt();
|
||||
#endif
|
||||
// Cross-platform declarations. delayMicroseconds(), arch_feed_wdt(),
|
||||
// arch_get_cpu_cycle_count() vary per platform (some inline, some
|
||||
// out-of-line) so they live in hal/hal_<platform>.h.
|
||||
void __attribute__((noreturn)) arch_restart();
|
||||
void arch_init();
|
||||
uint32_t arch_get_cpu_cycle_count();
|
||||
uint32_t arch_get_cpu_freq_hz();
|
||||
|
||||
#ifndef USE_ESP8266
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <esp_attr.h>
|
||||
#include <esp_cpu.h>
|
||||
#include <esp_task_wdt.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
@@ -15,6 +17,11 @@
|
||||
|
||||
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.
|
||||
__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()));
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
#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 arch_feed_wdt() { system_soft_wdt_feed(); }
|
||||
|
||||
uint32_t arch_get_cpu_cycle_count();
|
||||
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ESP8266
|
||||
|
||||
@@ -19,6 +19,10 @@ uint32_t micros();
|
||||
uint32_t millis();
|
||||
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
|
||||
|
||||
#endif // USE_HOST
|
||||
|
||||
@@ -88,6 +88,10 @@ __attribute__((always_inline)) inline uint32_t millis() { return static_cast<uin
|
||||
#endif
|
||||
__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
|
||||
|
||||
#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 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
|
||||
|
||||
#endif // USE_RP2040
|
||||
|
||||
@@ -19,6 +19,10 @@ uint32_t micros();
|
||||
uint32_t millis();
|
||||
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
|
||||
|
||||
#endif // USE_ZEPHYR
|
||||
|
||||
@@ -663,8 +663,8 @@ float gamma_uncorrect(float value, float gamma) {
|
||||
}
|
||||
|
||||
void rgb_to_hsv(float red, float green, float blue, int &hue, float &saturation, float &value) {
|
||||
float max_color_value = std::max(std::max(red, green), blue);
|
||||
float min_color_value = std::min(std::min(red, green), blue);
|
||||
float max_color_value = std::max({red, green, blue});
|
||||
float min_color_value = std::min({red, green, blue});
|
||||
float delta = max_color_value - min_color_value;
|
||||
|
||||
if (delta == 0) {
|
||||
|
||||
@@ -69,6 +69,10 @@ template<typename Derived> class PreferencesMixin {
|
||||
ESPPreferenceObject make_preference(uint32_t type) {
|
||||
return static_cast<Derived *>(this)->make_preference(sizeof(T), type);
|
||||
}
|
||||
|
||||
private:
|
||||
PreferencesMixin() = default;
|
||||
friend Derived;
|
||||
};
|
||||
|
||||
// Macro for platform preferences.h headers to declare the standard aliases.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Useful stuff when working in a development environment
|
||||
clang-format==13.0.1 # also change in .pre-commit-config.yaml and Dockerfile when updating
|
||||
clang-tidy==18.1.8 # When updating clang-tidy, also update Dockerfile
|
||||
clang-tidy==22.1.0.1
|
||||
yamllint==1.38.0 # also change in .pre-commit-config.yaml when updating
|
||||
|
||||
+3
-3
@@ -295,7 +295,7 @@ def main():
|
||||
|
||||
failed_files = []
|
||||
try:
|
||||
executable = get_binary("clang-tidy", 18)
|
||||
executable = get_binary("clang-tidy", 22)
|
||||
task_queue = queue.Queue(args.jobs)
|
||||
lock = threading.Lock()
|
||||
for _ in range(args.jobs):
|
||||
@@ -341,13 +341,13 @@ def main():
|
||||
try:
|
||||
try:
|
||||
subprocess.call(
|
||||
["clang-apply-replacements-18", tmpdir], close_fds=False
|
||||
["clang-apply-replacements-22", tmpdir], close_fds=False
|
||||
)
|
||||
except FileNotFoundError:
|
||||
subprocess.call(["clang-apply-replacements", tmpdir], close_fds=False)
|
||||
except FileNotFoundError:
|
||||
print(
|
||||
"Error please install clang-apply-replacements-18 or clang-apply-replacements.\n",
|
||||
"Error please install clang-apply-replacements-22 or clang-apply-replacements.\n",
|
||||
file=sys.stderr,
|
||||
)
|
||||
except:
|
||||
|
||||
Reference in New Issue
Block a user