Explorar o código

Merge branch 'bugfix/esp32c3_light_sleep_default_params_optimize' into 'master'

light sleep: some default parameters optimization

See merge request espressif/esp-idf!12461
Jiang Jiang Jian %!s(int64=4) %!d(string=hai) anos
pai
achega
ae65cffff0

+ 4 - 0
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"

+ 29 - 0
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

+ 48 - 1
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

+ 11 - 1
components/esp_system/sleep_modes.c

@@ -622,8 +622,18 @@ void IRAM_ATTR esp_deep_sleep_start(void)
     // Correct the sleep time
     s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
 
+    uint32_t force_pd_flags = RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO;
+
+#if SOC_PM_SUPPORT_WIFI_PD
+    force_pd_flags |= RTC_SLEEP_PD_WIFI;
+#endif
+
+#if SOC_PM_SUPPORT_BT_PD
+    force_pd_flags |= RTC_SLEEP_PD_BT;
+#endif
+
     // Enter sleep
-    esp_sleep_start(RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | pd_flags);
+    esp_sleep_start(force_pd_flags | pd_flags);
 
     // Because RTC is in a slower clock domain than the CPU, it
     // can take several CPU cycles for the sleep mode to start.

+ 18 - 0
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

+ 22 - 4
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

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit d21608a505f8000ba3a7cce696985fb3b4cd8e81
+Subproject commit 6cafbeadef4fa20bd28929c75a96d644b8b0ab15

+ 17 - 1
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) {

+ 4 - 0
components/soc/esp32c3/include/soc/soc_caps.h

@@ -146,3 +146,7 @@
 #define SOC_PM_SUPPORT_BT_WAKEUP        (1)
 
 #define SOC_PM_SUPPORT_CPU_PD           (1)
+
+#define SOC_PM_SUPPORT_WIFI_PD          (1)
+
+#define SOC_PM_SUPPORT_BT_PD            (1)

+ 2 - 0
components/soc/esp32s2/include/soc/soc_caps.h

@@ -317,5 +317,7 @@
 
 #define SOC_PM_SUPPORT_WIFI_WAKEUP      (1)
 
+#define SOC_PM_SUPPORT_WIFI_PD          (1)
+
 /* ---------------------------- Compatibility ------------------------------- */
 // No contents