Просмотр исходного кода

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 3 лет назад
Родитель
Сommit
33f1747feb

+ 13 - 4
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.
 
 
-    endchoice
 endmenu
 
 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 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);
@@ -1096,6 +1106,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
             err = ESP_ERR_INVALID_ARG;
             goto error;
         }
+#if CONFIG_SW_COEXIST_ENABLE
+        coex_update_lpclk_interval();
+#endif
 
 #ifdef CONFIG_PM_ENABLE
         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;
                 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 +1187,22 @@ 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
+            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);
 
 #if CONFIG_MAC_BB_PD
@@ -1235,6 +1265,21 @@ 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
+            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);
 
 #if CONFIG_MAC_BB_PD
@@ -1257,7 +1302,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;
 }
 

+ 12 - 4
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.
 
-    endchoice
 endmenu
 
 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 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);
@@ -1128,6 +1138,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
             err = ESP_ERR_INVALID_ARG;
             goto error;
         }
+#if CONFIG_SW_COEXIST_ENABLE
+        coex_update_lpclk_interval();
+#endif
 
 #ifdef CONFIG_PM_ENABLE
         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;
                 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;
@@ -1205,6 +1219,22 @@ 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
+            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);
 
 #if CONFIG_MAC_BB_PD
@@ -1267,6 +1297,22 @@ 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
+            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);
 
 #if CONFIG_MAC_BB_PD
@@ -1284,7 +1330,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;
 }
 

+ 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
 #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);

+ 9 - 1
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)

+ 9 - 1
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)

+ 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
  */
@@ -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.
  *

+ 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
  */
@@ -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
 
 /**

+ 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;
     }
     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