diff --git a/components/bt/controller/esp32c3/Kconfig.in b/components/bt/controller/esp32c3/Kconfig.in index fd1a2784e3..187d3886ab 100644 --- a/components/bt/controller/esp32c3/Kconfig.in +++ b/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 diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 1970529297..dc43b3b67c 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/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,10 +953,18 @@ 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) { return ESP_ERR_NO_MEM; @@ -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); diff --git a/components/bt/controller/lib b/components/bt/controller/lib index cf348db2d2..272aaca1f8 160000 --- a/components/bt/controller/lib +++ b/components/bt/controller/lib @@ -1 +1 @@ -Subproject commit cf348db2d264019ac8c2a5c40147f9973f7cf52c +Subproject commit 272aaca1f859f87c9694cd441ae68cb3d7829664 diff --git a/components/bt/include/esp32c3/include/esp_bt.h b/components/bt/include/esp32c3/include/esp_bt.h index 45d0d9bc3e..543f80785e 100644 --- a/components/bt/include/esp32c3/include/esp_bt.h +++ b/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; /** diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index d2bb9fdd88..f83ecc179f 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/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; diff --git a/components/esp_system/include/esp_sleep.h b/components/esp_system/include/esp_sleep.h index 4c247ce706..900b1ff4e6 100644 --- a/components/esp_system/include/esp_sleep.h +++ b/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 diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 0add0788a5..cbcd82b0ad 100644 --- a/components/esp_system/sleep_modes.c +++ b/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(); diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 1fc15fc180..56e8adac61 100644 --- a/components/esp_wifi/Kconfig +++ b/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 diff --git a/components/esp_wifi/include/esp_phy_init.h b/components/esp_wifi/include/esp_phy_init.h index 72dc673337..f85d8b38b1 100644 --- a/components/esp_wifi/include/esp_phy_init.h +++ b/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 diff --git a/components/esp_wifi/include/esp_private/wifi.h b/components/esp_wifi/include/esp_private/wifi.h index c0df0d2749..9ae3003994 100644 --- a/components/esp_wifi/include/esp_private/wifi.h +++ b/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 /** diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 56d0911c8a..ba5b0ff41f 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 56d0911c8a27bd97e7939057bf82c61e82a689e6 +Subproject commit ba5b0ff41f052c8e1e66c92be577a503fcd46674 diff --git a/components/esp_wifi/src/phy_init.c b/components/esp_wifi/src/phy_init.c index 9e836f8510..cf89bb9275 100644 --- a/components/esp_wifi/src/phy_init.c +++ b/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 diff --git a/components/esp_wifi/src/wifi_init.c b/components/esp_wifi/src/wifi_init.c index f01336665b..f60ebb87c2 100644 --- a/components/esp_wifi/src/wifi_init.c +++ b/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; diff --git a/components/hal/interrupt_controller_hal.c b/components/hal/interrupt_controller_hal.c index 0af5762725..9e00841fdb 100644 --- a/components/hal/interrupt_controller_hal.c +++ b/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; } diff --git a/components/soc/esp32c3/include/soc/soc.h b/components/soc/esp32c3/include/soc/soc.h index c85b764e43..0b4a7645cf 100644 --- a/components/soc/esp32c3/include/soc/soc.h +++ b/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 ************************************************************************************************************* */