From 1595973fe83857b1df1fd0c12dfde292e283b9ce Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Tue, 23 Feb 2021 10:17:27 +0800 Subject: [PATCH] light sleep: some default parameters optimization --- components/esp_pm/Kconfig | 4 ++ .../esp_pm/include/esp_private/pm_impl.h | 29 +++++++++++ components/esp_pm/pm_impl.c | 49 ++++++++++++++++++- components/esp_wifi/Kconfig | 18 +++++++ .../esp_wifi/include/esp_private/wifi.h | 26 ++++++++-- components/esp_wifi/lib | 2 +- components/esp_wifi/src/wifi_init.c | 18 ++++++- 7 files changed, 139 insertions(+), 7 deletions(-) diff --git a/components/esp_pm/Kconfig b/components/esp_pm/Kconfig index 1ce8e6af4f..d06018213f 100644 --- a/components/esp_pm/Kconfig +++ b/components/esp_pm/Kconfig @@ -90,4 +90,8 @@ menu "Power Management" Waring: If you want to enable this option on ESP32, you should enable `GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL` at first, otherwise you will not be able to switch pullup/pulldown mode. + config PM_SLP_DEFAULT_PARAMS_OPT + bool + default n + endmenu # "Power Management" diff --git a/components/esp_pm/include/esp_private/pm_impl.h b/components/esp_pm/include/esp_private/pm_impl.h index 50e459fc77..e208d2bcf5 100644 --- a/components/esp_pm/include/esp_private/pm_impl.h +++ b/components/esp_pm/include/esp_private/pm_impl.h @@ -49,6 +49,13 @@ typedef enum { */ pm_mode_t esp_pm_impl_get_mode(esp_pm_lock_type_t type, int arg); +/** + * @brief Get CPU clock frequency by power mode + * @param mode power mode + * @return CPU clock frequency + */ +int esp_pm_impl_get_cpu_freq(pm_mode_t mode); + /** * If profiling is enabled, this data type will be used to store microsecond * timestamps. @@ -172,6 +179,28 @@ esp_err_t esp_pm_register_inform_out_light_sleep_overhead_callback(inform_out_li */ esp_err_t esp_pm_unregister_inform_out_light_sleep_overhead_callback(inform_out_light_sleep_overhead_cb_t cb); +/** + * @brief Callback function type for peripherals to know light sleep default parameters + */ +typedef void (* update_light_sleep_default_params_config_cb_t)(int, int); + +/** + * @brief Register peripherals light sleep default parameters configure callback + * + * This function allows you to register a callback that configure the peripherals + * of default parameters of light sleep + * @param cb function to update default parameters + */ +void esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t cb); + +/** + * @brief Unregister peripherals light sleep default parameters configure Callback + * + * This function allows you to unregister a callback that configure the peripherals + * of default parameters of light sleep + */ +void esp_pm_unregister_light_sleep_default_params_config_callback(void); + #ifdef CONFIG_PM_PROFILING #define WITH_PROFILING #endif diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 2f9173f34b..bc2c4f335a 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -152,7 +152,7 @@ static esp_pm_lock_handle_t s_rtos_lock_handle[portNUM_PROCESSORS]; /* Lookup table of CPU frequency configs to be used in each mode. * Initialized by esp_pm_impl_init and modified by esp_pm_configure. */ -rtc_cpu_freq_config_t s_cpu_freq_by_mode[PM_MODE_COUNT]; +static rtc_cpu_freq_config_t s_cpu_freq_by_mode[PM_MODE_COUNT]; /* Whether automatic light sleep is enabled */ static bool s_light_sleep_en = false; @@ -198,6 +198,9 @@ static const char* TAG = "pm"; static void do_switch(pm_mode_t new_mode); static void leave_idle(void); static void on_freq_update(uint32_t old_ticks_per_us, uint32_t ticks_per_us); +#if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT +static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz); +#endif pm_mode_t esp_pm_impl_get_mode(esp_pm_lock_type_t type, int arg) { @@ -311,6 +314,12 @@ esp_err_t esp_pm_configure(const void* vconfig) } #endif +#if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT + if (config->light_sleep_enable) { + esp_pm_light_sleep_default_params_config(min_freq_mhz, max_freq_mhz); + } +#endif + return ESP_OK; } @@ -662,6 +671,19 @@ void esp_pm_impl_dump_stats(FILE* out) } #endif // WITH_PROFILING +int esp_pm_impl_get_cpu_freq(pm_mode_t mode) +{ + int freq_mhz; + if (mode >= PM_MODE_LIGHT_SLEEP && mode < PM_MODE_COUNT) { + portENTER_CRITICAL(&s_switch_lock); + freq_mhz = s_cpu_freq_by_mode[mode].freq_mhz; + portEXIT_CRITICAL(&s_switch_lock); + } else { + abort(); + } + return freq_mhz; +} + void esp_pm_impl_init(void) { #if defined(CONFIG_ESP_CONSOLE_UART) @@ -818,3 +840,28 @@ void periph_inform_out_light_sleep_overhead(uint32_t out_light_sleep_time) } } } + +static update_light_sleep_default_params_config_cb_t s_light_sleep_default_params_config_cb = NULL; + +void esp_pm_register_light_sleep_default_params_config_callback(update_light_sleep_default_params_config_cb_t cb) +{ + if (s_light_sleep_default_params_config_cb == NULL) { + s_light_sleep_default_params_config_cb = cb; + } +} + +void esp_pm_unregister_light_sleep_default_params_config_callback(void) +{ + if (s_light_sleep_default_params_config_cb) { + s_light_sleep_default_params_config_cb = NULL; + } +} + +#if CONFIG_PM_SLP_DEFAULT_PARAMS_OPT +static void esp_pm_light_sleep_default_params_config(int min_freq_mhz, int max_freq_mhz) +{ + if (s_light_sleep_default_params_config_cb) { + (*s_light_sleep_default_params_config_cb)(min_freq_mhz, max_freq_mhz); + } +} +#endif diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 37386ee7f8..6fd5846eff 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -323,6 +323,8 @@ menu "Wi-Fi" config ESP_WIFI_SLP_IRAM_OPT bool "WiFi SLP IRAM speed optimization" + depends on FREERTOS_USE_TICKLESS_IDLE + select PM_SLP_DEFAULT_PARAMS_OPT 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. @@ -331,6 +333,22 @@ menu "Wi-Fi" 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. + config ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME + int "Minimum active time" + range 8 60 + default 8 + depends on ESP_WIFI_SLP_IRAM_OPT + help + The minimum timeout for waiting to receive data, unit: milliseconds. + + config ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME + int "Maximum keep alive time" + range 10 60 + default 60 + depends on ESP_WIFI_SLP_IRAM_OPT + help + The maximum time that wifi keep alive, unit: seconds. + config ESP_WIFI_FTM_INITIATOR_SUPPORT bool "FTM Initiator support" default y diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index 9ae3003994..3c5a93a106 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -575,10 +575,28 @@ 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); + * @brief Update WIFI light sleep default parameters + * + * @param min_freq_mhz: minimum frequency of DFS + * @param max_freq_mhz: maximum frequency of DFS + */ +void esp_wifi_internal_update_light_sleep_default_params(int min_freq_mhz, int max_freq_mhz); + +/** + * @brief Set the delay time for wifi to enter the sleep state when light sleep + * + * @param return_to_sleep_delay: minimum timeout time for waiting to receive + * data, when no data is received during the timeout period, + * the wifi enters the sleep process. + */ +void esp_wifi_set_sleep_delay_time(uint32_t return_to_sleep_delay); + +/** + * @brief Set wifi keep alive time + * + * @param keep_alive_time: keep alive time + */ +void esp_wifi_set_keep_alive_time(uint32_t keep_alive_time); /** * @brief Set FTM Report log level diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index d21608a505..6cafbeadef 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit d21608a505f8000ba3a7cce696985fb3b4cd8e81 +Subproject commit 6cafbeadef4fa20bd28929c75a96d644b8b0ab15 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 4569277105..73284f5514 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -151,6 +151,9 @@ esp_err_t esp_wifi_deinit(void) 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 +#if CONFIG_ESP_WIFI_SLP_IRAM_OPT + esp_pm_unregister_light_sleep_default_params_config_callback(); +#endif #endif #if CONFIG_MAC_BB_PD esp_unregister_mac_bb_pd_callback(pm_mac_sleep); @@ -186,7 +189,6 @@ static void esp_wifi_config_info(void) #endif #ifdef CONFIG_ESP_WIFI_SLP_IRAM_OPT - esp_wifi_internal_optimize_wake_ahead_time(); ESP_LOGI(TAG, "WiFi SLP IRAM OP enabled"); #endif @@ -222,6 +224,20 @@ 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); + + uint32_t sleep_delay_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME * 1000; + esp_wifi_set_sleep_delay_time(sleep_delay_us); + + uint32_t keep_alive_time_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME * 1000 * 1000; + esp_wifi_set_keep_alive_time(keep_alive_time_us); +#endif + #if SOC_WIFI_HW_TSF esp_err_t ret = esp_pm_register_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active); if (ret != ESP_OK) {