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
This commit is contained in:
island 2017-11-10 10:54:50 +08:00 committed by Tian Hao
parent 8eaae96658
commit 9b7454de0c
12 changed files with 460 additions and 69 deletions

View File

@ -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

View File

@ -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;
}

@ -1 +1 @@
Subproject commit b76cf6aa307acca2bf3634f2534c84b89f60a054
Subproject commit 9a93239bc8f54bc5434e8a3dec98e2a8b6b9454a

View File

@ -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"

View File

@ -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
}

View File

@ -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<<MODEM_BLE_MODULE) | \
(1<<MODEM_CLASSIC_BT_MODULE))
/**
* @brief Module WIFI mask for medem sleep
*/
#define MODEM_WIFI_MASK ((1<<MODEM_WIFI_STATION_MODULE) | \
(1<<MODEM_WIFI_SOFTAP_MODULE) | \
(1<<MODEM_WIFI_SNIFFER_MODULE))
/**
* @brief Modules needing to call phy_rf_init
*/
typedef enum{
PHY_BT_MODULE, //!< Bluetooth used
PHY_WIFI_MODULE, //!< Wi-Fi used
PHY_MODEM_MODULE, //!< Modem sleep used
PHY_MODULE_COUNT //!< Number of items
}phy_rf_module_t;
/**
* @brief Get PHY init data
*
@ -130,8 +167,8 @@ esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_da
* @return ESP_OK on success.
* @return ESP_FAIL on fail.
*/
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data);
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,esp_phy_calibration_mode_t mode,
esp_phy_calibration_data_t* calibration_data, phy_rf_module_t module);
/**
* @brief De-initialize PHY and RF module
@ -142,12 +179,32 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
*
* @return ESP_OK on success.
*/
esp_err_t esp_phy_rf_deinit(void);
esp_err_t esp_phy_rf_deinit(phy_rf_module_t module);
/**
* @brief Load calibration data from NVS and initialize PHY and RF module
*/
void esp_phy_load_cal_and_init(void);
void esp_phy_load_cal_and_init(phy_rf_module_t module);
/**
* @brief Module requires to enter modem sleep
*/
esp_err_t esp_modem_sleep_enter(modem_sleep_module_t module);
/**
* @brief Module requires to exit modem sleep
*/
esp_err_t esp_modem_sleep_exit(modem_sleep_module_t module);
/**
* @brief Register module to make it be able to require to enter/exit modem sleep
*/
esp_err_t esp_modem_sleep_register(modem_sleep_module_t module);
/**
* @brief De-register module from modem sleep list
*/
esp_err_t esp_modem_sleep_deregister(modem_sleep_module_t module);
#ifdef __cplusplus
}

View File

@ -174,8 +174,9 @@ typedef struct {
}wifi_fast_scan_threshold_t;
typedef enum {
WIFI_PS_NONE, /**< No power save */
WIFI_PS_MODEM, /**< Modem power save */
WIFI_PS_NONE, /**< No power save */
WIFI_PS_MIN_MODEM, /**< Minimum modem power save. In this mode, station wakes up to receive beacon every DTIM period */
WIFI_PS_MAX_MODEM, /**< Maximum modem power save. In this mode, station wakes up to receive beacon every listen interval */
} wifi_ps_type_t;
#define WIFI_PROTOCOL_11B 1
@ -208,6 +209,7 @@ typedef struct {
bool bssid_set; /**< whether set MAC address of target AP or not. Generally, station_config.bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.*/
uint8_t bssid[6]; /**< MAC address of target AP*/
uint8_t channel; /**< channel of target AP. Set to 1~13 to scan starting from the specified channel before connecting to AP. If the channel of AP is unknown, set it to 0.*/
uint16_t listen_interval; /**< Listen interval for ESP32 station to receive beacon in maximum power save mode, units: beacon interval */
wifi_sort_method_t sort_method; /**< sort the connect AP in the list by rssi or security mode */
wifi_fast_scan_threshold_t threshold; /**< When scan_method is set to WIFI_FAST_SCAN, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */
} wifi_sta_config_t;

@ -1 +1 @@
Subproject commit c47bfa9e70fda83d969aaf8bee28cb5714eb1b11
Subproject commit 608bf369c66c33c15b0cc198e573e421c7103e1f

View File

@ -39,13 +39,30 @@
#include "esp_coexist.h"
#include "driver/periph_ctrl.h"
static const char* TAG = "phy_init";
/* Count value to indicate if there is peripheral that has initialized PHY and RF */
static int s_phy_rf_init_count = 0;
static _lock_t s_phy_rf_init_lock;
/* Bit mask of modules needing to call phy_rf_init */
static uint32_t s_module_phy_rf_init = 0;
/* Whether modern sleep in turned on */
static volatile bool s_is_phy_rf_en = false;
/* Bit mask of modules needing to enter modem sleep mode */
static uint32_t s_modem_sleep_module_enter = 0;
/* Bit mask of modules which might use RF, system can enter modem
* sleep mode only when all modules registered require to enter
* modem sleep*/
static uint32_t s_modem_sleep_module_register = 0;
/* Whether modern sleep is turned on */
static volatile bool s_is_modem_sleep_en = false;
static _lock_t s_modem_sleep_lock;
uint32_t IRAM_ATTR phy_enter_critical(void)
{
return portENTER_CRITICAL_NESTED();
@ -56,55 +73,264 @@ void IRAM_ATTR phy_exit_critical(uint32_t level)
portEXIT_CRITICAL_NESTED(level);
}
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,
esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data)
esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibration_mode_t mode,
esp_phy_calibration_data_t* calibration_data, phy_rf_module_t module)
{
assert((s_phy_rf_init_count <= 1) && (s_phy_rf_init_count >= 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);

View File

@ -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
-----------------------------------

View File

@ -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

View File

@ -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));