From 9b7454de0c171a7f94dd8f42a5453ef6c75370e0 Mon Sep 17 00:00:00 2001 From: island Date: Fri, 10 Nov 2017 10:54:50 +0800 Subject: [PATCH 1/2] support wifi&bt coexist (v0.9.1) 1. refactor wifi modem sleep 2. refactor wifi and bt phy enable/diable coexistence 3. support wifi&bt coexist (v0.9.1) 3. add coex pause resume 4. fix bt library interrupt reaction slowly 5. make a2dp more smooth when coex 6. add coexist preference option 7. Make CI do not check libcoexist.a printf/ets_printf 8. disable Wifi RX AMPDU when software coexistence enable && update wifi lib 9. bluetooth call modem sleep api --- .gitlab-ci.yml | 4 +- components/bt/bt.c | 15 +- components/bt/lib | 2 +- components/esp32/Kconfig | 38 ++- components/esp32/include/esp_coexist.h | 66 +++- components/esp32/include/esp_phy_init.h | 65 +++- components/esp32/include/esp_wifi_types.h | 6 +- components/esp32/lib | 2 +- components/esp32/phy_init.c | 302 +++++++++++++++--- docs/en/api-guides/wifi.rst | 6 +- .../wifi/power_save/main/Kconfig.projbuild | 14 +- examples/wifi/power_save/main/power_save.c | 9 +- 12 files changed, 460 insertions(+), 69 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c3e188bdc..27e9e0bbc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -98,8 +98,8 @@ build_template_app: - make all V=1 # Check if there are any stray printf/ets_printf references in WiFi libs - cd ../components/esp32/lib - - test $(xtensa-esp32-elf-nm *.a | grep -w printf | wc -l) -eq 0 - - test $(xtensa-esp32-elf-nm *.a | grep -w ets_printf | wc -l) -eq 0 + - test $(ls *.a|awk '{if ($1 != "libcoexist.a") print $1}' | xargs xtensa-esp32-elf-nm | grep -w printf | wc -l) -eq 0 + - test $(ls *.a|awk '{if ($1 != "libcoexist.a") print $1}' | xargs xtensa-esp32-elf-nm | grep -w ets_printf | wc -l) -eq 0 .build_template: &build_template diff --git a/components/bt/bt.c b/components/bt/bt.c index 8a42a7124..0d848e214 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -540,7 +540,13 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) esp_pm_lock_acquire(s_pm_lock); #endif - esp_phy_load_cal_and_init(); + esp_phy_load_cal_and_init(PHY_BT_MODULE); + esp_modem_sleep_register(MODEM_BLE_MODULE); + + /* TODO: Classic BT should be registered once it supports + * modem sleep */ + + esp_modem_sleep_exit(MODEM_BLE_MODULE); if (btdm_bb_init_flag == false) { btdm_bb_init_flag = true; @@ -549,6 +555,8 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) ret = btdm_controller_enable(mode); if (ret) { + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_phy_rf_deinit(PHY_BT_MODULE); return ESP_ERR_INVALID_STATE; } @@ -571,7 +579,10 @@ esp_err_t esp_bt_controller_disable(void) } if (ret == ESP_BT_MODE_IDLE) { - esp_phy_rf_deinit(); + /* TODO: Need to de-register classic BT once it supports + * modem sleep */ + esp_modem_sleep_deregister(MODEM_BLE_MODULE); + esp_phy_rf_deinit(PHY_BT_MODULE); btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; } diff --git a/components/bt/lib b/components/bt/lib index b76cf6aa3..9a93239bc 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit b76cf6aa307acca2bf3634f2534c84b89f60a054 +Subproject commit 9a93239bc8f54bc5434e8a3dec98e2a8b6b9454a diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index af62a206e..3c94b0e95 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -822,12 +822,40 @@ menu Wi-Fi config SW_COEXIST_ENABLE bool "Software controls WiFi/Bluetooth coexistence" depends on BT_ENABLED - default n + default y help If enabled, WiFi & Bluetooth coexistence is controlled by software rather than hardware. Recommended for heavy traffic scenarios. Both coexistence configuration options are automatically managed, no user intervention is required. +choice SW_COEXIST_PREFERENCE + prompt "WiFi/Bluetooth coexistence performance preference" + depends on SW_COEXIST_ENABLE + default SW_COEXIST_PREFERENCE_BALANCE + help + Choose Bluetooth/WiFi/Balance for different preference. + If choose WiFi, it will make WiFi performance better. Such, keep WiFi Audio more smooth. + If choose Bluetooth, it will make Bluetooth performance better. Such, keep Bluetooth(A2DP) Audio more smooth. + If choose Balance, the performance of WiFi and bluetooth will be balance. It's default. + Except config preference in menuconfig, you can also call esp_coex_preference_set() dynamically. + +config SW_COEXIST_PREFERENCE_WIFI + bool "WiFi" + +config SW_COEXIST_PREFERENCE_BT + bool "Bluetooth(include BR/EDR and BLE)" + +config SW_COEXIST_PREFERENCE_BALANCE + bool "Balance" + +endchoice + +config SW_COEXIST_PREFERENCE_VALUE + int + depends on SW_COEXIST_ENABLE + default 0 if SW_COEXIST_PREFERENCE_WIFI + default 1 if SW_COEXIST_PREFERENCE_BT + default 2 if SW_COEXIST_PREFERENCE_BALANCE config ESP32_WIFI_STATIC_RX_BUFFER_NUM int "Max number of WiFi static RX buffers" @@ -919,27 +947,33 @@ config ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM config ESP32_WIFI_AMPDU_TX_ENABLED bool "WiFi AMPDU TX" + default y if SW_COEXIST_ENABLE default y help Select this option to enable AMPDU TX feature + Suggest enable it when SW_COEXIST_ENABLE is defined. config ESP32_WIFI_TX_BA_WIN int "WiFi AMPDU TX BA window size" depends on ESP32_WIFI_AMPDU_TX_ENABLED range 2 32 + default 2 if SW_COEXIST_ENABLE default 6 help Set the size of WiFi Block Ack TX window. Generally a bigger value means higher throughput but more memory. Most of time we should NOT change the default value unless special reason, e.g. test the maximum UDP TX throughput with iperf etc. For iperf test in shieldbox, the recommended - value is 9~12. + value is 9~12. If SW_COEXIST_ENABLE is defined, suggest value is 2. config ESP32_WIFI_AMPDU_RX_ENABLED bool "WiFi AMPDU RX" + depends on !SW_COEXIST_ENABLE + default y default y help Select this option to enable AMPDU RX feature + Suggest disable this option when SW_COEXIST_ENABLE is enabled. It can improve WiFi RX performance normally. config ESP32_WIFI_RX_BA_WIN int "WiFi AMPDU RX BA window size" diff --git a/components/esp32/include/esp_coexist.h b/components/esp32/include/esp_coexist.h index 872b5e5ab..342652a19 100644 --- a/components/esp32/include/esp_coexist.h +++ b/components/esp32/include/esp_coexist.h @@ -18,8 +18,16 @@ extern "C" { #endif +typedef enum { + COEX_PREFER_WIFI = 0, + COEX_PREFER_BT, + COEX_PREFER_BALANCE, + COEX_PREFER_NUM, +} coex_prefer_t; + /** * @brief Init software coexist + * extern function for internal use. * * @return Init ok or failed. */ @@ -27,24 +35,62 @@ esp_err_t coex_init(void); /** * @brief De-init software coexist + * extern function for internal use. */ void coex_deinit(void); /** - * @brief Get software coexist enable or not - * - * @return software coexist enable status. + * @brief Pause software coexist + * extern function for internal use. */ -bool coexist_get_enable(void); +void coex_pause(void); /** - * @brief Set software coexist enable or not - * - * @param enable software coexist or disable it - * - * @return Void. + * @brief Resume software coexist + * extern function for internal use. */ -void coexist_set_enable(bool enable); +void coex_resume(void); + +/** + * @brief Get software coexist version string + * extern function for internal use. + * @return : version string + */ +const char *coex_version_get(void); + +/** + * @brief Coexist performance preference set from libbt.a + * extern function for internal use. + * + * @param prefer : the prefer enumeration value + * @return : ESP_OK - success, other - failed + */ +esp_err_t coex_preference_set(coex_prefer_t prefer); + +/** + * @brief Get software coexist version string + * + * @return : version string + */ +static inline const char *esp_coex_version_get(void) +{ + return coex_version_get(); +} + +/** + * @brief Set coexist preference of performance + * For example, if prefer to bluetooth, then it will make A2DP(play audio via classic bt) + * more smooth while wifi is runnning something. + * If prefer to wifi, it will do similar things as prefer to bluetooth. + * Default, it prefer to balance. + * + * @param prefer : the prefer enumeration value + * @return : ESP_OK - success, other - failed + */ +static inline esp_err_t esp_coex_preference_set(coex_prefer_t prefer) +{ + return coex_preference_set(prefer); +} #ifdef __cplusplus } diff --git a/components/esp32/include/esp_phy_init.h b/components/esp32/include/esp_phy_init.h index 1184c4e8d..75cb8fb58 100644 --- a/components/esp32/include/esp_phy_init.h +++ b/components/esp32/include/esp_phy_init.h @@ -46,6 +46,43 @@ typedef enum { PHY_RF_CAL_FULL = 0x00000002 /*!< Do full RF calibration. Produces best results, but also consumes a lot of time and current. Suggested to be used once. */ } esp_phy_calibration_mode_t; + +/** + * @brief Modules for modem sleep + */ +typedef enum{ + MODEM_BLE_MODULE, //!< BLE controller used + MODEM_CLASSIC_BT_MODULE, //!< Classic BT controller used + MODEM_WIFI_STATION_MODULE, //!< Wi-Fi Station used + MODEM_WIFI_SOFTAP_MODULE, //!< Wi-Fi SoftAP used + MODEM_WIFI_SNIFFER_MODULE, //!< Wi-Fi Sniffer used + MODEM_USER_MODULE, //!< User used + MODEM_MODULE_COUNT //!< Number of items +}modem_sleep_module_t; + +/** + * @brief Module WIFI mask for medem sleep + */ +#define MODEM_BT_MASK ((1<= 0)); + /* 3 modules may call phy_init: Wi-Fi, BT, Modem Sleep */ + if (module >= PHY_MODULE_COUNT){ + ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \ + module count(%d)", __func__, module, PHY_MODULE_COUNT); + return ESP_ERR_INVALID_ARG; + } _lock_acquire(&s_phy_rf_init_lock); - if (s_phy_rf_init_count == 0) { - // Enable WiFi/BT common peripheral clock - periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE); - ESP_LOGV(TAG, "register_chipv7_phy, init_data=%p, cal_data=%p, mode=%d", - init_data, calibration_data, mode); - phy_set_wifi_mode_only(0); - if (calibration_data != NULL) { - uint8_t mac[6]; - esp_efuse_mac_get_default(mac); - memcpy(&calibration_data->opaque[4], mac, 6); + uint32_t s_module_phy_rf_init_old = s_module_phy_rf_init; + bool is_wifi_or_bt_enabled = !!(s_module_phy_rf_init_old & (BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE))); + esp_err_t status = ESP_OK; + s_module_phy_rf_init |= BIT(module); + + if ((is_wifi_or_bt_enabled == false) && (module == PHY_MODEM_MODULE)){ + status = ESP_FAIL; + } + else if (s_is_phy_rf_en == true) { + } + else { + /* If Wi-Fi, BT all disabled, modem sleep should not take effect; + * If either Wi-Fi or BT is enabled, should allow modem sleep requires + * to enter sleep; + * If Wi-Fi, BT co-exist, it is disallowed that only one module + * support modem sleep, E,g. BT support modem sleep but Wi-Fi not + * support modem sleep; + */ + if (is_wifi_or_bt_enabled == false){ + if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){ + s_is_phy_rf_en = true; + } + } + else { + if (module == PHY_MODEM_MODULE){ + s_is_phy_rf_en = true; + } + else if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){ + /* New module (BT or Wi-Fi) can init RF according to modem_sleep_exit */ + } + } + if (s_is_phy_rf_en == true){ + // Enable WiFi/BT common peripheral clock + periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE); + phy_set_wifi_mode_only(0); + register_chipv7_phy(init_data, calibration_data, mode); + coex_bt_high_prio(); } - register_chipv7_phy(init_data, calibration_data, mode); - coex_bt_high_prio(); - } else { -#if CONFIG_SW_COEXIST_ENABLE - coex_init(); -#endif } - s_phy_rf_init_count++; + +#if CONFIG_SW_COEXIST_ENABLE + if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){ + uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE); + if ((s_module_phy_rf_init & phy_bt_wifi_mask) == phy_bt_wifi_mask) { //both wifi & bt enabled + coex_init(); + coex_preference_set(CONFIG_SW_COEXIST_PREFERENCE_VALUE); + coex_resume(); + } + } +#endif + _lock_release(&s_phy_rf_init_lock); - return ESP_OK; + return status; } -esp_err_t esp_phy_rf_deinit(void) +esp_err_t esp_phy_rf_deinit(phy_rf_module_t module) { - assert((s_phy_rf_init_count <= 2) && (s_phy_rf_init_count >= 1)); + /* 3 modules may call phy_init: Wi-Fi, BT, Modem Sleep */ + if (module >= PHY_MODULE_COUNT){ + ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \ + module count(%d)", __func__, module, PHY_MODULE_COUNT); + return ESP_ERR_INVALID_ARG; + } _lock_acquire(&s_phy_rf_init_lock); - if (s_phy_rf_init_count == 1) { - // Disable PHY and RF. - phy_close_rf(); - // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG - periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE); - } else { + uint32_t s_module_phy_rf_init_old = s_module_phy_rf_init; + uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE); + bool is_wifi_or_bt_enabled = !!(s_module_phy_rf_init_old & phy_bt_wifi_mask); + bool is_both_wifi_bt_enabled = ((s_module_phy_rf_init_old & phy_bt_wifi_mask) == phy_bt_wifi_mask); + s_module_phy_rf_init &= ~BIT(module); + esp_err_t status = ESP_OK; + #if CONFIG_SW_COEXIST_ENABLE - coex_deinit(); -#endif + if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){ + if (is_both_wifi_bt_enabled == true) { + coex_deinit(); + } } - s_phy_rf_init_count--; +#endif + + if ((is_wifi_or_bt_enabled == false) && (module == PHY_MODEM_MODULE)){ + /* Modem sleep should not take effect in this case */ + status = ESP_FAIL; + } + else if (s_is_phy_rf_en == false) { + //do nothing + } + else { + if (is_wifi_or_bt_enabled == false){ + if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){ + s_is_phy_rf_en = false; + ESP_LOGE(TAG, "%s, RF should not be in enabled state if both Wi-Fi and BT are disabled", __func__); + } + } + else { + if (module == PHY_MODEM_MODULE){ + s_is_phy_rf_en = false; + } + else if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){ + s_is_phy_rf_en = is_both_wifi_bt_enabled ? true : false; + } + } + + if (s_is_phy_rf_en == false) { + gpio_set_level(15, 0); //G1, 15 + // Disable PHY and RF. + phy_close_rf(); + // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG + periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE); + } + } + _lock_release(&s_phy_rf_init_lock); + return status; +} + + + +esp_err_t esp_modem_sleep_enter(modem_sleep_module_t module) +{ +#if CONFIG_SW_COEXIST_ENABLE + uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE); +#endif + + if (module >= MODEM_MODULE_COUNT){ + ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \ + module count(%d)", __func__, module, MODEM_MODULE_COUNT); + return ESP_ERR_INVALID_ARG; + } + else if (!(s_modem_sleep_module_register & BIT(module))){ + ESP_LOGW(TAG, "%s, module (%d) has not been registered", __func__, module); + return ESP_ERR_INVALID_ARG; + } + else { + _lock_acquire(&s_modem_sleep_lock); + s_modem_sleep_module_enter |= BIT(module); +#if CONFIG_SW_COEXIST_ENABLE + _lock_acquire(&s_phy_rf_init_lock); + if (((s_module_phy_rf_init & phy_bt_wifi_mask) == phy_bt_wifi_mask) //both wifi & bt enabled + && (s_modem_sleep_module_enter & (MODEM_BT_MASK | MODEM_WIFI_MASK)) != 0){ + coex_pause(); + } + _lock_release(&s_phy_rf_init_lock); +#endif + if (!s_is_modem_sleep_en && (s_modem_sleep_module_enter == s_modem_sleep_module_register)){ + esp_err_t status = esp_phy_rf_deinit(PHY_MODEM_MODULE); + if (status == ESP_OK){ + s_is_modem_sleep_en = true; + } + } + _lock_release(&s_modem_sleep_lock); + return ESP_OK; + } +} + +esp_err_t esp_modem_sleep_exit(modem_sleep_module_t module) +{ +#if CONFIG_SW_COEXIST_ENABLE + uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE); +#endif + + if (module >= MODEM_MODULE_COUNT){ + ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \ + module count(%d)", __func__, module, MODEM_MODULE_COUNT); + return ESP_ERR_INVALID_ARG; + } + else if (!(s_modem_sleep_module_register & BIT(module))){ + ESP_LOGW(TAG, "%s, module (%d) has not been registered", __func__, module); + return ESP_ERR_INVALID_ARG; + } + else { + _lock_acquire(&s_modem_sleep_lock); + s_modem_sleep_module_enter &= ~BIT(module); + if (s_is_modem_sleep_en){ + esp_err_t status = esp_phy_rf_init(NULL,PHY_RF_CAL_NONE,NULL, PHY_MODEM_MODULE); + if (status == ESP_OK){ + s_is_modem_sleep_en = false; + } + } +#if CONFIG_SW_COEXIST_ENABLE + _lock_acquire(&s_phy_rf_init_lock); + if (((s_module_phy_rf_init & phy_bt_wifi_mask) == phy_bt_wifi_mask) //both wifi & bt enabled + && (s_modem_sleep_module_enter & (MODEM_BT_MASK | MODEM_WIFI_MASK)) == 0){ + coex_resume(); + } + _lock_release(&s_phy_rf_init_lock); +#endif + _lock_release(&s_modem_sleep_lock); + return ESP_OK; + } return ESP_OK; } +esp_err_t esp_modem_sleep_register(modem_sleep_module_t module) +{ + if (module >= MODEM_MODULE_COUNT){ + ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \ + module count(%d)", __func__, module, MODEM_MODULE_COUNT); + return ESP_ERR_INVALID_ARG; + } + else if (s_modem_sleep_module_register & BIT(module)){ + ESP_LOGI(TAG, "%s, multiple registration of module (%d)", __func__, module); + return ESP_OK; + } + else{ + _lock_acquire(&s_modem_sleep_lock); + s_modem_sleep_module_register |= BIT(module); + /* The module is set to enter modem sleep by default, otherwise will prevent + * other modules from entering sleep mode if this module never call enter sleep function + * in the future */ + s_modem_sleep_module_enter |= BIT(module); + _lock_release(&s_modem_sleep_lock); + return ESP_OK; + } +} + +esp_err_t esp_modem_sleep_deregister(modem_sleep_module_t module) +{ + if (module >= MODEM_MODULE_COUNT){ + ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \ + module count(%d)", __func__, module, MODEM_MODULE_COUNT); + return ESP_ERR_INVALID_ARG; + } + else if (!(s_modem_sleep_module_register & BIT(module))){ + ESP_LOGI(TAG, "%s, module (%d) has not been registered", __func__, module); + return ESP_OK; + } + else{ + _lock_acquire(&s_modem_sleep_lock); + s_modem_sleep_module_enter &= ~BIT(module); + s_modem_sleep_module_register &= ~BIT(module); + if (s_modem_sleep_module_register == 0){ + s_modem_sleep_module_enter = 0; + /* Once all module are de-registered and current state + * is modem sleep mode, we need to turn off modem sleep + */ + if (s_is_modem_sleep_en == true){ + s_is_modem_sleep_en = false; + esp_phy_rf_init(NULL,PHY_RF_CAL_NONE,NULL, PHY_MODEM_MODULE); + } + } + _lock_release(&s_modem_sleep_lock); + return ESP_OK; + } +} + + // PHY init data handling functions #if CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION #include "esp_partition.h" @@ -274,7 +500,7 @@ static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle, return err; } -void esp_phy_load_cal_and_init(void) +void esp_phy_load_cal_and_init(phy_rf_module_t module) { esp_phy_calibration_data_t* cal_data = (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1); @@ -300,7 +526,7 @@ void esp_phy_load_cal_and_init(void) calibration_mode = PHY_RF_CAL_FULL; } - esp_phy_rf_init(init_data, calibration_mode, cal_data); + esp_phy_rf_init(init_data, calibration_mode, cal_data, module); if (calibration_mode != PHY_RF_CAL_NONE && err != ESP_OK) { err = esp_phy_store_cal_data_to_nvs(cal_data); @@ -308,7 +534,7 @@ void esp_phy_load_cal_and_init(void) err = ESP_OK; } #else - esp_phy_rf_init(init_data, PHY_RF_CAL_FULL, cal_data); + esp_phy_rf_init(NULL, PHY_RF_CAL_FULL, cal_data, module); #endif esp_phy_release_init_data(init_data); diff --git a/docs/en/api-guides/wifi.rst b/docs/en/api-guides/wifi.rst index 226d993bc..61ce2ce6c 100644 --- a/docs/en/api-guides/wifi.rst +++ b/docs/en/api-guides/wifi.rst @@ -1201,9 +1201,11 @@ By default, all Wi-Fi management frames are processed by the Wi-Fi driver, and t ESP32 Wi-Fi Power-saving Mode ----------------------------------- -Currently, ESP32 Wi-Fi supports the Modem-sleep mode which refers to WMM (Wi-Fi Multi Media) power-saving mode in the IEEE 802.11 protocol. If the Modem-sleep mode is enabled and the Wi-Fi enters a sleep state, then, RF, PHY and BB are turned off in order to reduce power consumption. Modem-sleep mode works in Station-only mode and the station must be connected to the AP first. +Currently, ESP32 Wi-Fi supports the Modem-sleep mode which refers to the legacy power-saving mode in the IEEE 802.11 protocol. Modem-sleep mode works in Station-only mode and the station must connect to the AP first. If the Modem-sleep mode is enabled, station will switch between active and doze state periodically. In doze state, RF, PHY and BB are turned off in order to reduce power consumption. Station can keep connection with AP in modem-sleep mode. -Call esp_wifi_set_ps(WIFI_PS_MODEM) to enable Modem-sleep mode after calling esp_wifi_init(). About 10 seconds after the station connects to the AP, Modem-sleep will start. When the station disconnects from the AP, Modem-sleep will stop. +Modem-sleep mode includes minimum and maximum power save modes. In minimum power save mode, station wakes up every DTIM to receive beacon. Broadcast data will not be lost because it is transmitted after DTIM. However, it can not save much more power if DTIM is short for DTIM is determined by AP. In maximum power save mode, station wakes up every listen interval to receive beacon. Broadcast data may be lost because station may be in doze state at DTIM time. If listen interval is longer, more power is saved but broadcast data is more easy to lose. Listen interval can be configured by calling API esp_wifi_set_config() before connecting to AP. + +Call esp_wifi_set_ps(WIFI_PS_MIN_MODEM) to enable Modem-sleep minimum power save mode or esp_wifi_set_ps(WIFI_PS_MAX_MODEM) to enable Modem-sleep maximum power save mode after calling esp_wifi_init(). When station connects to AP, Modem-sleep will start. When station disconnects from AP, Modem-sleep will stop. ESP32 Wi-Fi Connect Crypto ----------------------------------- diff --git a/examples/wifi/power_save/main/Kconfig.projbuild b/examples/wifi/power_save/main/Kconfig.projbuild index 70c87c86b..2a436fcd0 100644 --- a/examples/wifi/power_save/main/Kconfig.projbuild +++ b/examples/wifi/power_save/main/Kconfig.projbuild @@ -11,17 +11,25 @@ config WIFI_PASSWORD default "mypassword" help WiFi password (WPA or WPA2) for the example to use. + +config WIFI_LISTEN_INTERVAL + int "WiFi listen interval" + default 3 + help + WiFi listen interval for station to receive beacon from AP. choice POWER_SAVE_MODE prompt "power save mode" - default POWER_SAVE_MODEM + default POWER_SAVE_MIN_MODEM help Power save mode for the esp32 to use. config POWER_SAVE_NONE bool "none" -config POWER_SAVE_MODEM - bool "modem" +config POWER_SAVE_MIN_MODEM + bool "minimum modem" +config POWER_SAVE_MAX_MODEM + bool "maximum modem" endchoice endmenu diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index f1d665fb9..507994b2c 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -24,8 +24,12 @@ #define DEFAULT_SSID CONFIG_WIFI_SSID #define DEFAULT_PWD CONFIG_WIFI_PASSWORD -#if CONFIG_POWER_SAVE_MODEM -#define DEFAULT_PS_MODE WIFI_PS_MODEM +#define DEFAULT_LISTEN_INTERVAL CONFIG_WIFI_LISTEN_INTERVAL + +#if CONFIG_POWER_SAVE_MIN_MODEM +#define DEFAULT_PS_MODE WIFI_PS_MIN_MODEM +#elif CONFIG_POWER_SAVE_MAX_MODEM +#define DEFAULT_PS_MODE WIFI_PS_MAX_MODEM #elif CONFIG_POWER_SAVE_NONE #define DEFAULT_PS_MODE WIFI_PS_NONE #else @@ -70,6 +74,7 @@ static void wifi_power_save(void) .sta = { .ssid = DEFAULT_SSID, .password = DEFAULT_PWD, + .listen_interval = DEFAULT_LISTEN_INTERVAL, }, }; ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); From 3b3ad875c4ab2b00c6a90219f97b4359278524e0 Mon Sep 17 00:00:00 2001 From: He Yin Ling Date: Mon, 2 Apr 2018 18:13:52 +0800 Subject: [PATCH 2/2] test: use SSC_BLE_WIFI to test NVS cases --- components/idf_test/integration_test/TestCaseAll.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/idf_test/integration_test/TestCaseAll.yml b/components/idf_test/integration_test/TestCaseAll.yml index 9bfd9c580..00fa2457b 100644 --- a/components/idf_test/integration_test/TestCaseAll.yml +++ b/components/idf_test/integration_test/TestCaseAll.yml @@ -8435,7 +8435,7 @@ test cases: version: v1 (2015-8-15) - ID: SYS_NVS_01001 SDK: ESP32_IDF - Test App: SSC_BLE + Test App: SSC_BLE_WIFI auto test: 'Yes' category: Function test point 1: compatiable test