diff --git a/components/esp_hw_support/include/esp_private/sleep_modem.h b/components/esp_hw_support/include/esp_private/sleep_modem.h index 2e84830b6d..fe8e3ea220 100644 --- a/components/esp_hw_support/include/esp_private/sleep_modem.h +++ b/components/esp_hw_support/include/esp_private/sleep_modem.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -161,6 +161,35 @@ void esp_pm_register_light_sleep_default_params_config_callback(update_light_sle */ void esp_pm_unregister_light_sleep_default_params_config_callback(void); +#if SOC_PM_SUPPORT_PMU_MODEM_STATE +/** + * @brief Init Wi-Fi modem state. + * + * This function init wifi modem state. + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if no memory for link + */ +esp_err_t sleep_modem_wifi_modem_state_init(void); + +/** + * @brief Deinit Wi-Fi modem state. + * + * This function deinit wifi modem state. + */ +void sleep_modem_wifi_modem_state_deinit(void); + +/** + * @brief Function to check Wi-Fi modem state to skip light sleep. + * + * This function is to check if light sleep should skip by Wi-Fi modem state . + * @return + * - true skip light sleep + * - false not skip light sleep + */ +bool sleep_modem_wifi_modem_state_skip_light_sleep(void); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/sleep_modem.c b/components/esp_hw_support/sleep_modem.c index ccedf6a245..7e963aa64d 100644 --- a/components/esp_hw_support/sleep_modem.c +++ b/components/esp_hw_support/sleep_modem.c @@ -167,7 +167,7 @@ typedef struct sleep_modem_config { static sleep_modem_config_t s_sleep_modem = { .wifi.phy_link = NULL, .wifi.flags = 0 }; -static __attribute__((unused)) esp_err_t sleep_modem_wifi_modem_state_init(void) +esp_err_t sleep_modem_wifi_modem_state_init(void) { esp_err_t err = ESP_OK; phy_i2c_master_command_attribute_t cmd; @@ -244,7 +244,7 @@ static __attribute__((unused)) esp_err_t sleep_modem_wifi_modem_state_init(void) return err; } -static __attribute__((unused)) void sleep_modem_wifi_modem_state_deinit(void) +__attribute__((unused)) void sleep_modem_wifi_modem_state_deinit(void) { if (s_sleep_modem.wifi.phy_link) { regdma_link_destroy(s_sleep_modem.wifi.phy_link, 0); @@ -302,7 +302,7 @@ uint32_t IRAM_ATTR sleep_modem_reject_triggers(void) return reject_triggers; } -static __attribute__((unused)) bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_light_sleep(void) +bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_light_sleep(void) { bool skip = false; #if SOC_PM_SUPPORT_PMU_MODEM_STATE @@ -317,17 +317,8 @@ static __attribute__((unused)) bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_ esp_err_t sleep_modem_configure(int max_freq_mhz, int min_freq_mhz, bool light_sleep_enable) { #if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP - extern int esp_wifi_internal_mac_sleep_configure(bool, bool); - if (light_sleep_enable) { - if (sleep_modem_wifi_modem_state_init() == ESP_OK) { - esp_pm_register_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep); - esp_wifi_internal_mac_sleep_configure(light_sleep_enable, true); /* require WiFi to enable automatically receives the beacon */ - } - } else { - esp_wifi_internal_mac_sleep_configure(light_sleep_enable, false); /* require WiFi to disable automatically receives the beacon */ - esp_pm_unregister_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep); - sleep_modem_wifi_modem_state_deinit(); - } + extern int esp_wifi_internal_light_sleep_configure(bool); + esp_wifi_internal_light_sleep_configure(light_sleep_enable); #endif #if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT if (light_sleep_enable) { diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index a02146e63a..505b0bfee1 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,8 +85,10 @@ static bool s_is_phy_calibrated = false; static bool s_is_phy_reg_stored = false; /* Memory to store PHY digital registers */ static uint32_t* s_phy_digital_regs_mem = NULL; -static uint8_t s_phy_modem_init_ref = 0; #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP +static uint8_t s_phy_modem_init_ref = 0; +#endif #if CONFIG_ESP_PHY_MULTIPLE_INIT_DATA_BIN @@ -349,23 +351,29 @@ void esp_wifi_bt_power_domain_off(void) void esp_phy_modem_init(void) { -#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP _lock_acquire(&s_phy_access_lock); s_phy_modem_init_ref++; +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA if (s_phy_digital_regs_mem == NULL) { s_phy_digital_regs_mem = (uint32_t *)heap_caps_malloc(SOC_PHY_DIG_REGS_MEM_SIZE, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); } - _lock_release(&s_phy_access_lock); #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA +#if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + sleep_modem_wifi_modem_state_init(); +#endif // CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + _lock_release(&s_phy_access_lock); +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP } void esp_phy_modem_deinit(void) { -#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP _lock_acquire(&s_phy_access_lock); s_phy_modem_init_ref--; if (s_phy_modem_init_ref == 0) { +#if SOC_PM_MODEM_RETENTION_BY_BACKUPDMA s_is_phy_reg_stored = false; free(s_phy_digital_regs_mem); s_phy_digital_regs_mem = NULL; @@ -374,11 +382,14 @@ void esp_phy_modem_deinit(void) */ #if CONFIG_IDF_TARGET_ESP32C3 phy_init_flag(); -#endif - } - - _lock_release(&s_phy_access_lock); +#endif // CONFIG_IDF_TARGET_ESP32C3 #endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA +#if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + sleep_modem_wifi_modem_state_deinit(); +#endif // CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + } + _lock_release(&s_phy_access_lock); +#endif // SOC_PM_MODEM_RETENTION_BY_BACKUPDMA || CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP } #if CONFIG_MAC_BB_PD diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 08547bd882..417b046d30 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -123,6 +123,8 @@ static bool s_skipped_light_sleep[portNUM_PROCESSORS]; */ static bool s_skip_light_sleep[portNUM_PROCESSORS]; #endif // portNUM_PROCESSORS == 2 + +static _lock_t s_skip_light_sleep_lock; #endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE /* A flag indicating that Idle hook has run on a given CPU; @@ -547,25 +549,32 @@ static void IRAM_ATTR leave_idle(void) esp_err_t esp_pm_register_skip_light_sleep_callback(skip_light_sleep_cb_t cb) { + _lock_acquire(&s_skip_light_sleep_lock); for (int i = 0; i < PERIPH_SKIP_LIGHT_SLEEP_NO; i++) { if (s_periph_skip_light_sleep_cb[i] == cb) { + _lock_release(&s_skip_light_sleep_lock); return ESP_OK; } else if (s_periph_skip_light_sleep_cb[i] == NULL) { s_periph_skip_light_sleep_cb[i] = cb; + _lock_release(&s_skip_light_sleep_lock); return ESP_OK; } } + _lock_release(&s_skip_light_sleep_lock); return ESP_ERR_NO_MEM; } esp_err_t esp_pm_unregister_skip_light_sleep_callback(skip_light_sleep_cb_t cb) { + _lock_acquire(&s_skip_light_sleep_lock); for (int i = 0; i < PERIPH_SKIP_LIGHT_SLEEP_NO; i++) { if (s_periph_skip_light_sleep_cb[i] == cb) { s_periph_skip_light_sleep_cb[i] = NULL; + _lock_release(&s_skip_light_sleep_lock); return ESP_OK; } } + _lock_release(&s_skip_light_sleep_lock); return ESP_ERR_INVALID_STATE; } diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index acb18626ef..fc7ae119b0 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -629,15 +629,23 @@ void esp_wifi_set_keep_alive_time(uint32_t keep_alive_time); void esp_wifi_beacon_monitor_configure(wifi_beacon_monitor_config_t *config); /** - * @brief Require WiFi to enable or disable Advanced DTIM sleep function + * @brief Set modem state mode to require WiFi to enable or disable Advanced DTIM sleep function * - * @param light_sleep_enable: true for light sleep mode is enabled, false for light sleep mode is disabled. - * @param modem_state_enable: true for require WiFi to enable Advanced DTIM sleep function, + * @param require_modem_state: true for require WiFi to enable Advanced DTIM sleep function, * false for require WiFi to disable Advanced DTIM sleep function. * @return * - ESP_OK: succeed */ -void esp_wifi_internal_mac_sleep_configure(bool light_sleep_enable, bool modem_state_enable); +void esp_wifi_internal_modem_state_configure(bool require_modem_state); + +/** + * @brief Set light sleep mode to require WiFi to enable or disable Advanced DTIM sleep function + * + * @param light_sleep_enable: true for light sleep mode is enabled, false for light sleep mode is disabled. + * @return + * - ESP_OK: succeed + */ +void esp_wifi_internal_light_sleep_configure(bool light_sleep_enable); /** * @brief Start Publishing a service in the NAN cluster diff --git a/components/esp_wifi/include/esp_wifi.h b/components/esp_wifi/include/esp_wifi.h index 3df8585aed..4a233406e5 100644 --- a/components/esp_wifi/include/esp_wifi.h +++ b/components/esp_wifi/include/esp_wifi.h @@ -1271,6 +1271,32 @@ esp_err_t esp_wifi_config_11b_rate(wifi_interface_t ifx, bool disable); */ esp_err_t esp_wifi_connectionless_module_set_wake_interval(uint16_t wake_interval); +/** + * @brief Request extra reference of Wi-Fi radio. + * Wi-Fi keep active state(RF opened) to be able to receive packets. + * + * @attention Please pair the use of `esp_wifi_force_wakeup_acquire` with `esp_wifi_force_wakeup_release`. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start + */ +esp_err_t esp_wifi_force_wakeup_acquire(void); + +/** + * @brief Release extra reference of Wi-Fi radio. + * Wi-Fi go to sleep state(RF closed) if no more use of radio. + * + * @attention Please pair the use of `esp_wifi_force_wakeup_acquire` with `esp_wifi_force_wakeup_release`. + * + * @return + * - ESP_OK: succeed + * - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init + * - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start + */ +esp_err_t esp_wifi_force_wakeup_release(void); + /** * @brief configure country * diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index b74ee01606..d5352da6c4 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit b74ee0160632978f0e36763f55be0ea6ee18f0c8 +Subproject commit d5352da6c4f6e5d460a8f5af957b4e47420e7782 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index e67069a6a5..4473cfc438 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -167,6 +167,10 @@ esp_err_t esp_wifi_deinit(void) #if CONFIG_MAC_BB_PD esp_wifi_internal_set_mac_sleep(false); esp_mac_bb_pd_mem_deinit(); +#endif +#if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + esp_wifi_internal_modem_state_configure(false); + esp_pm_unregister_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep); #endif esp_phy_modem_deinit(); @@ -231,12 +235,12 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) #endif #if CONFIG_ESP_WIFI_SLP_IRAM_OPT - esp_pm_register_light_sleep_default_params_config_callback(esp_wifi_internal_update_light_sleep_default_params); - int min_freq_mhz = esp_pm_impl_get_cpu_freq(PM_MODE_LIGHT_SLEEP); int max_freq_mhz = esp_pm_impl_get_cpu_freq(PM_MODE_CPU_MAX); esp_wifi_internal_update_light_sleep_default_params(min_freq_mhz, max_freq_mhz); + esp_pm_register_light_sleep_default_params_config_callback(esp_wifi_internal_update_light_sleep_default_params); + uint32_t sleep_delay_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME * 1000; esp_wifi_set_sleep_delay_time(sleep_delay_us); @@ -291,6 +295,12 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) esp_wifi_internal_set_mac_sleep(true); #endif esp_phy_modem_init(); +#if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP + if (sleep_modem_wifi_modem_state_enabled()) { + esp_pm_register_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep); + esp_wifi_internal_modem_state_configure(true); /* require WiFi to enable automatically receives the beacon */ + } +#endif #if CONFIG_IDF_TARGET_ESP32 s_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time; #endif