Explorar o código

Merge branch 'bugfix/wifi_bt_use_same_clock_source' into 'master'

Fix Wi-Fi does not know that Bluetooth has modified the lpclk source

Closes WIFI-4114, BT-1996, and BT-2005

See merge request espressif/esp-idf!15703
Jiang Jiang Jian %!s(int64=3) %!d(string=hai) anos
pai
achega
33f1747feb

+ 13 - 4
components/bt/controller/esp32c3/Kconfig.in

@@ -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
-                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
         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
+
+    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.
 
 
 
 
-    endchoice
 endmenu
 endmenu
 
 
 config BT_CTRL_SLEEP_MODE_EFF
 config BT_CTRL_SLEEP_MODE_EFF

+ 57 - 13
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 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"
-                 "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) {
         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);
@@ -1096,6 +1106,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) {
@@ -1103,6 +1116,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 +1187,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
@@ -1235,6 +1265,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
@@ -1257,7 +1302,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;
 }
 }
 
 

+ 12 - 4
components/bt/controller/esp32s3/Kconfig.in

@@ -368,9 +368,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
-                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
         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
@@ -385,9 +385,17 @@ 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
 
 
+    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.
 
 
-    endchoice
 endmenu
 endmenu
 
 
 config BT_CTRL_SLEEP_MODE_EFF
 config BT_CTRL_SLEEP_MODE_EFF

+ 58 - 13
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 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;
@@ -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
         // 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
@@ -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
         // 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(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) {
         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(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.");
                  "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(BT_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);
@@ -1128,6 +1138,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) {
@@ -1135,6 +1148,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(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) {
         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;
@@ -1205,6 +1219,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
@@ -1267,6 +1297,22 @@ 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
@@ -1284,7 +1330,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;
 }
 }
 
 

+ 9 - 2
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
     // Re-calibrate the RTC Timer clock
 #ifdef CONFIG_ESP_SYSTEM_RTC_EXT_XTAL
 #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
 #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);
     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);

+ 9 - 1
components/esp_wifi/esp32c3/esp_adapter.c

@@ -35,6 +35,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 "esp_private/periph_ctrl.h"
 #include "esp_private/periph_ctrl.h"
 #include "esp_private/esp_clk.h"
 #include "esp_private/esp_clk.h"
@@ -47,6 +48,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);
@@ -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
     /* 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)

+ 9 - 1
components/esp_wifi/esp32s3/esp_adapter.c

@@ -35,6 +35,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 "esp_private/periph_ctrl.h"
 #include "esp_private/periph_ctrl.h"
 #include "esp_private/esp_clk.h"
 #include "esp_private/esp_clk.h"
@@ -48,6 +49,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);
@@ -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
     /* 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)

+ 14 - 1
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
  * SPDX-License-Identifier: Apache-2.0
  */
  */
@@ -23,6 +23,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
@@ -115,6 +116,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.
  *
  *

+ 10 - 1
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
  * 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
 
 
 /**
 /**

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit 3a69afcd419114281a027d8792e2bfa03044fedd
+Subproject commit 767ec0f081e8db890dc86cc88cf77d280a20def6

+ 3 - 0
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;
         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