From 80ed54103257bab0ea1ba76caee56003ee5673e1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 19 May 2026 10:13:58 -0700 Subject: [PATCH] [core] Add progmem_memcpy HAL helper (#16470) --- esphome/components/esp8266/hal.h | 6 ++++++ esphome/core/hal.h | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/esphome/components/esp8266/hal.h b/esphome/components/esp8266/hal.h index effa9c9371..f3b33da692 100644 --- a/esphome/components/esp8266/hal.h +++ b/esphome/components/esp8266/hal.h @@ -58,6 +58,12 @@ __attribute__((always_inline)) inline const char *progmem_read_ptr(const char *c __attribute__((always_inline)) inline uint16_t progmem_read_uint16(const uint16_t *addr) { return pgm_read_word(addr); // NOLINT } +// Bulk PROGMEM copy: routes to the SDK's aligned-flash `memcpy_P` so callers +// don't have to drop to a byte-by-byte `progmem_read_byte` loop, which on +// ESP8266 is ~4x as many flash accesses as the bulk path. +__attribute__((always_inline)) inline void progmem_memcpy(void *dst, const void *src, size_t len) { + memcpy_P(dst, src, len); // NOLINT +} // NOLINTNEXTLINE(readability-identifier-naming) __attribute__((always_inline)) inline void delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } diff --git a/esphome/core/hal.h b/esphome/core/hal.h index 4babda807d..b44a422836 100644 --- a/esphome/core/hal.h +++ b/esphome/core/hal.h @@ -1,6 +1,7 @@ #pragma once -#include #include +#include +#include #include "gpio.h" #include "esphome/core/defines.h" #include "esphome/core/time_64.h" @@ -42,6 +43,9 @@ void __attribute__((noreturn)) arch_restart(); inline uint8_t progmem_read_byte(const uint8_t *addr) { return *addr; } inline const char *progmem_read_ptr(const char *const *addr) { return *addr; } inline uint16_t progmem_read_uint16(const uint16_t *addr) { return *addr; } +// Bulk copy out of PROGMEM. PROGMEM is a no-op everywhere except ESP8266, so a +// plain `std::memcpy` is correct and the fast path here. +inline void progmem_memcpy(void *dst, const void *src, size_t len) { std::memcpy(dst, src, len); } #endif } // namespace esphome