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>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.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.
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