Mark 12 leaf classes (no subclasses) as final to enable
compiler devirtualization of virtual calls, reducing code
size and improving performance on embedded targets.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eliminates virtual dispatch from ESPPreferenceBackend and ESPPreferences.
Only one implementation of each exists per platform build, so the
polymorphic design was unnecessary overhead — same pattern as OTA (#14473)
and socket (#14398) devirtualizations.
Each platform's backend class is now a standalone final class in its own
header (preference_backend.h). The preferences manager class is extracted
to the platform's preferences.h with a PreferencesMixin CRTP base for
shared template helpers. core/preference_backend.h provides the
PreferenceBackend alias, ESPPreferenceObject, and DECLARE_PREFERENCE_ALIASES
macro. core/preferences.h is a thin wrapper including the active platform.
ESPPreferenceBackend and ESPPreferences become backward-compatible type
aliases to the concrete types. Zero caller changes required.
Don't set started_ = true in setup(). Let the link polling in
loop() set it when the W5500 PHY link is actually up. Previously,
setting it immediately caused a spurious state transition because
the W5500 needs time after begin() before the link is ready.
localIP() reads netif->ip_addr which can be mutated by DHCP
callbacks from IRQ context. Lock for consistency since this is
called from API responses, not just hot-loop polling.
- Throttle linkStatus()/connected() polling to 500ms intervals to
avoid excessive SPI transactions on every loop iteration
- Guard USE_ETHERNET/USE_ETHERNET_SPI in RP2040 defines.h block
with #ifndef to prevent macro redefinition warnings
Explain why linkStatus() and connected() are called without
LwIPLock — linkStatus() only reads the W5500 PHY via SPI, and
connected() does a single atomic 32-bit read of netif->ip_addr.
- Copy dns_getserver() values (not pointers) under LwIPLock in
dump_connect_params_() to avoid dereferencing stale pointers
- Read netif ip_addr/netmask/gw under LwIPLock to prevent races
with DHCP callbacks from IRQ context
- Remove duplicate connect_begin_ assignment in start_connect_()
- Remove duplicate status_set_warning() call in start_connect_()
Add a separate no-argument status_set_warning() that delegates to the
LogString* overload, matching the existing status_set_error() pattern.
This allows the linker to garbage-collect the const char* overload in
firmware that only uses no-arg or LOG_STR() calls.
Migrate static string literal callers to LOG_STR() so the const char*
overload can be eliminated in most builds.
- Use cv.SplitDefault for clock_speed (default only on ESP32)
- Use cv.only_on_esp32 for clock_speed and polling_interval validators
- Single SPI_SCHEMA works for both ESP32 and RP2040
- Add type annotations to _to_code_esp32 and _to_code_rp2040
These options are handled by arduino-pico internally on RP2040.
Use cv.only_on([Platform.ESP32]) in the schema validators instead
of rejecting them in _validate().
- Clean up eth_ on begin() failure to prevent leak and stale pointer
- Add LwIPLock around dns_getserver() in get_dns_address()
- Add LwIPLock around dns_setserver() in start_connect_()
- Add LwIPLock around dns_getserver() in dump_connect_params_()
- Reject clock_speed and polling_interval config options on RP2040
- Add CONFIG_ETH_SPI_ETHERNET_W5500, CONFIG_ETH_SPI_ETHERNET_DM9051,
CONFIG_ETH_USE_ESP32_EMAC to defines.h for clang-tidy visibility
- Fix %lu format to PRIu32 for polling_interval_
Add W5500 SPI Ethernet support for RP2040 boards using arduino-pico's
Wiznet5500lwIP class. Tested on WIZnet W5500-EVB-Pico hardware.
- Add ethernet_component_rp2040.cpp with W5500 implementation
- Add RP2040 members and setters to ethernet_component.h
- Enable RP2040 platform in SPI_SCHEMA and FILTER_SOURCE_FILES
- Add RP2040 validation, code generation, and lwIP_w5500 library
- Add W5500 RP2040 test YAML
Restructure the ethernet component from ESP32-only to multi-platform,
following the same pattern as the wifi component (FILTER_SOURCE_FILES
with platform-specific .cpp files).
- Split ethernet_component.cpp into common code + ethernet_component_esp32.cpp
- Remove DEPENDENCIES = ["esp32"], add platform validators per type
- Add FILTER_SOURCE_FILES to select platform-specific .cpp
- Move ESP32 imports inside platform-conditional functions
- Update ethernet_info guards from USE_ESP32 to USE_ETHERNET
- Add USE_ETHERNET_SPI/OPENETH/SPI_POLLING_SUPPORT to defines.h
- Guard ethernet_helpers.c with USE_ESP32
No behavioral changes for ESP32 — this is a pure restructuring to
enable adding non-ESP32 platform support.
Restructure the ethernet component from ESP32-only to multi-platform,
following the same pattern as the wifi component (FILTER_SOURCE_FILES
with platform-specific .cpp files).
- Split ethernet_component.cpp into common code + ethernet_component_esp32.cpp
- Remove DEPENDENCIES = ["esp32"], add platform validators per type
- Add FILTER_SOURCE_FILES to select platform-specific .cpp
- Move ESP32 imports inside platform-conditional functions
- Update ethernet_info guards from USE_ESP32 to USE_ETHERNET
- Add USE_ETHERNET_SPI/OPENETH/SPI_POLLING_SUPPORT to defines.h
- Guard ethernet_helpers.c with USE_ESP32
No behavioral changes for ESP32 — this is a pure restructuring to
enable adding non-ESP32 platform support.
Restructure the ethernet component from ESP32-only to multi-platform,
following the same pattern as the wifi component (FILTER_SOURCE_FILES
with platform-specific .cpp files).
- Split ethernet_component.cpp into common code + ethernet_component_esp32.cpp
- Remove DEPENDENCIES = ["esp32"], add platform validators per type
- Add FILTER_SOURCE_FILES to select platform-specific .cpp
- Move ESP32 imports inside platform-conditional functions
- Update ethernet_info guards from USE_ESP32 to USE_ETHERNET
- Add USE_ETHERNET_SPI/OPENETH/SPI_POLLING_SUPPORT to defines.h
- Guard ethernet_helpers.c with USE_ESP32
No behavioral changes for ESP32 — this is a pure restructuring to
enable adding non-ESP32 platform support.