From cf9309c8a20c74faa77e020cb21a6ca1ed194116 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Thu, 14 Oct 2021 15:26:01 +0800 Subject: [PATCH] ESP32S3:bluetooth support use main XTAL in light sleep mode --- components/bt/controller/esp32s3/Kconfig.in | 18 +++++--- components/bt/controller/esp32s3/bt.c | 50 ++++++++++++++++----- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/components/bt/controller/esp32s3/Kconfig.in b/components/bt/controller/esp32s3/Kconfig.in index 03eb095249..7e98f5957d 100644 --- a/components/bt/controller/esp32s3/Kconfig.in +++ b/components/bt/controller/esp32s3/Kconfig.in @@ -368,9 +368,9 @@ menu "MODEM SLEEP Options" bool "Main crystal" help 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 - cannot work when light sleep is enabled. Main crystal has a relatively better performance than - other bluetooth low power clock sources. + selected, bluetooth modem sleep can work under Dynamic Frequency Scaling(DFS) enabled, and + bluetooth can work under light sleep enabled. Main crystal has a relatively better performance + than other bluetooth low power clock sources. config BT_CTRL_LPCLK_SEL_EXT_32K_XTAL bool "External 32kHz crystal" depends on ESP32S3_RTC_CLK_SRC_EXT_CRYS @@ -385,9 +385,17 @@ menu "MODEM SLEEP Options" help 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. - - 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 config BT_CTRL_SLEEP_MODE_EFF diff --git a/components/bt/controller/esp32s3/bt.c b/components/bt/controller/esp32s3/bt.c index 995f9aa6c5..aaef25ee4a 100644 --- a/components/bt/controller/esp32s3/bt.c +++ b/components/bt/controller/esp32s3/bt.c @@ -70,7 +70,8 @@ typedef union { 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 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; } btdm_lpcntl_t; @@ -1033,12 +1034,13 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) // set default values for global states or resources s_lp_stat.val = 0; s_lp_cntl.val = 0; + s_lp_cntl.main_xtal_pu = 0; s_wakeup_req_sem = NULL; s_btdm_slp_tmr = NULL; // configure and initialize resources 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 CONFIG_MAC_BB_PD @@ -1081,33 +1083,41 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) // check whether or not EXT_CRYS is working 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.no_light_sleep = 0; } else { - ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock\n" - "light sleep mode will not be able to apply when bluetooth is enabled"); + ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to 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_MAIN_XTAL + ESP_LOGI(BT_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 EXT_CRYS is working + // check whether or not internal 150 kHz RC oscillator is working 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 - ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is " + ESP_LOGW(BT_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."); } else { ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC oscillator not detected."); assert(0); } -#else - s_lp_cntl.no_light_sleep = 1; #endif bool select_src_ret __attribute__((unused)); bool set_div_ret __attribute__((unused)); 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); - 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); 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) { select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL32K); set_div_ret = btdm_lpclk_set_div(0); @@ -1133,6 +1143,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) err = ESP_ERR_NO_MEM; goto error; } + ESP_LOGW(BT_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) { err = ESP_ERR_NO_MEM; @@ -1202,6 +1213,14 @@ error: semphr_delete_wrapper(s_wakeup_req_sem); 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); @@ -1265,6 +1284,15 @@ esp_err_t esp_bt_controller_deinit(void) semphr_delete_wrapper(s_wakeup_req_sem); 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); #if CONFIG_MAC_BB_PD