Merge branch 'bugfix/wifi_bt_use_same_clock_source_v4.3' into 'release/v4.3'

Fix Wi-Fi does not know that Bluetooth has modified the lpclk source (v4.3)

See merge request espressif/esp-idf!15733
This commit is contained in:
Jiang Jiang Jian
2022-08-12 12:52:18 +08:00
11 changed files with 145 additions and 25 deletions

View File

@ -351,9 +351,9 @@ menu "MODEM SLEEP Options"
bool "Main crystal" bool "Main crystal"
help help
Main crystal can be used as low power clock for bluetooth modem sleep. If this option is Main crystal can be used as low power clock for bluetooth modem sleep. If this option is
selected, bluetooth modem sleep can work under Dynamic Frequency Scaling(DFS) enabled, but selected, bluetooth modem sleep can work under Dynamic Frequency Scaling(DFS) enabled, and
cannot work when light sleep is enabled. Main crystal has a relatively better performance than bluetooth can work under light sleep enabled. Main crystal has a relatively better performance
other bluetooth low power clock sources. than other bluetooth low power clock sources.
config BT_CTRL_LPCLK_SEL_EXT_32K_XTAL config BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
bool "External 32kHz crystal" bool "External 32kHz crystal"
depends on ESP32C3_RTC_CLK_SRC_EXT_CRYS depends on ESP32C3_RTC_CLK_SRC_EXT_CRYS
@ -368,9 +368,18 @@ menu "MODEM SLEEP Options"
help help
Internal 150kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is required Internal 150kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is required
in Bluetooth communication, so don't select this option in scenarios such as BLE connection state. in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.
endchoice endchoice
config BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
bool "power up main XTAL during light sleep"
depends on (BT_CTRL_LPCLK_SEL_MAIN_XTAL || BT_CTRL_LPCLK_SEL_EXT_32K_XTAL) && FREERTOS_USE_TICKLESS_IDLE
default n
help
If this option is selected, the main crystal will power up during light sleep when the low power clock
selects an external 32kHz crystal but the external 32kHz crystal does not exist or the low power clock
selects the main crystal.
endmenu endmenu
config BT_CTRL_SLEEP_MODE_EFF config BT_CTRL_SLEEP_MODE_EFF

View File

@ -71,7 +71,8 @@ typedef union {
uint32_t mac_bb_pd : 1; // whether hardware(MAC, BB) force-power-down is required during sleep uint32_t mac_bb_pd : 1; // whether hardware(MAC, BB) force-power-down is required during sleep
uint32_t wakeup_timer_required : 1; // whether system timer is needed uint32_t wakeup_timer_required : 1; // whether system timer is needed
uint32_t no_light_sleep : 1; // do not allow system to enter light sleep after bluetooth is enabled uint32_t no_light_sleep : 1; // do not allow system to enter light sleep after bluetooth is enabled
uint32_t reserved : 26; // reserved uint32_t main_xtal_pu : 1; // power up main XTAL
uint32_t reserved : 25; // reserved
}; };
uint32_t val; uint32_t val;
} btdm_lpcntl_t; } btdm_lpcntl_t;
@ -1006,12 +1007,13 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
// set default values for global states or resources // set default values for global states or resources
s_lp_stat.val = 0; s_lp_stat.val = 0;
s_lp_cntl.val = 0; s_lp_cntl.val = 0;
s_lp_cntl.main_xtal_pu = 0;
s_wakeup_req_sem = NULL; s_wakeup_req_sem = NULL;
s_btdm_slp_tmr = NULL; s_btdm_slp_tmr = NULL;
// configure and initialize resources // configure and initialize resources
s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0; s_lp_cntl.enable = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? 1 : 0;
s_lp_cntl.no_light_sleep = 1; s_lp_cntl.no_light_sleep = 0;
if (s_lp_cntl.enable) { if (s_lp_cntl.enable) {
#if CONFIG_MAC_BB_PD #if CONFIG_MAC_BB_PD
@ -1054,32 +1056,40 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
// check whether or not EXT_CRYS is working // check whether or not EXT_CRYS is working
if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL) { if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL) {
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32 kHz XTAL s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32 kHz XTAL
s_lp_cntl.no_light_sleep = 0;
} else { } else {
ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" ESP_LOGW(BTDM_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock.");
"light sleep mode will not be able to apply when bluetooth is enabled"); #if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
s_lp_cntl.no_light_sleep = 1;
#endif
} }
#elif CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW #elif (CONFIG_BT_CTRL_LPCLK_SEL_MAIN_XTAL)
// check whether or not EXT_CRYS is working ESP_LOGI(BTDM_LOG_TAG, "Bluetooth will use main XTAL as Bluetooth sleep clock.");
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
s_lp_cntl.no_light_sleep = 1;
#endif
#elif (CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW)
// check whether or not internal 150 kHz RC oscillator is working
if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) { if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) {
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // Internal 150 kHz RC oscillator s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // Internal 150 kHz RC oscillator
ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is " ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is "
"required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state."); "required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.");
} else { } else {
ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC oscillator not detected."); ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC oscillator not detected.");
assert(0); assert(0);
} }
#else
s_lp_cntl.no_light_sleep = 1;
#endif #endif
bool select_src_ret, set_div_ret; bool select_src_ret, set_div_ret;
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) { if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
s_lp_cntl.main_xtal_pu = 1;
#endif
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get() * 2); set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get());
assert(select_src_ret && set_div_ret); assert(select_src_ret && set_div_ret);
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); btdm_lpcycle_us = 1 << (btdm_lpcycle_us_frac);
} else if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL32K) { } else if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL32K) {
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K);
set_div_ret = btdm_lpclk_set_div(0); set_div_ret = btdm_lpclk_set_div(0);
@ -1098,6 +1108,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
err = ESP_ERR_INVALID_ARG; err = ESP_ERR_INVALID_ARG;
goto error; goto error;
} }
#if CONFIG_SW_COEXIST_ENABLE
coex_update_lpclk_interval();
#endif
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
if (s_lp_cntl.no_light_sleep) { if (s_lp_cntl.no_light_sleep) {
@ -1105,6 +1118,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
err = ESP_ERR_NO_MEM; err = ESP_ERR_NO_MEM;
goto error; goto error;
} }
ESP_LOGW(BTDM_LOG_TAG, "Light sleep mode will not be able to apply when bluetooth is enabled.");
} }
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) { if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
err = ESP_ERR_NO_MEM; err = ESP_ERR_NO_MEM;
@ -1175,6 +1189,22 @@ error:
s_wakeup_req_sem = NULL; s_wakeup_req_sem = NULL;
} }
} }
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
if (s_lp_cntl.main_xtal_pu) {
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
s_lp_cntl.main_xtal_pu = 0;
}
#endif
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
btdm_lpclk_set_div(0);
#if CONFIG_SW_COEXIST_ENABLE
coex_update_lpclk_interval();
#endif
}
btdm_lpcycle_us = 0;
} while (0); } while (0);
#if CONFIG_MAC_BB_PD #if CONFIG_MAC_BB_PD
@ -1242,6 +1272,21 @@ esp_err_t esp_bt_controller_deinit(void)
semphr_delete_wrapper(s_wakeup_req_sem); semphr_delete_wrapper(s_wakeup_req_sem);
s_wakeup_req_sem = NULL; s_wakeup_req_sem = NULL;
} }
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
if (s_lp_cntl.main_xtal_pu) {
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
s_lp_cntl.main_xtal_pu = 0;
}
#endif
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
btdm_lpclk_set_div(0);
#if CONFIG_SW_COEXIST_ENABLE
coex_update_lpclk_interval();
#endif
}
btdm_lpcycle_us = 0;
} while (0); } while (0);
#if CONFIG_MAC_BB_PD #if CONFIG_MAC_BB_PD
@ -1260,7 +1305,6 @@ esp_err_t esp_bt_controller_deinit(void)
osi_funcs_p = NULL; osi_funcs_p = NULL;
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
btdm_lpcycle_us = 0;
return ESP_OK; return ESP_OK;
} }

View File

@ -1080,7 +1080,6 @@ esp_err_t esp_bt_controller_deinit(void)
osi_funcs_p = NULL; osi_funcs_p = NULL;
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
btdm_lpcycle_us = 0;
return ESP_OK; return ESP_OK;
} }

View File

@ -448,6 +448,26 @@ void esp_bt_controller_wakeup_request(void);
*/ */
int esp_bt_h4tl_eif_io_event_notify(int event); int esp_bt_h4tl_eif_io_event_notify(int event);
<<<<<<< HEAD
=======
/**
* @brief bt Wi-Fi power domain power on
*/
void esp_wifi_bt_power_domain_on(void);
/**
* @brief bt Wi-Fi power domain power off
*/
void esp_wifi_bt_power_domain_off(void);
/**
* @brief Register application callback function to Wi-Fi low power clock module.
*
* @param callback : Wi-Fi set low power clock callback function
*/
void esp_wifi_set_lpclk_register_callback(esp_set_lpclk_source_callback_t callback);
>>>>>>> 8f0c559c03... make bluetooth and wifi use the same low power clock
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -727,8 +727,15 @@ esp_err_t esp_light_sleep_start(void)
// Re-calibrate the RTC Timer clock // Re-calibrate the RTC Timer clock
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS) #if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS) || defined(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS)
uint64_t time_per_us = 1000000ULL; if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_32K_XTAL) {
s_config.rtc_clk_cal_period = (time_per_us << RTC_CLK_CAL_FRACT) / rtc_clk_slow_freq_get_hz(); uint64_t time_per_us = 1000000ULL;
s_config.rtc_clk_cal_period = (time_per_us << RTC_CLK_CAL_FRACT) / rtc_clk_slow_freq_get_hz();
} else {
// If the external 32 kHz XTAL does not exist, use the internal 150 kHz RC oscillator
// as the RTC slow clock source.
s_config.rtc_clk_cal_period = rtc_clk_cal(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);
}
#elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC) #elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC)
s_config.rtc_clk_cal_period = rtc_clk_cal_cycling(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES); s_config.rtc_clk_cal_period = rtc_clk_cal_cycling(RTC_CAL_RTC_MUX, RTC_CLK_SRC_CAL_CYCLES);
esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period); esp_clk_slowclk_cal_set(s_config.rtc_clk_cal_period);

View File

@ -43,6 +43,7 @@
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/syscon_reg.h" #include "soc/syscon_reg.h"
#include "soc/system_reg.h"
#include "phy_init_data.h" #include "phy_init_data.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "nvs.h" #include "nvs.h"
@ -53,6 +54,8 @@
#define TAG "esp_adapter" #define TAG "esp_adapter"
#define MHZ (1000000)
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
extern void wifi_apb80m_request(void); extern void wifi_apb80m_request(void);
extern void wifi_apb80m_release(void); extern void wifi_apb80m_release(void);
@ -440,7 +443,12 @@ static uint32_t esp_clk_slowclk_cal_get_wrapper(void)
/* The bit width of WiFi light sleep clock calibration is 12 while the one of /* The bit width of WiFi light sleep clock calibration is 12 while the one of
* system is 19. It should shift 19 - 12 = 7. * system is 19. It should shift 19 - 12 = 7.
*/ */
return (esp_clk_slowclk_cal_get() >> (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH)); if (GET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_XTAL)) {
uint64_t time_per_us = 1000000ULL;
return (((time_per_us << RTC_CLK_CAL_FRACT) / (MHZ)) >> (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH));
} else {
return (esp_clk_slowclk_cal_get() >> (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH));
}
} }
static void * IRAM_ATTR malloc_internal_wrapper(size_t size) static void * IRAM_ATTR malloc_internal_wrapper(size_t size)

View File

@ -42,6 +42,7 @@
#include "soc/rtc_cntl_reg.h" #include "soc/rtc_cntl_reg.h"
#include "soc/rtc.h" #include "soc/rtc.h"
#include "soc/syscon_reg.h" #include "soc/syscon_reg.h"
#include "soc/system_reg.h"
#include "phy_init_data.h" #include "phy_init_data.h"
#include "driver/periph_ctrl.h" #include "driver/periph_ctrl.h"
#include "nvs.h" #include "nvs.h"
@ -52,6 +53,8 @@
#define TAG "esp_adapter" #define TAG "esp_adapter"
#define MHZ (1000000)
#ifdef CONFIG_PM_ENABLE #ifdef CONFIG_PM_ENABLE
extern void wifi_apb80m_request(void); extern void wifi_apb80m_request(void);
extern void wifi_apb80m_release(void); extern void wifi_apb80m_release(void);
@ -485,7 +488,12 @@ static uint32_t esp_clk_slowclk_cal_get_wrapper(void)
/* The bit width of WiFi light sleep clock calibration is 12 while the one of /* The bit width of WiFi light sleep clock calibration is 12 while the one of
* system is 19. It should shift 19 - 12 = 7. * system is 19. It should shift 19 - 12 = 7.
*/ */
return (esp_clk_slowclk_cal_get() >> (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH)); if (GET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_XTAL)) {
uint64_t time_per_us = 1000000ULL;
return (((time_per_us << RTC_CLK_CAL_FRACT) / (MHZ)) >> (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH));
} else {
return (esp_clk_slowclk_cal_get() >> (RTC_CLK_CAL_FRACT - SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH));
}
} }
static void * IRAM_ATTR malloc_internal_wrapper(size_t size) static void * IRAM_ATTR malloc_internal_wrapper(size_t size)

View File

@ -30,6 +30,7 @@ typedef enum {
} coex_prefer_t; } coex_prefer_t;
typedef void (* coex_func_cb_t)(uint32_t event, int sched_cnt); typedef void (* coex_func_cb_t)(uint32_t event, int sched_cnt);
typedef esp_err_t (* coex_set_lpclk_source_callback_t)(void);
/** /**
* @brief Pre-Init software coexist * @brief Pre-Init software coexist
@ -122,6 +123,18 @@ int coex_wifi_release(uint32_t event);
*/ */
int coex_wifi_channel_set(uint8_t primary, uint8_t secondary); int coex_wifi_channel_set(uint8_t primary, uint8_t secondary);
/**
* @brief Register application callback function to Wi-Fi update low power clock module.
*
* @param callback : Wi-Fi update low power clock callback function
*/
void coex_wifi_register_update_lpclk_callback(coex_set_lpclk_source_callback_t callback);
/**
* @brief Update low power clock interval
*/
void coex_update_lpclk_interval(void);
/** /**
* @brief Get coexistence event duration. * @brief Get coexistence event duration.
* *

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -496,6 +496,15 @@ bool esp_wifi_internal_is_tsf_active(void);
* *
*/ */
void esp_wifi_internal_update_light_sleep_wake_ahead_time(uint32_t); void esp_wifi_internal_update_light_sleep_wake_ahead_time(uint32_t);
/**
* @brief Update WiFi TSF tick interval
*
* @return
* - true: Active
* - false: Not active
*/
esp_err_t esp_wifi_update_tsf_tick_interval(void);
#endif #endif
/** /**

View File

@ -242,6 +242,9 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
return ret; return ret;
} }
esp_sleep_enable_wifi_wakeup(); esp_sleep_enable_wifi_wakeup();
#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE
coex_wifi_register_update_lpclk_callback(esp_wifi_update_tsf_tick_interval);
#endif
#endif #endif
#endif #endif