From a9ec101631a3c9fc917e7234b6e7bd99bcd6ff1f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 15 May 2026 22:36:15 -0700 Subject: [PATCH] [store_yaml] Use memcpy_P on ESP8266, std::memcpy elsewhere Byte-by-byte `progmem_read_byte` for a 512-byte chunk does 512 aligned 32-bit flash reads + shifts on ESP8266. Switching to `memcpy_P` lets the SDK do bulk aligned-flash copies. Other platforms get a plain `std::memcpy` since their `PROGMEM` is a no-op and the blob lives in normal address space. `memcpy_P` is only available on ESP8266 (via ``), so the implementation is platform-gated; both paths boil down to a one-call copy. --- esphome/components/store_yaml/store_yaml.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/esphome/components/store_yaml/store_yaml.cpp b/esphome/components/store_yaml/store_yaml.cpp index 3a3e57c627e..607575e2c6a 100644 --- a/esphome/components/store_yaml/store_yaml.cpp +++ b/esphome/components/store_yaml/store_yaml.cpp @@ -3,6 +3,10 @@ #ifdef USE_STORE_YAML #include "esphome/core/log.h" +#include +#ifdef USE_ESP8266 +#include +#endif namespace esphome::store_yaml { @@ -23,10 +27,15 @@ void StoreYamlComponent::dump_config() { } void StoreYamlComponent::read_chunk(size_t pos, uint8_t *dst, size_t len) const { - const uint8_t *src = this->data_ + pos; - for (size_t i = 0; i < len; i++) { - dst[i] = progmem_read_byte(&src[i]); - } +#ifdef USE_ESP8266 + // ESP8266 needs `memcpy_P` for aligned bulk flash reads; the byte-by-byte + // `progmem_read_byte` loop would otherwise emit ~4x as many flash accesses. + memcpy_P(dst, this->data_ + pos, len); +#else + // PROGMEM is a no-op everywhere else and the data lives in normal address + // space, so a plain `std::memcpy` is correct and the fast path. + std::memcpy(dst, this->data_ + pos, len); +#endif } } // namespace esphome::store_yaml