Răsfoiți Sursa

Mac BB power down in light sleep

components/bt: Do not use feature: timer support isr dispatch method

disable controller after wake up finished.

protect critical section of power down

choose clk in sleep

components/coex: mac bb power down in light sleep

components/coex: Macro changed

components/os: protect reserved interrupt number

update phy to phy_version 300,6e46ba7,Jan 25 2021

some bugfix
baohongde 5 ani în urmă
părinte
comite
eef66789d4

+ 17 - 0
components/bt/controller/esp32c3/Kconfig.in

@@ -310,6 +310,21 @@ menu "MODEM SLEEP Options"
                 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.
+        config BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
+            bool "External 32kHz crystal"
+            depends on ESP32C3_RTC_CLK_SRC_EXT_CRYS
+            help
+                External 32kHz crystal has a nominal frequency of 32.768kHz and provides good frequency
+                stability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth
+                modem sleep to be used with both DFS and light sleep.
+
+        config BT_CTRL_LPCLK_SEL_RTC_SLOW
+            bool "Internal 150kHz RC oscillator"
+            depends on ESP32C3_RTC_CLK_SRC_INT_RC
+            help
+                Internal 150kHz RC oscillator.
+
+
     endchoice
 endmenu
 
@@ -321,6 +336,8 @@ config BT_CTRL_SLEEP_MODE_EFF
 config BT_CTRL_SLEEP_CLOCK_EFF
     int
     default 1 if BT_CTRL_LPCLK_SEL_MAIN_XTAL
+    default 2 if BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
+    default 3 if BT_CTRL_LPCLK_SEL_RTC_SLOW
 
     default 0
 

+ 109 - 60
components/bt/controller/esp32c3/bt.c

@@ -44,6 +44,7 @@
 #include "esp_coexist_internal.h"
 #include "esp32c3/rom/rom_layout.h"
 #include "esp_timer.h"
+#include "esp_sleep.h"
 
 #if CONFIG_BT_ENABLED
 
@@ -246,7 +247,7 @@ extern void btdm_deep_sleep_mem_deinit(void);
 extern void btdm_ble_power_down_dma_copy(bool copy);
 extern uint8_t btdm_sleep_clock_sync(void);
 
-#if CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB
+#if CONFIG_MAC_BB_PD
 extern void esp_mac_bb_power_down(void);
 extern void esp_mac_bb_power_up(void);
 extern void ets_backup_dma_copy(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_mem);
@@ -404,9 +405,9 @@ static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock;
 static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock;
 #endif
 
-void btdm_hw_mac_power_down_wrapper(void)
+void IRAM_ATTR btdm_hw_mac_power_down_wrapper(void)
 {
-#if CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB
+#if CONFIG_MAC_BB_PD
     // le module power down
     SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO);
     SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD);
@@ -415,9 +416,9 @@ void btdm_hw_mac_power_down_wrapper(void)
 #endif
 }
 
-void btdm_hw_mac_power_up_wrapper(void)
+void IRAM_ATTR btdm_hw_mac_power_up_wrapper(void)
 {
-#if CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB
+#if CONFIG_MAC_BB_PD
     // le module power up
     CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_BT_FORCE_PD);
     CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_BT_FORCE_ISO);
@@ -426,9 +427,9 @@ void btdm_hw_mac_power_up_wrapper(void)
 #endif
 }
 
-void btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr, uint32_t num,  bool to_mem)
+void IRAM_ATTR btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr, uint32_t num,  bool to_mem)
 {
-#if CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB
+#if CONFIG_MAC_BB_PD
     ets_backup_dma_copy(reg, mem_addr, num, to_mem);
 #endif
 }
@@ -688,13 +689,6 @@ static void btdm_sleep_enter_phase2_wrapper(void)
             assert(0);
         }
 
-        if (s_lp_cntl.mac_bb_pd && s_lp_stat.mac_bb_pd == 0) {
-#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB)
-            btdm_ble_power_down_dma_copy(true);
-#endif
-            s_lp_stat.mac_bb_pd = 1;
-        }
-
         if (s_lp_stat.pm_lock_released == 0) {
 #ifdef CONFIG_PM_ENABLE
             esp_pm_lock_release(s_pm_lock);
@@ -706,6 +700,16 @@ static void btdm_sleep_enter_phase2_wrapper(void)
 
 static void btdm_sleep_exit_phase3_wrapper(void)
 {
+#ifdef CONFIG_PM_ENABLE
+    // If BT wakeup before esp timer coming due to timer task have no chance to run.
+    // Then we will not run into `btdm_sleep_exit_phase0` and acquire PM lock,
+    // Do it again here to fix this issue.
+    if (s_lp_stat.pm_lock_released) {
+        esp_pm_lock_acquire(s_pm_lock);
+        s_lp_stat.pm_lock_released = 0;
+    }
+#endif
+
     if(btdm_sleep_clock_sync()) {
         ESP_LOGE(BTDM_LOG_TAG, "sleep eco state err\n");
         assert(0);
@@ -716,6 +720,14 @@ static void btdm_sleep_exit_phase3_wrapper(void)
             s_lp_stat.phy_enabled = 1;
         }
     }
+
+    // If BT wakeup before esp timer coming due to timer task have no chance to run.
+    // Then we will not run into `btdm_sleep_exit_phase0` and stop esp timer,
+    // Do it again here to fix this issue.
+    if (s_lp_cntl.wakeup_timer_required && s_lp_stat.wakeup_timer_started) {
+        esp_timer_stop(s_btdm_slp_tmr);
+        s_lp_stat.wakeup_timer_started = 0;
+    }
 }
 
 static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
@@ -729,12 +741,6 @@ static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
     }
 #endif
 
-#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB)
-    if (s_lp_cntl.mac_bb_pd && s_lp_stat.mac_bb_pd) {
-        btdm_ble_power_down_dma_copy(false);
-        s_lp_stat.mac_bb_pd = 0;
-    }
-#endif
     btdm_wakeup_request();
 
     if (s_lp_cntl.wakeup_timer_required && s_lp_stat.wakeup_timer_started) {
@@ -749,14 +755,9 @@ static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
 
 static void IRAM_ATTR btdm_slp_tmr_callback(void *arg)
 {
-#if  (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB)
-#ifdef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
-    btdm_vnd_offload_post_from_isr(BTDM_VND_OL_SIG_WAKEUP_TMR, (void *)BTDM_ASYNC_WAKEUP_SRC_TMR, false);
-    esp_timer_isr_dispatch_need_yield();
-#else
+#ifdef CONFIG_PM_ENABLE
     btdm_vnd_offload_post(BTDM_VND_OL_SIG_WAKEUP_TMR, (void *)BTDM_ASYNC_WAKEUP_SRC_TMR);
 #endif
-#endif
 }
 
 
@@ -888,16 +889,27 @@ void esp_release_wifi_and_coex_mem(void)
     ESP_ERROR_CHECK(try_heap_caps_add_region((intptr_t)ets_rom_layout_p->data_start_interface_coexist,(intptr_t)ets_rom_layout_p->bss_end_interface_pp));
 }
 
-esp_err_t esp_bluetooth_stop(void)
+#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
+static void IRAM_ATTR btdm_mac_bb_power_down_cb(void)
 {
-#ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB
+    if (s_lp_cntl.mac_bb_pd && s_lp_stat.mac_bb_pd == 0) {
+#if (CONFIG_MAC_BB_PD)
+        btdm_ble_power_down_dma_copy(true);
+#endif
+        s_lp_stat.mac_bb_pd = 1;
+    }
+}
+
+static void IRAM_ATTR btdm_mac_bb_power_up_cb(void)
+{
+#if (CONFIG_MAC_BB_PD)
     if (s_lp_cntl.mac_bb_pd && s_lp_stat.mac_bb_pd) {
-        btdm_hw_mac_power_up_wrapper();
+        btdm_ble_power_down_dma_copy(false);
         s_lp_stat.mac_bb_pd = 0;
     }
 #endif
-    return ESP_OK;
 }
+#endif
 
 esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 {
@@ -941,9 +953,17 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 
     btdm_controller_mem_init();
 
-    if (esp_register_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop) != 0) {
-        return ESP_ERR_INVALID_ARG;
+#if CONFIG_MAC_BB_PD
+    if (esp_register_mac_bb_pd_callback(btdm_mac_bb_power_down_cb) != 0) {
+        err = ESP_ERR_INVALID_ARG;
+        goto error;
+    }
+
+    if (esp_register_mac_bb_pu_callback(btdm_mac_bb_power_up_cb) != 0) {
+        err = ESP_ERR_INVALID_ARG;
+        goto error;
     }
+#endif
 
     osi_funcs_p = (struct osi_funcs_t *)malloc_internal_wrapper(sizeof(struct osi_funcs_t));
     if (osi_funcs_p == NULL) {
@@ -969,17 +989,17 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 
         // 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_PM_POWER_DOWN_WIFI_BT_MAC_BB)
+#if (CONFIG_MAC_BB_PD)
             if (!btdm_deep_sleep_mem_init()) {
                 err = ESP_ERR_NO_MEM;
                 goto error;
             }
             s_lp_cntl.mac_bb_pd = 1;
 #endif
-#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB)
+#ifdef CONFIG_PM_ENABLE
             s_lp_cntl.wakeup_timer_required = 1;
 #endif
             // async wakeup semaphore for VHCI
@@ -992,17 +1012,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
         }
 
         if (s_lp_cntl.wakeup_timer_required) {
-#ifndef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
-            ESP_LOGE(BTDM_LOG_TAG, "ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is required");
-            err = ESP_ERR_NOT_SUPPORTED;
-            goto error;
-#endif
             esp_timer_create_args_t create_args = {
                 .callback = btdm_slp_tmr_callback,
                 .arg = NULL,
-#ifdef CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD
-                .dispatch_method = ESP_TIMER_ISR,
-#endif
                 .name = "btSlp",
             };
             if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
@@ -1014,8 +1026,32 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
         btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
         btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
 
-        // set default bluetooth sleep clock source
-        s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL;
+        // // set default bluetooth sleep clock source
+        // s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL;
+#if CONFIG_BT_CTRL_LPCLK_SEL_EXT_32K_XTAL
+        // 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; // set default value
+// #ifdef CONFIG_PM_ENABLE
+//             s_btdm_allow_light_sleep = true;
+// #endif
+        } 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");
+            s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
+        }
+#elif (CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW)
+        // check whether or not EXT_CRYS is working
+        if (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) {
+            s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // set default value
+        } else {
+            ESP_LOGW(BTDM_LOG_TAG, "Internal 150kHz RC oscillator 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");
+            s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
+        }
+#else
+        s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value
+#endif
 
         bool select_src_ret, set_div_ret;
         if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
@@ -1024,9 +1060,22 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
             assert(select_src_ret && set_div_ret);
             btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
             btdm_lpcycle_us = 2 << (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);
+            assert(select_src_ret && set_div_ret);
+            btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+            btdm_lpcycle_us = (RTC_CLK_CAL_FRACT > 15) ? (1000000 << (RTC_CLK_CAL_FRACT - 15)) :
+                (1000000 >> (15 - RTC_CLK_CAL_FRACT));
+            assert(btdm_lpcycle_us != 0);
+        } else if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_RTC_SLOW) {
+            select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
+            set_div_ret = btdm_lpclk_set_div(0);
+            assert(select_src_ret && set_div_ret);
+            btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
+            btdm_lpcycle_us = esp_clk_slowclk_cal_get();
         } else {
-            ESP_LOGW(BTDM_LOG_TAG, "%s sleep clock not supported", __func__);
-            err = ESP_ERR_NOT_SUPPORTED;
+            err = ESP_ERR_INVALID_ARG;
             goto error;
         }
 
@@ -1052,10 +1101,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 
     periph_module_enable(PERIPH_BT_MODULE);
 
-#ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB
-    btdm_hw_mac_power_up_wrapper();
-#endif
-
     esp_phy_enable();
     s_lp_stat.phy_enabled = 1;
 
@@ -1095,7 +1140,7 @@ error:
             s_btdm_slp_tmr = NULL;
         }
 
-#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB)
+#if (CONFIG_MAC_BB_PD)
         if (s_lp_cntl.mac_bb_pd) {
             btdm_deep_sleep_mem_deinit();
             s_lp_cntl.mac_bb_pd = 0;
@@ -1110,7 +1155,11 @@ error:
         }
     } while (0);
 
-    esp_unregister_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop);
+#if CONFIG_MAC_BB_PD
+    esp_unregister_mac_bb_pd_callback(btdm_mac_bb_power_down_cb);
+
+    esp_unregister_mac_bb_pu_callback(btdm_mac_bb_power_up_cb);
+#endif
 
     if (osi_funcs_p != NULL) {
         free(osi_funcs_p);
@@ -1137,12 +1186,10 @@ esp_err_t esp_bt_controller_deinit(void)
 
     // deinit low power control resources
     do {
-#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB)
+#if (CONFIG_MAC_BB_PD)
         btdm_deep_sleep_mem_deinit();
 #endif
-#ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB
-        btdm_hw_mac_power_down_wrapper();
-#endif
+
 #ifdef CONFIG_PM_ENABLE
         if (s_lp_cntl.no_light_sleep) {
             esp_pm_lock_delete(s_light_sleep_pm_lock);
@@ -1170,8 +1217,10 @@ esp_err_t esp_bt_controller_deinit(void)
         }
     } while (0);
 
-    esp_unregister_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop);
-
+#if CONFIG_MAC_BB_PD
+    esp_unregister_mac_bb_pd_callback(btdm_mac_bb_power_down_cb);
+    esp_unregister_mac_bb_pu_callback(btdm_mac_bb_power_up_cb);
+#endif
     free(osi_funcs_p);
     osi_funcs_p = NULL;
 
@@ -1247,7 +1296,7 @@ esp_err_t esp_bt_controller_disable(void)
     }
 
     async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_DISA);
-
+    while (!btdm_power_state_active()){}
     btdm_controller_disable();
 
     async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_DISA);

+ 1 - 1
components/bt/controller/lib

@@ -1 +1 @@
-Subproject commit cf348db2d264019ac8c2a5c40147f9973f7cf52c
+Subproject commit 272aaca1f859f87c9694cd441ae68cb3d7829664

+ 2 - 1
components/bt/include/esp32c3/include/esp_bt.h

@@ -73,7 +73,8 @@ typedef enum {
     ESP_BT_SLEEP_CLOCK_NONE            = 0,   /*!< Sleep clock not configured */
     ESP_BT_SLEEP_CLOCK_MAIN_XTAL       = 1,   /*!< SoC main crystal */
     ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL    = 2,   /*!< External 32.768kHz crystal */
-    ESP_BT_SLEEP_CLOCK_FPGA_32K        = 3,   /*!< Hardwired 32KHz clock temporarily used for FPGA */
+    ESP_BT_SLEEP_CLOCK_RTC_SLOW        = 3,   /*!< Internal 150kHz RC oscillator */
+    ESP_BT_SLEEP_CLOCK_FPGA_32K        = 4,   /*!< Hardwired 32KHz clock temporarily used for FPGA */
 } esp_bt_sleep_clock_t;
 
 /**

+ 1 - 0
components/esp_rom/esp32c3/ld/esp32c3.rom.ld

@@ -1731,6 +1731,7 @@ ieee80211_set_tx_desc = 0x4000186c;
 rom_sta_input = 0x40001870;
 wifi_get_macaddr = 0x40001874;
 wifi_rf_phy_disable = 0x40001878;
+wifi_rf_phy_enable = 0x4000187c;
 ic_ebuf_alloc = 0x40001880;
 ieee80211_classify = 0x40001884;
 ieee80211_copy_eb_header = 0x40001888;

+ 45 - 0
components/esp_system/include/esp_sleep.h

@@ -409,6 +409,51 @@ void esp_sleep_gpio_status_init(void);
  */
 void esp_sleep_gpio_status_switch_configure(bool enable);
 #endif
+
+#if CONFIG_MAC_BB_PD
+/**
+ * @brief Function type for stub to run mac bb power down.
+ */
+typedef void (* mac_bb_power_down_cb_t)(void);
+
+/**
+ * @brief Function type for stub to run mac bb power up.
+ */
+typedef void (* mac_bb_power_up_cb_t)(void);
+
+/**
+ * @brief  Registet mac bb power down callback.
+ * @param  cb mac bb power down callback.
+ * @return
+ *  - ESP_OK on success
+ */
+esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb);
+
+/**
+ * @brief  Unregistet mac bb power down callback.
+ * @param  cb mac bb power down callback.
+ * @return
+ *  - ESP_OK on success
+ */
+esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb);
+
+/**
+ * @brief  Registet mac bb power up callback.
+ * @param  cb mac bb power up callback.
+ * @return
+ *  - ESP_OK on success
+ */
+esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb);
+
+/**
+ * @brief  Unregistet mac bb power up callback.
+ * @param  cb mac bb power up callback.
+ * @return
+ *  - ESP_OK on success
+ */
+esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb);
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 97 - 0
components/esp_system/sleep_modes.c

@@ -176,6 +176,95 @@ static void timer_wakeup_prepare(void);
 static void touch_wakeup_prepare(void);
 #endif
 
+#if CONFIG_MAC_BB_PD
+#define MAC_BB_POWER_DOWN_CB_NO 2
+#define MAC_BB_POWER_UP_CB_NO 2
+static DRAM_ATTR mac_bb_power_down_cb_t   s_mac_bb_power_down_cb[MAC_BB_POWER_DOWN_CB_NO];
+static DRAM_ATTR mac_bb_power_up_cb_t    s_mac_bb_power_up_cb[MAC_BB_POWER_UP_CB_NO];
+
+esp_err_t esp_register_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
+{
+    int index = MAC_BB_POWER_DOWN_CB_NO;
+    for (int i = MAC_BB_POWER_DOWN_CB_NO -1; i >= 0; i--) {
+        if (s_mac_bb_power_down_cb[i] == cb) {
+            return ESP_ERR_INVALID_STATE;
+        }
+
+        if (s_mac_bb_power_down_cb[i] == NULL) {
+            index = i;
+        }
+    }
+
+    if (index < MAC_BB_POWER_DOWN_CB_NO) {
+        s_mac_bb_power_down_cb[index] = cb;
+        return ESP_OK;
+    }
+
+    return ESP_ERR_NO_MEM;
+}
+
+esp_err_t esp_unregister_mac_bb_pd_callback(mac_bb_power_down_cb_t cb)
+{
+    for (int i = MAC_BB_POWER_DOWN_CB_NO -1; i >= 0; i--) {
+        if (s_mac_bb_power_down_cb[i] == cb) {
+            s_mac_bb_power_down_cb[i] = NULL;
+            return ESP_OK;
+        }
+    }
+    return ESP_ERR_INVALID_STATE;
+}
+
+static IRAM_ATTR void mac_bb_power_down_cb_execute(void)
+{
+    for (int i = 0; i < MAC_BB_POWER_DOWN_CB_NO; i++) {
+        if (s_mac_bb_power_down_cb[i]) {
+            s_mac_bb_power_down_cb[i]();
+        }
+    }
+}
+
+esp_err_t esp_register_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
+{
+    int index = MAC_BB_POWER_UP_CB_NO;
+    for (int i = MAC_BB_POWER_UP_CB_NO -1; i >= 0; i--) {
+        if (s_mac_bb_power_up_cb[i] == cb) {
+            return ESP_ERR_INVALID_STATE;
+        }
+
+        if (s_mac_bb_power_up_cb[i] == NULL) {
+            index = i;
+        }
+    }
+
+    if (index < MAC_BB_POWER_UP_CB_NO) {
+        s_mac_bb_power_up_cb[index] = cb;
+        return ESP_OK;
+    }
+
+    return ESP_ERR_NO_MEM;
+}
+
+esp_err_t esp_unregister_mac_bb_pu_callback(mac_bb_power_up_cb_t cb)
+{
+    for (int i = MAC_BB_POWER_UP_CB_NO -1; i >= 0; i--) {
+        if (s_mac_bb_power_up_cb[i] == cb) {
+            s_mac_bb_power_up_cb[i] = NULL;
+            return ESP_OK;
+        }
+    }
+    return ESP_ERR_INVALID_STATE;
+}
+
+static IRAM_ATTR void mac_bb_power_up_cb_execute(void)
+{
+    for (int i = 0; i < MAC_BB_POWER_UP_CB_NO; i++) {
+        if (s_mac_bb_power_up_cb[i]) {
+            s_mac_bb_power_up_cb[i]();
+        }
+    }
+}
+#endif ///CONFIG_MAC_BB_PD
+
 /* Wake from deep sleep stub
    See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
 */
@@ -342,6 +431,7 @@ void esp_sleep_gpio_status_switch_configure(bool enable)
 }
 #endif // SOC_GPIO_SUPPORT_SLP_SWITCH
 
+
 static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
 {
     // Stop UART output so that output is not lost due to APB frequency change.
@@ -364,6 +454,10 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
         suspend_uarts();
     }
 
+#if CONFIG_MAC_BB_PD
+    mac_bb_power_down_cb_execute();
+#endif
+
     // Save current frequency and switch to XTAL
     rtc_cpu_freq_config_t cpu_freq_config;
     rtc_clk_cpu_freq_get_config(&cpu_freq_config);
@@ -474,6 +568,9 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
     gpio_sleep_mode_config_unapply();
 #endif
 
+#if CONFIG_MAC_BB_PD
+    mac_bb_power_up_cb_execute();
+#endif
     // re-enable UART output
     resume_uarts();
 

+ 1 - 1
components/esp_wifi/Kconfig

@@ -446,7 +446,7 @@ menu "PHY"
 
     config ESP32_PHY_MAC_BB_PD
         bool "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled"
-        depends on IDF_TARGET_ESP32C3
+        depends on (IDF_TARGET_ESP32C3 && FREERTOS_USE_TICKLESS_IDLE)
         default n
         help
             If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered

+ 1 - 0
components/esp_wifi/include/esp_phy_init.h

@@ -219,6 +219,7 @@ int64_t esp_phy_rf_get_on_ts(void);
  */
 esp_err_t esp_phy_update_country_info(const char *country);
 
+
 #if CONFIG_ESP32_SUPPORT_MULTIPLE_PHY_INIT_DATA_BIN
 /**
  * @brief Apply PHY init bin to PHY

+ 10 - 0
components/esp_wifi/include/esp_private/wifi.h

@@ -526,6 +526,16 @@ void esp_wifi_internal_update_light_sleep_wake_ahead_time(uint32_t);
   *    - ESP_OK: succeed
   */
 esp_err_t esp_wifi_internal_set_mac_sleep(bool enable);
+
+/**
+ * @brief mac bb sleep.
+ */
+void pm_mac_sleep(void);
+
+/**
+ * @brief mac bb wakeup.
+ */
+void pm_mac_wakeup(void);
 #endif
 
 /**

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit 56d0911c8a27bd97e7939057bf82c61e82a689e6
+Subproject commit ba5b0ff41f052c8e1e66c92be577a503fcd46674

+ 3 - 7
components/esp_wifi/src/phy_init.c

@@ -271,8 +271,6 @@ void esp_mac_bb_pd_mem_init(void)
 
 IRAM_ATTR void esp_mac_bb_power_up(void)
 {
-    uint32_t level = phy_enter_critical();
-
     if (s_mac_bb_pd_mem != NULL && s_mac_bb_pd_ref == 0) {
         esp_phy_common_clock_enable();
         CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
@@ -283,13 +281,13 @@ IRAM_ATTR void esp_mac_bb_power_up(void)
         esp_phy_common_clock_disable();
     }
     s_mac_bb_pd_ref++;
-
-    phy_exit_critical(level);
 }
 
 IRAM_ATTR void esp_mac_bb_power_down(void)
 {
-    uint32_t level = phy_enter_critical();
+    if (s_mac_bb_pd_ref == 0) {
+        return;
+    }
 
     s_mac_bb_pd_ref--;
     if (s_mac_bb_pd_mem != NULL && s_mac_bb_pd_ref == 0) {
@@ -299,8 +297,6 @@ IRAM_ATTR void esp_mac_bb_power_down(void)
         SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PD);
         esp_phy_common_clock_disable();
     }
-
-    phy_exit_critical(level);
 }
 #endif
 

+ 24 - 5
components/esp_wifi/src/wifi_init.c

@@ -152,7 +152,10 @@ esp_err_t esp_wifi_deinit(void)
     esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
 #endif
 #endif
-
+#if CONFIG_MAC_BB_PD
+    esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
+    esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
+#endif
     return err;
 }
 
@@ -207,11 +210,26 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
         }
     }
 #endif
+
 #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
+#if CONFIG_MAC_BB_PD
+    if (esp_register_mac_bb_pd_callback(pm_mac_sleep) != ESP_OK
+        || esp_register_mac_bb_pu_callback(pm_mac_wakeup) != ESP_OK) {
+
+        esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
+        esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
+        return ESP_ERR_INVALID_ARG;
+    }
+#endif
+
 #if SOC_WIFI_HW_TSF
     esp_err_t ret = esp_pm_register_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active);
     if (ret != ESP_OK) {
         ESP_LOGE(TAG, "Failed to register skip light sleep callback (0x%x)", ret);
+#if CONFIG_MAC_BB_PD
+        esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
+        esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
+#endif
         return ret;
     }
     ret = esp_pm_register_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
@@ -222,10 +240,7 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
     esp_sleep_enable_wifi_wakeup();
 #endif
 #endif
-#if CONFIG_MAC_BB_PD
-    esp_mac_bb_pd_mem_init();
-    esp_wifi_internal_set_mac_sleep(true);
-#endif
+
 #if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER
     esp_err_t err = tcpip_adapter_set_default_wifi_handlers();
     if (err != ESP_OK) {
@@ -237,6 +252,10 @@ esp_err_t esp_wifi_init(const wifi_init_config_t *config)
 #endif
     esp_err_t result = esp_wifi_init_internal(config);
     if (result == ESP_OK) {
+#if CONFIG_MAC_BB_PD
+        esp_mac_bb_pd_mem_init();
+        esp_wifi_internal_set_mac_sleep(true);
+#endif
         esp_wifi_set_debug_log();
 #if CONFIG_IDF_TARGET_ESP32
         s_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time;

+ 2 - 2
components/hal/interrupt_controller_hal.c

@@ -20,8 +20,8 @@
 
 static bool is_interrupt_number_reserved(int interrupt_number)
 {
-    //TODO. Workaround to reserve interrupt number 0 for Wi-Fi.
-    if (interrupt_number == 1) {
+    //TODO. Workaround to reserve interrupt number 1 for Wi-Fi and 5&8 for Bluetooth.
+    if (interrupt_number == 1 || interrupt_number == 5 || interrupt_number == 8) {
         return true;
     }
 

+ 13 - 13
components/soc/esp32c3/include/soc/soc.h

@@ -270,23 +270,23 @@
 
 //interrupt cpu using table, Please see the core-isa.h
 /*************************************************************************************************************
- *      Intr num                Level           Type                    PRO CPU usage           APP CPU uasge
- *      0                       1               extern level            WMAC                    Reserved
- *      1                       1               extern level            BT/BLE Host HCI DMA     BT/BLE Host HCI DMA
+ *      Intr num                Level           Type                    PRO CPU usage
+ *      0                       1               extern level            Panic
+ *      1                       1               extern level            WMAC
  *      2                       1               extern level
  *      3                       1               extern level
  *      4                       1               extern level            WBB
- *      5                       1               extern level            BT/BLE Controller       BT/BLE Controller
- *      6                       1               timer                   FreeRTOS Tick(L1)       FreeRTOS Tick(L1)
- *      7                       1               software                BT/BLE VHCI             BT/BLE VHCI
- *      8                       1               extern level            BT/BLE BB(RX/TX)        BT/BLE BB(RX/TX)
+ *      5                       1               extern level            BT/BLE Controller
+ *      6                       1               timer                   FreeRTOS Tick(L1)
+ *      7                       1               software
+ *      8                       1               extern level            BT/BLE BB(RX/TX)
  *      9                       1               extern level
  *      10                      1               extern edge
  *      11                      3               profiling
  *      12                      1               extern level
  *      13                      1               extern level
- *      14                      7               nmi                     Reserved                Reserved
- *      15                      3               timer                   FreeRTOS Tick(L3)       FreeRTOS Tick(L3)
+ *      14                      7               nmi                     Reserved
+ *      15                      3               timer                   FreeRTOS Tick(L3)
  *      16                      5               timer
  *      17                      1               extern level
  *      18                      1               extern level
@@ -298,10 +298,10 @@
  *      24                      4               extern level            TG1_WDT
  *      25                      4               extern level            CACHEERR
  *      26                      5               extern level
- *      27                      3               extern level            Reserved                Reserved
- *      28                      4               extern edge             DPORT ACCESS            DPORT ACCESS
- *      29                      3               software                Reserved                Reserved
- *      30                      4               extern edge             Reserved                Reserved
+ *      27                      3               extern level            Reserved
+ *      28                      4               extern edge             Reserved
+ *      29                      3               software                Reserved
+ *      30                      4               extern edge             Reserved
  *      31                      5               extern level
  *************************************************************************************************************
  */