diff --git a/components/driver/include/driver/periph_ctrl.h b/components/driver/include/driver/periph_ctrl.h index f7c04da9b2..3c6ff8503c 100644 --- a/components/driver/include/driver/periph_ctrl.h +++ b/components/driver/include/driver/periph_ctrl.h @@ -91,6 +91,25 @@ void wifi_bt_common_module_enable(void); */ void wifi_bt_common_module_disable(void); +/** + * @brief enable wifi module + * + * @note Enable wifi module only. + * + * @return NULL + * + */ +void wifi_module_enable(void); + +/** + * @brief disable wifi module + * + * @note Disable wifi module only. + * + * @return NULL + * + */ +void wifi_module_disable(void); #ifdef __cplusplus } #endif diff --git a/components/driver/periph_ctrl.c b/components/driver/periph_ctrl.c index 5dafad481f..e6fb39913f 100644 --- a/components/driver/periph_ctrl.c +++ b/components/driver/periph_ctrl.c @@ -68,3 +68,13 @@ IRAM_ATTR void wifi_bt_common_module_disable(void) } portEXIT_CRITICAL_SAFE(&periph_spinlock); } + +void wifi_module_enable(void) +{ + periph_ll_wifi_module_enable_clk_clear_rst(); +} + +void wifi_module_disable(void) +{ + periph_ll_wifi_module_disable_clk_set_rst(); +} diff --git a/components/esp32/ld/esp32_fragments.lf b/components/esp32/ld/esp32_fragments.lf index f334beee8a..9e7d77fd25 100644 --- a/components/esp32/ld/esp32_fragments.lf +++ b/components/esp32/ld/esp32_fragments.lf @@ -96,6 +96,18 @@ entries: entries: .phyiram+ +[sections:wifi_slp_iram] +entries: + .wifislpiram+ + +[sections:wifi_or_slp_iram] +entries: + .wifiorslpiram+ + +[sections:wifi_slp_rx_iram] +entries: + .wifislprxiram+ + [scheme:default] entries: if APP_BUILD_USE_FLASH_SECTIONS = y: @@ -127,6 +139,9 @@ entries: iram_coredump -> iram_coredump rtc_coredump -> rtc_coredump rtc_fast_coredump -> rtc_fast_coredump + wifi_slp_iram -> flash_text + wifi_or_slp_iram -> flash_text + wifi_slp_rx_iram -> flash_text [scheme:rtc] entries: @@ -165,3 +180,15 @@ entries: entries: bss -> extern_ram common -> extern_ram + +[scheme:wifi_slp_iram] +entries: + wifi_slp_iram -> iram0_text + +[scheme:wifi_or_slp_iram] +entries: + wifi_or_slp_iram -> iram0_text + +[scheme:wifi_slp_rx_iram] +entries: + wifi_slp_rx_iram -> iram0_text diff --git a/components/esp32c3/ld/esp32c3_fragments.lf b/components/esp32c3/ld/esp32c3_fragments.lf index 2ab27f1091..252f77e3b1 100644 --- a/components/esp32c3/ld/esp32c3_fragments.lf +++ b/components/esp32c3/ld/esp32c3_fragments.lf @@ -76,6 +76,18 @@ entries: entries: .wifirxiram+ +[sections:wifi_slp_iram] +entries: + .wifislpiram+ + +[sections:wifi_or_slp_iram] +entries: + .wifiorslpiram+ + +[sections:wifi_slp_rx_iram] +entries: + .wifislprxiram+ + [scheme:default] entries: if APP_BUILD_USE_FLASH_SECTIONS = y: @@ -101,6 +113,9 @@ entries: iram_coredump -> iram_coredump rtc_coredump -> rtc_coredump rtc_fast_coredump -> rtc_fast_coredump + wifi_slp_iram -> flash_text + wifi_or_slp_iram -> flash_text + wifi_slp_rx_iram -> flash_text [scheme:rtc] entries: @@ -130,3 +145,15 @@ entries: [scheme:wifi_rx_iram] entries: wifi_rx_iram -> iram0_text + +[scheme:wifi_slp_iram] +entries: + wifi_slp_iram -> iram0_text + +[scheme:wifi_or_slp_iram] +entries: + wifi_or_slp_iram -> iram0_text + +[scheme:wifi_slp_rx_iram] +entries: + wifi_slp_rx_iram -> iram0_text diff --git a/components/esp32s2/ld/esp32s2_fragments.lf b/components/esp32s2/ld/esp32s2_fragments.lf index 72b74b63bf..ac231cf123 100644 --- a/components/esp32s2/ld/esp32s2_fragments.lf +++ b/components/esp32s2/ld/esp32s2_fragments.lf @@ -64,6 +64,18 @@ entries: entries: .wifirxiram+ +[sections:wifi_slp_iram] +entries: + .wifislpiram+ + +[sections:wifi_or_slp_iram] +entries: + .wifiorslpiram+ + +[sections:wifi_slp_rx_iram] +entries: + .wifislprxiram+ + [scheme:default] entries: text -> flash_text @@ -82,6 +94,9 @@ entries: dram_coredump -> dram_coredump rtc_coredump -> rtc_coredump rtc_fast_coredump -> rtc_fast_coredump + wifi_slp_iram -> flash_text + wifi_or_slp_iram -> flash_text + wifi_slp_rx_iram -> flash_text [scheme:rtc] entries: @@ -111,3 +126,15 @@ entries: [scheme:wifi_rx_iram] entries: wifi_rx_iram -> iram0_text + +[scheme:wifi_slp_iram] +entries: + wifi_slp_iram -> iram0_text + +[scheme:wifi_or_slp_iram] +entries: + wifi_or_slp_iram -> iram0_text + +[scheme:wifi_slp_rx_iram] +entries: + wifi_slp_rx_iram -> iram0_text diff --git a/components/esp_pm/include/esp_private/pm_impl.h b/components/esp_pm/include/esp_private/pm_impl.h index a2e92a48a0..50e459fc77 100644 --- a/components/esp_pm/include/esp_private/pm_impl.h +++ b/components/esp_pm/include/esp_private/pm_impl.h @@ -112,7 +112,6 @@ void esp_pm_impl_dump_stats(FILE* out); */ void esp_pm_impl_waiti(void); -#if CONFIG_IDF_TARGET_ESP32S2 /** * @brief Callback function type for peripherals to skip light sleep. * @@ -142,7 +141,36 @@ esp_err_t esp_pm_register_skip_light_sleep_callback(skip_light_sleep_cb_t cb); * - ESP_ERR_INVALID_STATE if the given callback hasn't been registered before */ esp_err_t esp_pm_unregister_skip_light_sleep_callback(skip_light_sleep_cb_t cb); -#endif + +/** + * @brief Callback function type for peripherals to know light sleep wakeup overhead. + * + */ +typedef void (* inform_out_light_sleep_overhead_cb_t)(uint32_t); + +/** + * @brief Register informing peripherals light sleep wakeup overhead time callback + * + * This function allows you to register a callback that informs the peripherals of + * the wakeup overhead time of light sleep. + * @param cb function to inform time + * @return + * - ESP_OK on success + * - ESP_ERR_NO_MEM if no more callback slots are available + */ +esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb); + +/** + * @brief Unregister informing peripherals light sleep wakeup overhead time callback + * + * This function allows you to unregister a callback that informs the peripherals of + * the wakeup overhead time of light sleep. + * @param cb function to inform time + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE if the given callback hasn't been registered before + */ +esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb); #ifdef CONFIG_PM_PROFILING #define WITH_PROFILING diff --git a/components/esp_pm/linker.lf b/components/esp_pm/linker.lf index e076a516c6..67c8051b96 100644 --- a/components/esp_pm/linker.lf +++ b/components/esp_pm/linker.lf @@ -4,6 +4,8 @@ entries: if PM_RTOS_IDLE_OPT = y: pm_impl:esp_pm_impl_idle_hook (noflash) pm_impl:esp_pm_impl_waiti (noflash) + if PM_SLP_IRAM_OPT = y && IDF_TARGET_ESP32 = n: + pm_impl:periph_inform_out_light_sleep_overhead (noflash) [mapping:esp_common_pm] archive: libesp_common.a diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index a7f764fc14..81caf32c0c 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -112,12 +112,10 @@ static uint32_t s_ccount_mul; #if CONFIG_FREERTOS_USE_TICKLESS_IDLE -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #define PERIPH_SKIP_LIGHT_SLEEP_NO 1 /* Indicates if light sleep shoule be skipped by peripherals. */ static skip_light_sleep_cb_t s_periph_skip_light_sleep_cb[PERIPH_SKIP_LIGHT_SLEEP_NO]; -#endif /* Indicates if light sleep entry was skipped in vApplicationSleep for given CPU. * This in turn gets used in IDLE hook to decide if `waiti` needs @@ -488,61 +486,8 @@ static void IRAM_ATTR leave_idle(void) } } -void esp_pm_impl_idle_hook(void) -{ - int core_id = xPortGetCoreID(); - uint32_t state = portENTER_CRITICAL_NESTED(); - if (!s_core_idle[core_id]) { - esp_pm_lock_release(s_rtos_lock_handle[core_id]); - s_core_idle[core_id] = true; - } - portEXIT_CRITICAL_NESTED(state); - ESP_PM_TRACE_ENTER(IDLE, core_id); -} - -void IRAM_ATTR esp_pm_impl_isr_hook(void) -{ - int core_id = xPortGetCoreID(); - ESP_PM_TRACE_ENTER(ISR_HOOK, core_id); - /* Prevent higher level interrupts (than the one this function was called from) - * from happening in this section, since they will also call into esp_pm_impl_isr_hook. - */ - uint32_t state = portENTER_CRITICAL_NESTED(); -#if portNUM_PROCESSORS == 2 - if (s_need_update_ccompare[core_id]) { - update_ccompare(); - s_need_update_ccompare[core_id] = false; - } else { - leave_idle(); - } -#else - leave_idle(); -#endif // portNUM_PROCESSORS == 2 - portEXIT_CRITICAL_NESTED(state); - ESP_PM_TRACE_EXIT(ISR_HOOK, core_id); -} - -void esp_pm_impl_waiti(void) -{ -#if CONFIG_FREERTOS_USE_TICKLESS_IDLE - int core_id = xPortGetCoreID(); - if (s_skipped_light_sleep[core_id]) { - asm("waiti 0"); - /* Interrupt took the CPU out of waiti and s_rtos_lock_handle[core_id] - * is now taken. However since we are back to idle task, we can release - * the lock so that vApplicationSleep can attempt to enter light sleep. - */ - esp_pm_impl_idle_hook(); - s_skipped_light_sleep[core_id] = false; - } -#else - asm("waiti 0"); -#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE -} - #if CONFIG_FREERTOS_USE_TICKLESS_IDLE -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 esp_err_t esp_pm_register_skip_light_sleep_callback(skip_light_sleep_cb_t cb) { for (int i = 0; i < PERIPH_SKIP_LIGHT_SLEEP_NO; i++) { @@ -578,7 +523,6 @@ static inline bool IRAM_ATTR periph_should_skip_light_sleep(void) } return false; } -#endif static inline bool IRAM_ATTR should_skip_light_sleep(int core_id) { @@ -589,11 +533,8 @@ static inline bool IRAM_ATTR should_skip_light_sleep(int core_id) return true; } #endif // portNUM_PROCESSORS == 2 -#if CONFIG_IDF_TARGET_ESP32 - if (s_mode != PM_MODE_LIGHT_SLEEP || s_is_switching) { -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + if (s_mode != PM_MODE_LIGHT_SLEEP || s_is_switching || periph_should_skip_light_sleep()) { -#endif s_skipped_light_sleep[core_id] = true; } else { s_skipped_light_sleep[core_id] = false; @@ -743,3 +684,97 @@ void esp_pm_impl_init(void) esp_pm_configure(&cfg); #endif //CONFIG_PM_DFS_INIT_AUTO } + +void esp_pm_impl_idle_hook(void) +{ + int core_id = xPortGetCoreID(); + uint32_t state = portENTER_CRITICAL_NESTED(); + if (!s_core_idle[core_id] +#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE + && !periph_should_skip_light_sleep() +#endif + ) { + esp_pm_lock_release(s_rtos_lock_handle[core_id]); + s_core_idle[core_id] = true; + } + portEXIT_CRITICAL_NESTED(state); + ESP_PM_TRACE_ENTER(IDLE, core_id); +} + +void IRAM_ATTR esp_pm_impl_isr_hook(void) +{ + int core_id = xPortGetCoreID(); + ESP_PM_TRACE_ENTER(ISR_HOOK, core_id); + /* Prevent higher level interrupts (than the one this function was called from) + * from happening in this section, since they will also call into esp_pm_impl_isr_hook. + */ + uint32_t state = portENTER_CRITICAL_NESTED(); +#if portNUM_PROCESSORS == 2 + if (s_need_update_ccompare[core_id]) { + update_ccompare(); + s_need_update_ccompare[core_id] = false; + } else { + leave_idle(); + } +#else + leave_idle(); +#endif // portNUM_PROCESSORS == 2 + portEXIT_CRITICAL_NESTED(state); + ESP_PM_TRACE_EXIT(ISR_HOOK, core_id); +} + +void esp_pm_impl_waiti(void) +{ +#if CONFIG_FREERTOS_USE_TICKLESS_IDLE + int core_id = xPortGetCoreID(); + if (s_skipped_light_sleep[core_id]) { + asm("waiti 0"); + /* Interrupt took the CPU out of waiti and s_rtos_lock_handle[core_id] + * is now taken. However since we are back to idle task, we can release + * the lock so that vApplicationSleep can attempt to enter light sleep. + */ + esp_pm_impl_idle_hook(); + s_skipped_light_sleep[core_id] = false; + } +#else + asm("waiti 0"); +#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE +} + +#define PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO 1 + +/* Inform peripherals of light sleep wakeup overhead time */ +static inform_out_light_sleep_overhead_cb_t s_periph_inform_out_light_sleep_overhead_cb[PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO]; + +esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { + if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { + return ESP_OK; + } else if (s_periph_inform_out_light_sleep_overhead_cb[i] == NULL) { + s_periph_inform_out_light_sleep_overhead_cb[i] = cb; + return ESP_OK; + } + } + return ESP_ERR_NO_MEM; +} + +esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { + if (s_periph_inform_out_light_sleep_overhead_cb[i] == cb) { + s_periph_inform_out_light_sleep_overhead_cb[i] = NULL; + return ESP_OK; + } + } + return ESP_ERR_INVALID_STATE; +} + +void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time) +{ + for (int i = 0; i < PERIPH_INFORM_OUT_LIGHT_SLEEP_OVERHEAD_NO; i++) { + if (s_periph_inform_out_light_sleep_overhead_cb[i]) { + s_periph_inform_out_light_sleep_overhead_cb[i](out_light_sleep_time); + } + } +} diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 267caaa277..b5b030a8c4 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -125,6 +125,8 @@ #define DEEP_SLEEP_WAKEUP_DELAY 0 #endif +extern void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time); + // Minimal amount of time we can sleep for #define LIGHT_SLEEP_MIN_TIME_US 200 @@ -602,6 +604,8 @@ esp_err_t esp_light_sleep_start(void) } #endif //CONFIG_ESP_SYSTEM_PD_FLASH + periph_inform_out_light_sleep_overhead(s_config.sleep_time_adjustment - sleep_time_overhead_in); + rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config(); // Safety net: enable WDT in case exit from light sleep fails diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index f0ab1bb459..e72afb2e09 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -321,6 +321,16 @@ menu "Wi-Fi" PMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details. + config ESP_WIFI_SLP_IRAM_OPT + bool "WiFi SLP IRAM speed optimization" + help + Select this option to place called Wi-Fi library TBTT process and receive beacon functions in IRAM. + Some functions can be put in IRAM either by ESP32_WIFI_IRAM_OPT and ESP32_WIFI_RX_IRAM_OPT, or this one. + If already enabled ESP32_WIFI_IRAM_OPT, the other 7.3KB IRAM memory would be taken by this option. + If already enabled ESP32_WIFI_RX_IRAM_OPT, the other 1.3KB IRAM memory would be taken by this option. + If neither of them are enabled, the other 7.4KB IRAM memory would be taken by this option. + Wi-Fi power-save mode average current would be reduced if this option is enabled. + endmenu # Wi-Fi menu "PHY" diff --git a/components/esp_wifi/esp32/esp_adapter.c b/components/esp_wifi/esp32/esp_adapter.c index 65f0c22b08..c51b59c0a8 100644 --- a/components/esp_wifi/esp32/esp_adapter.c +++ b/components/esp_wifi/esp32/esp_adapter.c @@ -460,12 +460,12 @@ static void wifi_reset_mac_wrapper(void) static void wifi_clock_enable_wrapper(void) { - periph_module_enable(PERIPH_WIFI_MODULE); + wifi_module_enable(); } static void wifi_clock_disable_wrapper(void) { - periph_module_disable(PERIPH_WIFI_MODULE); + wifi_module_disable(); } static int get_time_wrapper(void *t) diff --git a/components/esp_wifi/esp32c3/esp_adapter.c b/components/esp_wifi/esp32c3/esp_adapter.c index 193c15b598..3cbb3e4723 100644 --- a/components/esp_wifi/esp32c3/esp_adapter.c +++ b/components/esp_wifi/esp32c3/esp_adapter.c @@ -422,12 +422,12 @@ static void IRAM_ATTR wifi_rtc_disable_iso_wrapper(void) static void IRAM_ATTR wifi_clock_enable_wrapper(void) { - periph_module_enable(PERIPH_WIFI_MODULE); + wifi_module_enable(); } static void IRAM_ATTR wifi_clock_disable_wrapper(void) { - periph_module_disable(PERIPH_WIFI_MODULE); + wifi_module_disable(); } static int get_time_wrapper(void *t) diff --git a/components/esp_wifi/esp32s2/esp_adapter.c b/components/esp_wifi/esp32s2/esp_adapter.c index 3573eb20c5..24b8b67c8a 100644 --- a/components/esp_wifi/esp32s2/esp_adapter.c +++ b/components/esp_wifi/esp32s2/esp_adapter.c @@ -437,12 +437,12 @@ static void wifi_reset_mac_wrapper(void) static void wifi_clock_enable_wrapper(void) { - periph_module_enable(PERIPH_WIFI_MODULE); + wifi_module_enable(); } static void wifi_clock_disable_wrapper(void) { - periph_module_disable(PERIPH_WIFI_MODULE); + wifi_module_disable(); } static int get_time_wrapper(void *t) diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index d2c8e2972f..4068d21f69 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -467,7 +467,7 @@ esp_err_t esp_wifi_internal_get_negotiated_channel(wifi_interface_t ifx, uint8_t */ esp_err_t esp_wifi_internal_get_negotiated_bandwidth(wifi_interface_t ifx, uint8_t aid, uint8_t *bw); -#if CONFIG_IDF_TARGET_ESP32S2 +#if SOC_WIFI_HW_TSF /** * @brief Check if WiFi TSF is active * @@ -476,6 +476,12 @@ esp_err_t esp_wifi_internal_get_negotiated_bandwidth(wifi_interface_t ifx, uint8 * - false: Not active */ bool esp_wifi_internal_is_tsf_active(void); + +/** + * @brief Update WIFI light sleep wake ahead time + * + */ +void esp_wifi_internal_update_light_sleep_wake_ahead_time(uint32_t); #endif #if CONFIG_MAC_BB_PD @@ -526,6 +532,11 @@ esp_err_t esp_wifi_set_tx_done_cb(wifi_tx_done_cb_t cb); */ esp_err_t esp_wifi_internal_set_spp_amsdu(wifi_interface_t ifidx, bool spp_cap, bool spp_req); +/** + * @brief Apply WiFi sleep optimization parameters + * + */ +void esp_wifi_internal_optimize_wake_ahead_time(void); #ifdef __cplusplus } #endif diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 22a92a009e..ab4eb6bee5 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 22a92a009e4107341665ad307e4dd3c605ae31b3 +Subproject commit ab4eb6bee5c1d7a007ac955ec8100f882a32ecb4 diff --git a/components/esp_wifi/linker.lf b/components/esp_wifi/linker.lf index 8ea33b9818..d955938bce 100644 --- a/components/esp_wifi/linker.lf +++ b/components/esp_wifi/linker.lf @@ -2,6 +2,8 @@ archive: libphy.a entries: * (noflash_data) + if ESP_WIFI_SLP_IRAM_OPT = y && IDF_TARGET_ESP32 = y: + * (phy_iram) [mapping:rtc] archive: librtc.a @@ -17,6 +19,15 @@ entries: if ESP32_WIFI_RX_IRAM_OPT = y: * (wifi_rx_iram) + if ESP_WIFI_SLP_IRAM_OPT = y: + * (wifi_slp_iram) + + if ESP32_WIFI_IRAM_OPT || ESP_WIFI_SLP_IRAM_OPT: + * (wifi_or_slp_iram) + + if ESP32_WIFI_RX_IRAM_OPT || ESP_WIFI_SLP_IRAM_OPT: + * (wifi_slp_rx_iram) + if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y: * (extram_bss) @@ -31,3 +42,40 @@ entries: if ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY = y: * (extram_bss) + + if ESP_WIFI_SLP_IRAM_OPT = y: + * (wifi_slp_iram) + + if ESP32_WIFI_RX_IRAM_OPT || ESP_WIFI_SLP_IRAM_OPT: + * (wifi_slp_rx_iram) + +[mapping:coexist] +archive: libcoexist.a +entries: + if ESP_WIFI_SLP_IRAM_OPT = y: + * (wifi_slp_iram) + +[mapping:esp_wifi] +archive: libesp_wifi.a +entries: + if ESP_WIFI_SLP_IRAM_OPT =y: + esp_adapter:wifi_clock_enable_wrapper (noflash) + esp_adapter:wifi_clock_disable_wrapper (noflash) + phy_init:esp_phy_enable (noflash) + phy_init:esp_phy_disable (noflash) + wifi_init:wifi_apb80m_request (noflash) + wifi_init:wifi_apb80m_release (noflash) + +[mapping:driver_wifi_pm] +archive: libdriver.a +entries: + if ESP_WIFI_SLP_IRAM_OPT =y: + periph_ctrl:wifi_module_enable (noflash) + periph_ctrl:wifi_module_disable (noflash) + +[mapping:esp_timer_wifi_pm] +archive: libesp_timer.a +entries: + if ESP_WIFI_SLP_IRAM_OPT = y && IDF_TARGET_ESP32 = y: + esp_timer:timer_task (noflash) + esp_timer:timer_process_alarm (noflash) diff --git a/components/esp_wifi/src/phy_init.c b/components/esp_wifi/src/phy_init.c index 4de3314eb2..e7afc74986 100644 --- a/components/esp_wifi/src/phy_init.c +++ b/components/esp_wifi/src/phy_init.c @@ -207,7 +207,6 @@ IRAM_ATTR void esp_phy_enable(void) phy_update_wifi_mac_time(false, s_phy_rf_en_ts); #endif esp_phy_common_clock_enable(); - phy_set_wifi_mode_only(0); if (s_is_phy_calibrated == false) { esp_phy_load_cal_and_init(); diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 38c9e3d280..85d74a777c 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -143,6 +143,7 @@ esp_err_t esp_wifi_deinit(void) #if CONFIG_FREERTOS_USE_TICKLESS_IDLE #if SOC_WIFI_HW_TSF esp_pm_unregister_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active); + esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time); #endif #endif @@ -175,6 +176,11 @@ static void esp_wifi_config_info(void) ESP_LOGI(TAG, "WiFi RX IRAM OP enabled"); #endif +#ifdef CONFIG_ESP_WIFI_SLP_IRAM_OPT + esp_wifi_internal_optimize_wake_ahead_time(); + ESP_LOGI(TAG, "WiFi SLP IRAM OP enabled"); +#endif + #ifdef CONFIG_LWIP_IRAM_OPTIMIZATION ESP_LOGI(TAG, "LWIP IRAM OP enabled"); #endif @@ -202,6 +208,11 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) ESP_LOGE(TAG, "Failed to register skip light sleep callback (0x%x)", ret); return ret; } + ret = esp_pm_register_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to register inform light sleep overhead callback (0x%x)", ret); + return ret; + } esp_sleep_enable_wifi_wakeup(); #endif #endif diff --git a/components/hal/esp32/include/hal/clk_gate_ll.h b/components/hal/esp32/include/hal/clk_gate_ll.h index b282955637..d93311dd60 100644 --- a/components/hal/esp32/include/hal/clk_gate_ll.h +++ b/components/hal/esp32/include/hal/clk_gate_ll.h @@ -267,6 +267,18 @@ static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph) DPORT_REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0; } +static inline void periph_ll_wifi_module_enable_clk_clear_rst(void) +{ + DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN_M); + DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} + +static inline void periph_ll_wifi_module_disable_clk_set_rst(void) +{ + DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN_M); + DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/clk_gate_ll.h b/components/hal/esp32c3/include/hal/clk_gate_ll.h index 9a4cace824..f7382650d5 100644 --- a/components/hal/esp32c3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c3/include/hal/clk_gate_ll.h @@ -235,6 +235,18 @@ static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph) return DPORT_REG_GET_BIT(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)) == 0 && DPORT_REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0; } + +static inline void periph_ll_wifi_module_enable_clk_clear_rst(void) +{ + DPORT_SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_EN_M); + DPORT_CLEAR_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); +} + +static inline void periph_ll_wifi_module_disable_clk_set_rst(void) +{ + DPORT_CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_EN_M); + DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); +} #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/clk_gate_ll.h b/components/hal/esp32s2/include/hal/clk_gate_ll.h index 68230eff7e..3d2690649b 100644 --- a/components/hal/esp32s2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32s2/include/hal/clk_gate_ll.h @@ -287,6 +287,17 @@ static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph) DPORT_REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0; } +static inline void periph_ll_wifi_module_enable_clk_clear_rst(void) +{ + DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN_M); + DPORT_CLEAR_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} + +static inline void periph_ll_wifi_module_disable_clk_set_rst(void) +{ + DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN_M); + DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); +} #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/clk_gate_ll.h b/components/hal/esp32s3/include/hal/clk_gate_ll.h index b680dfacc1..c8de2b91e3 100644 --- a/components/hal/esp32s3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32s3/include/hal/clk_gate_ll.h @@ -283,6 +283,17 @@ static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph) DPORT_REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0; } +static inline void periph_ll_wifi_module_enable_clk_clear_rst(void) +{ + DPORT_SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_EN_M); + DPORT_CLEAR_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); +} + +static inline void periph_ll_wifi_module_disable_clk_set_rst(void) +{ + DPORT_CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_EN_M); + DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); +} #ifdef __cplusplus } #endif diff --git a/examples/wifi/power_save/sdkconfig.defaults b/examples/wifi/power_save/sdkconfig.defaults index 42b68979dd..b2a114339b 100644 --- a/examples/wifi/power_save/sdkconfig.defaults +++ b/examples/wifi/power_save/sdkconfig.defaults @@ -12,3 +12,5 @@ CONFIG_PM_RTOS_IDLE_OPT=y # Disable all GPIO at light sleep CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL=y CONFIG_PM_SLP_DISABLE_GPIO=y +# Enable wifi sleep iram optimization +CONFIG_ESP_WIFI_SLP_IRAM_OPT=y