ESP32C3:bluetooth support use main XTAL in light sleep mode

This commit is contained in:
xiongweichao 2021-10-13 15:13:21 +08:00
parent 6e98440ab1
commit d85d927bb0
2 changed files with 54 additions and 17 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 RTC_CLK_SRC_EXT_CRYS depends on 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

@ -72,7 +72,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;
@ -1003,12 +1004,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
@ -1051,33 +1053,41 @@ 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_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
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_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) { if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
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 __attribute__((unused)); bool select_src_ret __attribute__((unused));
bool set_div_ret __attribute__((unused)); bool set_div_ret __attribute__((unused));
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(esp_clk_xtal_freq() * 2 / MHZ); set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() / MHZ);
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);
@ -1103,6 +1113,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;
@ -1173,6 +1184,15 @@ 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
}
} while (0); } while (0);
#if CONFIG_MAC_BB_PD #if CONFIG_MAC_BB_PD
@ -1235,6 +1255,14 @@ 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
}
} while (0); } while (0);
#if CONFIG_MAC_BB_PD #if CONFIG_MAC_BB_PD