mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 12:17:23 +00:00
[wifi] Defer esp_wifi_init() to lazy-init so enable_on_boot: false actually saves RAM (#16606)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -632,6 +632,9 @@ void WiFiComponent::setup() {
|
||||
#endif
|
||||
|
||||
if (this->enable_on_boot_) {
|
||||
#ifdef USE_ESP32
|
||||
this->wifi_lazy_init_();
|
||||
#endif
|
||||
this->start();
|
||||
} else {
|
||||
this->state_ = WIFI_COMPONENT_STATE_DISABLED;
|
||||
@@ -1275,6 +1278,11 @@ void WiFiComponent::enable() {
|
||||
|
||||
ESP_LOGD(TAG, "Enabling");
|
||||
this->state_ = WIFI_COMPONENT_STATE_OFF;
|
||||
#ifdef USE_ESP32
|
||||
// Idempotent — only allocates DMA buffers + netifs on the first call. After this,
|
||||
// start() can safely run.
|
||||
this->wifi_lazy_init_();
|
||||
#endif
|
||||
this->start();
|
||||
}
|
||||
|
||||
|
||||
@@ -694,6 +694,12 @@ class WiFiComponent final : public Component {
|
||||
bool wifi_apply_hostname_();
|
||||
bool wifi_sta_connect_(const WiFiAP &ap);
|
||||
void wifi_pre_setup_();
|
||||
#ifdef USE_ESP32
|
||||
// ESP-IDF only: defers esp_wifi_init() + netif creation (which allocate ~15-30KB of
|
||||
// DMA-capable internal SRAM) until wifi actually needs to come up. Idempotent.
|
||||
// Called from setup() only when enable_on_boot_=true, and from enable() on first use.
|
||||
void wifi_lazy_init_();
|
||||
#endif
|
||||
WiFiSTAConnectStatus wifi_sta_connect_status_() const;
|
||||
bool is_connected_() const {
|
||||
return this->state_ == WIFI_COMPONENT_STATE_STA_CONNECTED &&
|
||||
@@ -889,6 +895,12 @@ class WiFiComponent final : public Component {
|
||||
bool rrm_{false};
|
||||
#endif
|
||||
bool enable_on_boot_{true};
|
||||
#ifdef USE_ESP32
|
||||
// Tracks whether esp_wifi_init() + netif creation has happened. Allows enable()
|
||||
// to be called at runtime without re-allocating, and ensures the heavy init is
|
||||
// skipped entirely when enable_on_boot_ is false until first enable().
|
||||
bool wifi_initialized_{false};
|
||||
#endif
|
||||
bool got_ipv4_address_{false};
|
||||
bool keep_scan_results_{false};
|
||||
bool has_completed_scan_after_captive_portal_start_{
|
||||
|
||||
@@ -163,11 +163,26 @@ void WiFiComponent::wifi_pre_setup_() {
|
||||
ESP_LOGE(TAG, "esp_event_handler_instance_register failed: %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
// NOTE: netif creation + esp_wifi_init() used to live here. They allocate ~15-30KB of
|
||||
// DMA-capable internal SRAM, which competes with W5500 SPI DMA and I2S DMA on
|
||||
// memory-tight devices. They are now deferred to wifi_lazy_init_(), called from
|
||||
// setup() when enable_on_boot_ is true, or from enable() on first runtime enable.
|
||||
// This makes enable_on_boot:false genuinely skip the wifi DMA allocation.
|
||||
}
|
||||
|
||||
s_sta_netif = esp_netif_create_default_wifi_sta();
|
||||
void WiFiComponent::wifi_lazy_init_() {
|
||||
if (this->wifi_initialized_)
|
||||
return;
|
||||
|
||||
// Guard each creation so partial init (e.g. a failed esp_wifi_init() below)
|
||||
// followed by a retry via enable() does not leak the existing netif handle
|
||||
// nor re-register the default WiFi handlers.
|
||||
if (s_sta_netif == nullptr)
|
||||
s_sta_netif = esp_netif_create_default_wifi_sta();
|
||||
|
||||
#ifdef USE_WIFI_AP
|
||||
s_ap_netif = esp_netif_create_default_wifi_ap();
|
||||
if (s_ap_netif == nullptr)
|
||||
s_ap_netif = esp_netif_create_default_wifi_ap();
|
||||
#endif // USE_WIFI_AP
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
@@ -175,7 +190,7 @@ void WiFiComponent::wifi_pre_setup_() {
|
||||
ESP_LOGW(TAG, "starting wifi without nvs");
|
||||
cfg.nvs_enable = false;
|
||||
}
|
||||
err = esp_wifi_init(&cfg);
|
||||
esp_err_t err = esp_wifi_init(&cfg);
|
||||
if (err != ERR_OK) {
|
||||
ESP_LOGE(TAG, "esp_wifi_init failed: %s", esp_err_to_name(err));
|
||||
return;
|
||||
@@ -185,6 +200,7 @@ void WiFiComponent::wifi_pre_setup_() {
|
||||
ESP_LOGE(TAG, "esp_wifi_set_storage failed: %s", esp_err_to_name(err));
|
||||
return;
|
||||
}
|
||||
this->wifi_initialized_ = true;
|
||||
}
|
||||
|
||||
bool WiFiComponent::wifi_mode_(optional<bool> sta, optional<bool> ap) {
|
||||
|
||||
15
tests/components/wifi/test-lifecycle.esp32-idf.yaml
Normal file
15
tests/components/wifi/test-lifecycle.esp32-idf.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
wifi:
|
||||
ssid: MySSID
|
||||
password: password1
|
||||
enable_on_boot: false
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
priority: 200
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
not:
|
||||
wifi.enabled:
|
||||
then:
|
||||
- wifi.enable:
|
||||
Reference in New Issue
Block a user