From d85d927bb04a7ec21f7a31f68b947c58ef4ec130 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Wed, 13 Oct 2021 15:13:21 +0800 Subject: [PATCH 1/5] ESP32C3:bluetooth support use main XTAL in light sleep mode --- components/bt/controller/esp32c3/Kconfig.in | 19 ++++++-- components/bt/controller/esp32c3/bt.c | 52 ++++++++++++++++----- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/components/bt/controller/esp32c3/Kconfig.in b/components/bt/controller/esp32c3/Kconfig.in index 13588d6efb..94b31a3d84 100644 --- a/components/bt/controller/esp32c3/Kconfig.in +++ b/components/bt/controller/esp32c3/Kconfig.in @@ -351,9 +351,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 RTC_CLK_SRC_EXT_CRYS @@ -368,9 +368,18 @@ 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/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index b80f9b2a43..8c5a0ac704 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -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 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; @@ -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 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 @@ -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 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.no_light_sleep = 0; } else { - ESP_LOGW(BTDM_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(BTDM_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_RTC_SLOW - // check whether or not EXT_CRYS is working +#elif (CONFIG_BT_CTRL_LPCLK_SEL_MAIN_XTAL) + 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) { 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 " "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."); + ESP_LOGW(BTDM_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(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); 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); @@ -1103,6 +1113,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) err = ESP_ERR_NO_MEM; 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) { err = ESP_ERR_NO_MEM; @@ -1173,6 +1184,15 @@ error: 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 @@ -1235,6 +1255,14 @@ 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 From 1fec2b9529433926400d27e3f899f2423f6c75e0 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Thu, 14 Oct 2021 15:26:01 +0800 Subject: [PATCH 2/5] ESP32S3:bluetooth support use main XTAL in light sleep mode --- components/bt/controller/esp32s3/Kconfig.in | 18 +++++-- components/bt/controller/esp32s3/bt.c | 52 ++++++++++++++++----- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/components/bt/controller/esp32s3/Kconfig.in b/components/bt/controller/esp32s3/Kconfig.in index 328ac378b8..db6cb10e57 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 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 4ede90cc06..a6e6cb73da 100644 --- a/components/bt/controller/esp32s3/bt.c +++ b/components/bt/controller/esp32s3/bt.c @@ -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 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; @@ -1035,12 +1036,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 @@ -1083,33 +1085,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_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { 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_RTC_SLOW - // check whether or not EXT_CRYS is working +#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 internal 150 kHz RC oscillator is working 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 - 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(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); 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); @@ -1135,6 +1145,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; @@ -1204,6 +1215,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); @@ -1267,6 +1286,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 From bb5e7004b9adfcbfd5dafd9236054010c7957d02 Mon Sep 17 00:00:00 2001 From: xiongweichao Date: Wed, 20 Oct 2021 19:32:21 +0800 Subject: [PATCH 3/5] make bluetooth and wifi use the same low power clock --- components/bt/controller/esp32c3/bt.c | 28 +++++++++++++++++- components/bt/controller/esp32s3/bt.c | 29 ++++++++++++++++++- .../bt/include/esp32c3/include/esp_bt.h | 12 ++++++++ .../bt/include/esp32s3/include/esp_bt.h | 12 ++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 8c5a0ac704..ab10fb9c2e 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -395,6 +395,8 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; // wakeup timer static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr; +// set low power clock source callback +static esp_set_lpclk_source_callback_t s_set_lpclk_source_cb = NULL; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock; @@ -925,6 +927,11 @@ static void IRAM_ATTR btdm_mac_bb_power_up_cb(void) } #endif +void esp_wifi_set_lpclk_register_callback(esp_set_lpclk_source_callback_t callback) +{ + s_set_lpclk_source_cb = callback; +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err = ESP_FAIL; @@ -1107,6 +1114,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto error; } + if (s_set_lpclk_source_cb) { + s_set_lpclk_source_cb(); + } + #ifdef CONFIG_PM_ENABLE if (s_lp_cntl.no_light_sleep) { if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { @@ -1192,7 +1203,15 @@ error: s_lp_cntl.main_xtal_pu = 0; } #endif + btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); + btdm_lpclk_set_div(0); + if (s_set_lpclk_source_cb) { + s_set_lpclk_source_cb(); + } } + + btdm_lpcycle_us = 0; + s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD @@ -1262,7 +1281,15 @@ esp_err_t esp_bt_controller_deinit(void) s_lp_cntl.main_xtal_pu = 0; } #endif + btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); + btdm_lpclk_set_div(0); + if (s_set_lpclk_source_cb) { + s_set_lpclk_source_cb(); + } } + + btdm_lpcycle_us = 0; + s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD @@ -1285,7 +1312,6 @@ esp_err_t esp_bt_controller_deinit(void) osi_funcs_p = NULL; btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; - btdm_lpcycle_us = 0; return ESP_OK; } diff --git a/components/bt/controller/esp32s3/bt.c b/components/bt/controller/esp32s3/bt.c index a6e6cb73da..90c6675924 100644 --- a/components/bt/controller/esp32s3/bt.c +++ b/components/bt/controller/esp32s3/bt.c @@ -399,6 +399,8 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; // wakeup timer static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr; +// set low power clock source callback +static esp_set_lpclk_source_callback_t s_set_lpclk_source_cb = NULL; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock; @@ -957,6 +959,11 @@ static void IRAM_ATTR btdm_mac_bb_power_up_cb(void) } #endif +void esp_wifi_set_lpclk_register_callback(esp_set_lpclk_source_callback_t callback) +{ + s_set_lpclk_source_cb = callback; +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err = ESP_FAIL; @@ -1139,6 +1146,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) goto error; } + if (s_set_lpclk_source_cb) { + s_set_lpclk_source_cb(); + } + #ifdef CONFIG_PM_ENABLE if (s_lp_cntl.no_light_sleep) { if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { @@ -1215,6 +1226,7 @@ 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 @@ -1223,7 +1235,15 @@ error: s_lp_cntl.main_xtal_pu = 0; } #endif + btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); + btdm_lpclk_set_div(0); + if (s_set_lpclk_source_cb) { + s_set_lpclk_source_cb(); + } } + + btdm_lpcycle_us = 0; + s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD @@ -1294,7 +1314,15 @@ esp_err_t esp_bt_controller_deinit(void) s_lp_cntl.main_xtal_pu = 0; } #endif + btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); + btdm_lpclk_set_div(0); + if (s_set_lpclk_source_cb) { + s_set_lpclk_source_cb(); + } } + + btdm_lpcycle_us = 0; + s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD @@ -1312,7 +1340,6 @@ esp_err_t esp_bt_controller_deinit(void) osi_funcs_p = NULL; btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; - btdm_lpcycle_us = 0; return ESP_OK; } diff --git a/components/bt/include/esp32c3/include/esp_bt.h b/components/bt/include/esp32c3/include/esp_bt.h index 2ec3064d6e..9ec44d0996 100644 --- a/components/bt/include/esp32c3/include/esp_bt.h +++ b/components/bt/include/esp32c3/include/esp_bt.h @@ -92,6 +92,11 @@ enum { */ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); +/** + * @brief callback function for Wi-Fi low power clock operations + */ +typedef void (* esp_set_lpclk_source_callback_t)(void); + #ifdef CONFIG_BT_ENABLED #define BT_CTRL_BLE_MAX_ACT_LIMIT 10 //Maximum BLE activity limitation @@ -535,6 +540,13 @@ void esp_wifi_bt_power_domain_on(void); */ 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); + #ifdef __cplusplus } #endif diff --git a/components/bt/include/esp32s3/include/esp_bt.h b/components/bt/include/esp32s3/include/esp_bt.h index 7bc1f0b6e2..30de2b3363 100644 --- a/components/bt/include/esp32s3/include/esp_bt.h +++ b/components/bt/include/esp32s3/include/esp_bt.h @@ -92,6 +92,11 @@ enum { */ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); +/** + * @brief callback function for Wi-Fi low power clock operations + */ +typedef void (* esp_set_lpclk_source_callback_t)(void); + #ifdef CONFIG_BT_ENABLED #define BT_CTRL_BLE_MAX_ACT_LIMIT 10 //Maximum BLE activity limitation @@ -534,6 +539,13 @@ void esp_wifi_bt_power_domain_on(void); */ 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); + #ifdef __cplusplus } #endif From 4afc1153971b4ac0ac54a9705be950b3fca83cb1 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 25 Oct 2021 10:56:40 +0800 Subject: [PATCH 4/5] Power Management: fix the issue of sleeping time error beacause external 32kHz xtal does not exist --- components/esp_hw_support/sleep_modes.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ed092feb23..58caee9b3e 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -687,8 +687,15 @@ esp_err_t esp_light_sleep_start(void) // Re-calibrate the RTC Timer clock #ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL - 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(); + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { + 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 CONFIG_RTC_CLK_SRC_INT_RC && CONFIG_IDF_TARGET_ESP32S2 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); From 4f2cec84956a20e10c47f75cfe5901f2396b4555 Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Mon, 25 Oct 2021 21:19:47 +0800 Subject: [PATCH 5/5] 1. Wi-Fi: update tsf tick interval when lpclk is modified 2. Move register_lpclk_callback to coexistence --- components/bt/controller/esp32c3/bt.c | 28 ++++++------------- components/bt/controller/esp32s3/bt.c | 28 ++++++------------- .../bt/include/esp32c3/include/esp_bt.h | 12 -------- .../bt/include/esp32s3/include/esp_bt.h | 12 -------- components/esp_wifi/esp32c3/esp_adapter.c | 10 ++++++- components/esp_wifi/esp32s3/esp_adapter.c | 10 ++++++- .../esp_wifi/include/esp_coexist_internal.h | 15 +++++++++- .../esp_wifi/include/esp_private/wifi.h | 11 +++++++- components/esp_wifi/lib | 2 +- components/esp_wifi/src/wifi_init.c | 3 ++ 10 files changed, 64 insertions(+), 67 deletions(-) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index ab10fb9c2e..e3a5b761b5 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -395,8 +395,6 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; // wakeup timer static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr; -// set low power clock source callback -static esp_set_lpclk_source_callback_t s_set_lpclk_source_cb = NULL; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock; @@ -927,11 +925,6 @@ static void IRAM_ATTR btdm_mac_bb_power_up_cb(void) } #endif -void esp_wifi_set_lpclk_register_callback(esp_set_lpclk_source_callback_t callback) -{ - s_set_lpclk_source_cb = callback; -} - esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err = ESP_FAIL; @@ -1113,10 +1106,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) err = ESP_ERR_INVALID_ARG; goto error; } - - if (s_set_lpclk_source_cb) { - s_set_lpclk_source_cb(); - } +#if CONFIG_SW_COEXIST_ENABLE + coex_update_lpclk_interval(); +#endif #ifdef CONFIG_PM_ENABLE if (s_lp_cntl.no_light_sleep) { @@ -1205,13 +1197,12 @@ error: #endif btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); btdm_lpclk_set_div(0); - if (s_set_lpclk_source_cb) { - s_set_lpclk_source_cb(); - } +#if CONFIG_SW_COEXIST_ENABLE + coex_update_lpclk_interval(); +#endif } btdm_lpcycle_us = 0; - s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD @@ -1283,13 +1274,12 @@ esp_err_t esp_bt_controller_deinit(void) #endif btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); btdm_lpclk_set_div(0); - if (s_set_lpclk_source_cb) { - s_set_lpclk_source_cb(); - } +#if CONFIG_SW_COEXIST_ENABLE + coex_update_lpclk_interval(); +#endif } btdm_lpcycle_us = 0; - s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD diff --git a/components/bt/controller/esp32s3/bt.c b/components/bt/controller/esp32s3/bt.c index 90c6675924..b38e9ec9e5 100644 --- a/components/bt/controller/esp32s3/bt.c +++ b/components/bt/controller/esp32s3/bt.c @@ -399,8 +399,6 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; // wakeup timer static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr; -// set low power clock source callback -static esp_set_lpclk_source_callback_t s_set_lpclk_source_cb = NULL; #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock; @@ -959,11 +957,6 @@ static void IRAM_ATTR btdm_mac_bb_power_up_cb(void) } #endif -void esp_wifi_set_lpclk_register_callback(esp_set_lpclk_source_callback_t callback) -{ - s_set_lpclk_source_cb = callback; -} - esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err = ESP_FAIL; @@ -1145,10 +1138,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) err = ESP_ERR_INVALID_ARG; goto error; } - - if (s_set_lpclk_source_cb) { - s_set_lpclk_source_cb(); - } +#if CONFIG_SW_COEXIST_ENABLE + coex_update_lpclk_interval(); +#endif #ifdef CONFIG_PM_ENABLE if (s_lp_cntl.no_light_sleep) { @@ -1237,13 +1229,12 @@ error: #endif btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); btdm_lpclk_set_div(0); - if (s_set_lpclk_source_cb) { - s_set_lpclk_source_cb(); - } +#if CONFIG_SW_COEXIST_ENABLE + coex_update_lpclk_interval(); +#endif } btdm_lpcycle_us = 0; - s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD @@ -1316,13 +1307,12 @@ esp_err_t esp_bt_controller_deinit(void) #endif btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW); btdm_lpclk_set_div(0); - if (s_set_lpclk_source_cb) { - s_set_lpclk_source_cb(); - } +#if CONFIG_SW_COEXIST_ENABLE + coex_update_lpclk_interval(); +#endif } btdm_lpcycle_us = 0; - s_set_lpclk_source_cb = NULL; } while (0); #if CONFIG_MAC_BB_PD diff --git a/components/bt/include/esp32c3/include/esp_bt.h b/components/bt/include/esp32c3/include/esp_bt.h index 9ec44d0996..2ec3064d6e 100644 --- a/components/bt/include/esp32c3/include/esp_bt.h +++ b/components/bt/include/esp32c3/include/esp_bt.h @@ -92,11 +92,6 @@ enum { */ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); -/** - * @brief callback function for Wi-Fi low power clock operations - */ -typedef void (* esp_set_lpclk_source_callback_t)(void); - #ifdef CONFIG_BT_ENABLED #define BT_CTRL_BLE_MAX_ACT_LIMIT 10 //Maximum BLE activity limitation @@ -540,13 +535,6 @@ void esp_wifi_bt_power_domain_on(void); */ 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); - #ifdef __cplusplus } #endif diff --git a/components/bt/include/esp32s3/include/esp_bt.h b/components/bt/include/esp32s3/include/esp_bt.h index 30de2b3363..7bc1f0b6e2 100644 --- a/components/bt/include/esp32s3/include/esp_bt.h +++ b/components/bt/include/esp32s3/include/esp_bt.h @@ -92,11 +92,6 @@ enum { */ typedef void (* esp_bt_hci_tl_callback_t) (void *arg, uint8_t status); -/** - * @brief callback function for Wi-Fi low power clock operations - */ -typedef void (* esp_set_lpclk_source_callback_t)(void); - #ifdef CONFIG_BT_ENABLED #define BT_CTRL_BLE_MAX_ACT_LIMIT 10 //Maximum BLE activity limitation @@ -539,13 +534,6 @@ void esp_wifi_bt_power_domain_on(void); */ 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); - #ifdef __cplusplus } #endif diff --git a/components/esp_wifi/esp32c3/esp_adapter.c b/components/esp_wifi/esp32c3/esp_adapter.c index ea028c407b..65f594dc00 100644 --- a/components/esp_wifi/esp32c3/esp_adapter.c +++ b/components/esp_wifi/esp32c3/esp_adapter.c @@ -35,6 +35,7 @@ #include "soc/rtc_cntl_reg.h" #include "soc/rtc.h" #include "soc/syscon_reg.h" +#include "soc/system_reg.h" #include "phy_init_data.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" @@ -47,6 +48,8 @@ #define TAG "esp_adapter" +#define MHZ (1000000) + #ifdef CONFIG_PM_ENABLE extern void wifi_apb80m_request(void); extern void wifi_apb80m_release(void); @@ -434,7 +437,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 * 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) diff --git a/components/esp_wifi/esp32s3/esp_adapter.c b/components/esp_wifi/esp32s3/esp_adapter.c index def48bff1d..fe8400610a 100644 --- a/components/esp_wifi/esp32s3/esp_adapter.c +++ b/components/esp_wifi/esp32s3/esp_adapter.c @@ -35,6 +35,7 @@ #include "soc/rtc_cntl_reg.h" #include "soc/rtc.h" #include "soc/syscon_reg.h" +#include "soc/system_reg.h" #include "phy_init_data.h" #include "esp_private/periph_ctrl.h" #include "esp_private/esp_clk.h" @@ -48,6 +49,8 @@ #define TAG "esp_adapter" +#define MHZ (1000000) + #ifdef CONFIG_PM_ENABLE extern void wifi_apb80m_request(void); extern void wifi_apb80m_release(void); @@ -545,7 +548,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 * 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) diff --git a/components/esp_wifi/include/esp_coexist_internal.h b/components/esp_wifi/include/esp_coexist_internal.h index b4137785d8..4e1bda69a1 100644 --- a/components/esp_wifi/include/esp_coexist_internal.h +++ b/components/esp_wifi/include/esp_coexist_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ typedef enum { } coex_prefer_t; 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 @@ -115,6 +116,18 @@ int coex_wifi_release(uint32_t event); */ 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. * diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index 6d77c8a353..b3f7342a0c 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/components/esp_wifi/include/esp_private/wifi.h @@ -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 */ @@ -496,6 +496,15 @@ bool esp_wifi_internal_is_tsf_active(void); * */ 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 /** diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 3a69afcd41..767ec0f081 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 3a69afcd419114281a027d8792e2bfa03044fedd +Subproject commit 767ec0f081e8db890dc86cc88cf77d280a20def6 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index 3019bbf499..02517049e8 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/components/esp_wifi/src/wifi_init.c @@ -234,6 +234,9 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config) return ret; } 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