Symbols declared with extern "C" linkage (like resetPins in esp8266/core.cpp)
lack C++ namespace prefixes, causing them to fall through to "other" in the
memory analysis. This adds source-file-based attribution by scanning ESPHome
object files with nm to build a symbol-to-component map.
Also removes resetPins from the arduino_core heuristic pattern since it's
an ESPHome function, not an Arduino one.
Replace three separate equality comparisons with a single bitmask
shift-and-test. This compiles to fully branchless code and halves
the function size on Xtensa (38 → 19 bytes, 14 → 7 instructions).
Only one preferences backend is ever compiled per binary, so the
platform prefix is redundant. Shorten all TAG strings from
"<platform>.preferences" to just "preferences".
Saves 4-8 bytes of RAM per platform (tag string stored in .rodata
on ESP8266).
Move LOG_LEVEL_COLOR_DIGIT and LOG_LEVEL_LETTER_CHARS arrays from
.rodata (RAM) to PROGMEM (flash) on ESP8266. These small lookup
tables were consuming 16 bytes of RAM unnecessarily.
Results on a minimal ESP8266 config:
- RAM: -16 bytes (.rodata 948 → 932 bytes)
- Flash: +32 bytes (PROGMEM access code)
Extract cycle_or_clamp_ helper and simplify the increment/decrement
branches by flattening nested conditionals. Use LOG_STR_LITERAL for
cycling log strings.
ESP32 modules like the ESP32-PICO-V3-02 use a different flash pin
configuration where GPIO7 and GPIO8 are freely usable. The existing
ignore_pin_validation_error option allows bypassing this check but
the error message did not mention it, making it hard to discover.
The SerializationBuffer introduced in #13625 places a 640-byte buffer
on the stack. When handling HTTP requests on the ESP-IDF httpd task
(which has a default stack of 4096 bytes), the deep call chain from
handleRequest through JSON serialization and lwip_send can overflow.
Increase the httpd task stack by 256 bytes to restore headroom.
Fixes#14991
time.h was missing #include "esphome/core/defines.h", so USE_TIME_TIMEZONE
was never defined when compiling time.cpp. Both functions always took the
#else path, returning 0 offset and treating local time as UTC.
When Callback::create receives a function reference (e.g. void(&)(int)),
&callable gives the address of the function's machine code, not a
pointer variable. The memcpy then reads bytes from executable code
memory instead of copying a function pointer value.
Fix by decaying the callable into a local variable before memcpy,
which converts function references to function pointers stored on
the stack.
No current callers trigger this bug (all pass lambdas), but this
prevents incorrect behavior if bare function names are ever passed.
Boards like rpipico2 (Raspberry Pi Pico 2) don't have WiFi hardware
but ESPHome allowed configuring wifi on them, leading to linker errors
from missing CYW43 driver symbols. Add validation to catch this at
config time with a clear error message.
- Add wifi detection to the board generator by checking for
PICO_CYW43_SUPPORTED=1 in upstream extra_flags
- Add validation in wifi component to reject non-WiFi RP2040 boards
Closes https://github.com/esphome/esphome/issues/14989