diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 27a47f13f5..b43514a8a0 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -61,6 +61,36 @@ #define BTDM_LPCLK_SEL_RTC_SLOW (2) #define BTDM_LPCLK_SEL_8M (3) +// wakeup request sources +enum { + BTDM_ASYNC_WAKEUP_SRC_VHCI = 0, + BTDM_ASYNC_WAKEUP_SRC_DISA, + BTDM_ASYNC_WAKEUP_SRC_MAX, +}; + +// low power control struct +typedef union { + struct { + uint32_t enable : 1; // whether low power mode is required + uint32_t lpclk_sel : 2; // low power clock source + 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 val; +} btdm_lpcntl_t; + +// low power control status +typedef union { + struct { + uint32_t pm_lock_released : 1; // whether power management lock is released + uint32_t mac_bb_pd : 1; // whether hardware(MAC, BB) is powered down + uint32_t reserved : 30; // reserved + }; + uint32_t val; +} btdm_lpstat_t; + /* Sleep and wakeup interval control */ #define BTDM_MIN_SLEEP_DURATION (24) // threshold of interval in half slots to allow to fall into modem sleep #define BTDM_MODEM_WAKE_UP_DELAY (8) // delay in half slots of modem wake up procedure, including re-enable PHY/RF @@ -200,8 +230,7 @@ extern void btdm_controller_enable_sleep(bool enable); extern uint8_t btdm_controller_get_sleep_mode(void); extern bool btdm_power_state_active(void); extern void btdm_wakeup_request(void); -extern void btdm_wakeup_request_start(void); -extern void btdm_wakeup_request_end(void); +extern void btdm_in_wakeup_requesting_set(bool in_wakeup_requesting); /* vendor dependent tasks to be posted and handled by controller task*/ extern int btdm_vnd_offload_task_register(btdm_vnd_ol_sig_t sig, btdm_vnd_ol_task_func_t func); @@ -296,7 +325,6 @@ static uint32_t IRAM_ATTR btdm_hus_2_lpcycles(uint32_t hus); static bool IRAM_ATTR btdm_sleep_check_duration(int32_t *slot_cnt); static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles); static void btdm_sleep_enter_phase2_wrapper(void); -static void IRAM_ATTR btdm_sleep_exit_phase1_wrapper(void); static void btdm_sleep_exit_phase3_wrapper(void); static void coex_wifi_sleep_set_hook(bool sleep); static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status); @@ -351,7 +379,7 @@ static const struct osi_funcs_t osi_funcs_ro = { ._btdm_sleep_check_duration = btdm_sleep_check_duration, ._btdm_sleep_enter_phase1 = btdm_sleep_enter_phase1_wrapper, ._btdm_sleep_enter_phase2 = btdm_sleep_enter_phase2_wrapper, - ._btdm_sleep_exit_phase1 = btdm_sleep_exit_phase1_wrapper, + ._btdm_sleep_exit_phase1 = NULL, ._btdm_sleep_exit_phase2 = NULL, ._btdm_sleep_exit_phase3 = btdm_sleep_exit_phase3_wrapper, //._coex_bt_request = coex_bt_request_wrapper, @@ -388,21 +416,21 @@ static DRAM_ATTR portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED; static DRAM_ATTR uint32_t btdm_lpcycle_us = 0; static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit for btdm_lpcycle_us +// low power control struct +static DRAM_ATTR btdm_lpcntl_t s_lp_cntl; +static DRAM_ATTR btdm_lpstat_t s_lp_stat; + #ifdef CONFIG_PM_ENABLE static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock; static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock; // pm_lock to prevent light sleep due to incompatibility currently -static DRAM_ATTR QueueHandle_t s_pm_lock_sem = NULL; #endif -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) +// used low power clock +static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; +// wakeup timer static DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr; -static void btdm_slp_tmr_callback(void *arg); -#endif -#ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB -static bool sleep_backup_en = false; -static bool sleep_backup_done = false; -#endif +static void btdm_slp_tmr_callback(void *arg); static inline void btdm_check_and_init_bb(void) { @@ -413,6 +441,10 @@ static inline void btdm_check_and_init_bb(void) void btdm_hw_mac_power_down_wrapper(void) { #if CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB + // 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); + esp_mac_bb_power_down(); #endif } @@ -420,6 +452,10 @@ void btdm_hw_mac_power_down_wrapper(void) void btdm_hw_mac_power_up_wrapper(void) { #if CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB + // 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); + esp_mac_bb_power_up(); #endif } @@ -822,17 +858,6 @@ static int IRAM_ATTR rand_wrapper(void) return (int)esp_random(); } -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) -static uint32_t IRAM_ATTR btdm_lpcycles_2_us(uint32_t cycles) -{ - // The number of lp cycles should not lead to overflow. Thrs: 100s - // clock measurement is conducted - uint64_t us = (uint64_t)btdm_lpcycle_us * cycles; - us = (us + (1 << (btdm_lpcycle_us_frac - 1))) >> btdm_lpcycle_us_frac; - return (uint32_t)us; -} -#endif - static uint32_t IRAM_ATTR btdm_lpcycles_2_hus(uint32_t cycles, uint32_t *error_corr) { uint64_t local_error_corr = (error_corr == NULL) ? 0 : (uint64_t)(*error_corr); @@ -872,9 +897,12 @@ static bool IRAM_ATTR btdm_sleep_check_duration(int32_t *half_slot_cnt) static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles) { -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) + if (s_lp_cntl.wakeup_timer_required == 0) { + return; + } + // start a timer to wake up and acquire the pm_lock before modem_sleep awakes - uint32_t us_to_sleep = btdm_lpcycles_2_us(lpcycles); + uint32_t us_to_sleep = btdm_lpcycles_2_hus(lpcycles, NULL) >> 1; #define BTDM_MIN_TIMER_UNCERTAINTY_US (1800) assert(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US); @@ -888,7 +916,6 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles) if (esp_timer_start_once(s_btdm_slp_tmr, us_to_sleep - uncertainty) != ESP_OK) { ESP_LOGW(BTDM_LOG_TAG, "timer start failed"); } -#endif } static void btdm_sleep_enter_phase2_wrapper(void) @@ -898,29 +925,22 @@ static void btdm_sleep_enter_phase2_wrapper(void) esp_phy_disable(); #endif /* BTDM_MODEM_SLEEP_IN_EFFECT */ + if (s_lp_cntl.mac_bb_pd && s_lp_stat.mac_bb_pd == 0) { #if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - if(sleep_backup_en) { - btdm_ble_power_down_dma_copy(true); - sleep_backup_done = true; - } + 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); - semphr_give_wrapper(s_pm_lock_sem); + esp_pm_lock_release(s_pm_lock); #endif + s_lp_stat.pm_lock_released = 1; + } } } -static void IRAM_ATTR btdm_sleep_exit_phase1_wrapper(void) -{ -#ifdef CONFIG_PM_ENABLE - if (semphr_take_from_isr_wrapper(s_pm_lock_sem, NULL) == pdTRUE) { - esp_pm_lock_acquire(s_pm_lock); - } -#endif -} - static void btdm_sleep_exit_phase3_wrapper(void) { if(btdm_sleep_clock_sync()) { @@ -932,35 +952,94 @@ static void btdm_sleep_exit_phase3_wrapper(void) esp_phy_enable(); #endif /* BTDM_MODEM_SLEEP_IN_EFFECT */ btdm_check_and_init_bb(); -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - esp_timer_stop(s_btdm_slp_tmr); -#endif + + if (s_lp_cntl.wakeup_timer_required) { + esp_timer_stop(s_btdm_slp_tmr); + } } } -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) static void IRAM_ATTR btdm_sleep_exit_phase0(void *param) { + assert(s_lp_cntl.enable == 1); + #ifdef CONFIG_PM_ENABLE - if (semphr_take_wrapper(s_pm_lock_sem, 0) == pdTRUE) { + if (s_lp_stat.pm_lock_released) { esp_pm_lock_acquire(s_pm_lock); + s_lp_stat.pm_lock_released = 0; } #endif -#ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB - if (sleep_backup_en && sleep_backup_done) { +#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); - sleep_backup_done = false; + s_lp_stat.mac_bb_pd = 0; } #endif + btdm_wakeup_request(); + + int event = (int) param; + if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI || event == BTDM_ASYNC_WAKEUP_SRC_DISA) { + semphr_give_wrapper(s_wakeup_req_sem); + } } static void IRAM_ATTR btdm_slp_tmr_callback(void *arg) { +#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) btdm_vnd_offload_post_from_isr(BTDM_VND_OL_SIG_WAKEUP_TMR, NULL, false); esp_timer_isr_dispatch_need_yield(); -} #endif +} + + +static bool async_wakeup_request(int event) +{ + if (s_lp_cntl.enable == 0) { + return false; + } + + bool do_wakeup_request = false; + switch (event) { + case BTDM_ASYNC_WAKEUP_SRC_VHCI: + case BTDM_ASYNC_WAKEUP_SRC_DISA: + btdm_in_wakeup_requesting_set(true); + if (!btdm_power_state_active()) { + btdm_vnd_offload_post(BTDM_VND_OL_SIG_WAKEUP_TMR, (void *)event); + do_wakeup_request = true; + semphr_take_wrapper(s_wakeup_req_sem, OSI_FUNCS_TIME_BLOCKING); + } + break; + default: + break; + } + + return do_wakeup_request; +} + +static void async_wakeup_request_end(int event) +{ + if (s_lp_cntl.enable == 0) { + return; + } + + bool allow_to_sleep; + switch (event) { + case BTDM_ASYNC_WAKEUP_SRC_VHCI: + case BTDM_ASYNC_WAKEUP_SRC_DISA: + allow_to_sleep = true; + break; + default: + allow_to_sleep = true; + break; + } + + if (allow_to_sleep) { + btdm_in_wakeup_requesting_set(false); + } + + return; +} static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status) { @@ -978,38 +1057,29 @@ static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status) bool esp_vhci_host_check_send_available(void) { + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return false; + } return API_vhci_host_check_send_available(); } void esp_vhci_host_send_packet(uint8_t *data, uint16_t len) { - btdm_wakeup_request_start(); - - if (!btdm_power_state_active()) { -#if CONFIG_PM_ENABLE - if (semphr_take_wrapper(s_pm_lock_sem, 0)) { - esp_pm_lock_acquire(s_pm_lock); - } -#endif -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - esp_timer_stop(s_btdm_slp_tmr); -#ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB - if (sleep_backup_en && sleep_backup_done) { - btdm_ble_power_down_dma_copy(false); - sleep_backup_done = false; + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return; } -#endif // CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB + async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_VHCI); -#endif - btdm_wakeup_request(); - } API_vhci_host_send_packet(data, len); - btdm_wakeup_request_end(); + async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_VHCI); } esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) { + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_FAIL; + } return API_vhci_host_register_callback((const vhci_host_callback_t *)callback) == 0 ? ESP_OK : ESP_FAIL; } @@ -1054,45 +1124,18 @@ void esp_release_wifi_and_coex_mem(void) esp_err_t esp_bluetooth_stop(void) { #ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB - if (sleep_backup_en && sleep_backup_done) { - + if (s_lp_cntl.mac_bb_pd && s_lp_stat.mac_bb_pd) { btdm_hw_mac_power_up_wrapper(); - // 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); - sleep_backup_done = false; + s_lp_stat.mac_bb_pd = 0; } #endif - - return 0; + return ESP_OK; } esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err; - btdm_controller_mem_init(); - if (esp_register_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop) != 0) { - return ESP_ERR_INVALID_ARG; - } - - 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; - } - - memcpy(osi_funcs_p, &osi_funcs_ro, sizeof(struct osi_funcs_t)); - if (btdm_osi_funcs_register(osi_funcs_p) != 0) { - return ESP_ERR_INVALID_ARG; - } - -#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - bool try_alloc = btdm_deep_sleep_mem_init(); - if(try_alloc) { - sleep_backup_en = true; - } -#endif - if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) { return ESP_ERR_INVALID_STATE; } @@ -1107,9 +1150,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) return ESP_ERR_INVALID_ARG; } - //overwrite some parameters - cfg->magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL; - if (cfg->bluetooth_mode != ESP_BT_MODE_BLE) { ESP_LOGE(BTDM_LOG_TAG, "%s controller only support BLE only mode", __func__); return ESP_ERR_NOT_SUPPORTED; @@ -1129,6 +1169,25 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) } } + //overwrite some parameters + cfg->magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL; + + btdm_controller_mem_init(); + + if (esp_register_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop) != 0) { + return ESP_ERR_INVALID_ARG; + } + + 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; + } + + memcpy(osi_funcs_p, &osi_funcs_ro, sizeof(struct osi_funcs_t)); + if (btdm_osi_funcs_register(osi_funcs_p) != 0) { + return ESP_ERR_INVALID_ARG; + } + read_mac_wrapper(own_bda); ESP_LOGI(BTDM_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version()); @@ -1136,75 +1195,98 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #if CONFIG_SPIRAM_USE_MALLOC btdm_queue_table_mux = xSemaphoreCreateMutex(); if (btdm_queue_table_mux == NULL) { - return ESP_ERR_NO_MEM; + err = ESP_ERR_NO_MEM; + goto error; } memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM); #endif - if (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) { + // init low-power control resources + do { + // set default values for global states or resources + s_lp_stat.val = 0; + s_lp_cntl.val = 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; + + if (s_lp_cntl.enable) { +#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) + if (!btdm_deep_sleep_mem_init()) { + goto error; + } + s_lp_cntl.mac_bb_pd = 1; +#endif +#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) + s_lp_cntl.wakeup_timer_required = 1; +#endif + // async wakeup semaphore for VHCI + s_wakeup_req_sem = semphr_create_wrapper(1, 0); + if (s_wakeup_req_sem == NULL) { + err = ESP_ERR_NO_MEM; + goto error; + } + btdm_vnd_offload_task_register(BTDM_VND_OL_SIG_WAKEUP_TMR, btdm_sleep_exit_phase0); + } + + if (s_lp_cntl.wakeup_timer_required) { + esp_timer_create_args_t create_args = { + .callback = btdm_slp_tmr_callback, + .arg = NULL, + .dispatch_method = ESP_TIMER_ISR, + .name = "btSlp", + }; + if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { + goto error; + } + } + + // set default bluetooth sleep clock cycle and its fractional bits + 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; + + bool select_src_ret, set_div_ret; + if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) { + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); + set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get() * 2); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); + } else { + ESP_LOGW(BTDM_LOG_TAG, "%s sleep clock not supported", __func__); + assert(0); + } + #ifdef CONFIG_PM_ENABLE - if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { - goto error; + if (s_lp_cntl.no_light_sleep) { + if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { + goto error; + } } if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) { goto error; - } - s_pm_lock_sem = semphr_create_wrapper(1, 0); - if (s_pm_lock_sem == NULL) { - err = ESP_ERR_NO_MEM; - goto error; + } else { + s_lp_stat.pm_lock_released = 1; } #endif -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - esp_timer_create_args_t create_args = { - .callback = btdm_slp_tmr_callback, - .arg = NULL, - .dispatch_method = ESP_TIMER_ISR, - .name = "btSlp", - }; - if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { - goto error; - } - btdm_vnd_offload_task_register(BTDM_VND_OL_SIG_WAKEUP_TMR, btdm_sleep_exit_phase0); -#endif + } while (0); - do {// todo: rewrite this block of code for chip - #if CONFIG_IDF_ENV_FPGA - // overwrite the sleep clock for FPGA - cfg->sleep_clock = ESP_BT_SLEEP_CLOCK_FPGA_32K; - ESP_LOGW(BTDM_LOG_TAG, "%s sleep clock overwrite on FPGA", __func__); - #endif - bool select_src_ret = false; - bool set_div_ret = false; - if (cfg->sleep_clock == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) { - select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); - set_div_ret = btdm_lpclk_set_div(rtc_clk_xtal_freq_get() * 2); - 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 (cfg->sleep_clock == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { - 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 = esp_clk_slowclk_cal_get(); - assert(btdm_lpcycle_us != 0); - } else if (cfg->sleep_clock == ESP_BT_SLEEP_CLOCK_FPGA_32K) { - // on FPGA, the low power clock is hard-wired to a 32kHz(clock cycle 31.25us) oscillator - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = 125 << (btdm_lpcycle_us_frac - 2); - } - } while (0); - } #if CONFIG_SW_COEXIST_ENABLE coex_init(); #endif periph_module_enable(PERIPH_BT_MODULE); + #ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB btdm_hw_mac_power_up_wrapper(); #endif - // must do fpga_init and phy init before controller init + esp_phy_enable(); if (btdm_controller_init(cfg) != 0) { @@ -1217,33 +1299,42 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) return ESP_OK; error: + do { + // deinit low power control resources #ifdef CONFIG_PM_ENABLE - if (s_light_sleep_pm_lock != NULL) { - esp_pm_lock_delete(s_light_sleep_pm_lock); - s_light_sleep_pm_lock = NULL; - } - if (s_pm_lock != NULL) { - esp_pm_lock_delete(s_pm_lock); - s_pm_lock = NULL; - } + if (s_lp_cntl.no_light_sleep) { + if (s_light_sleep_pm_lock != NULL) { + esp_pm_lock_delete(s_light_sleep_pm_lock); + s_light_sleep_pm_lock = NULL; + } + } + if (s_pm_lock != NULL) { + esp_pm_lock_delete(s_pm_lock); + s_pm_lock = NULL; + s_lp_stat.pm_lock_released = 0; + } - if (s_pm_lock_sem) { - semphr_delete_wrapper(s_pm_lock_sem); - s_pm_lock_sem = NULL; - } -#endif -#if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - if (s_btdm_slp_tmr != NULL) { - esp_timer_delete(s_btdm_slp_tmr); - s_btdm_slp_tmr = NULL; - } - btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR); #endif + if (s_lp_cntl.wakeup_timer_required && s_btdm_slp_tmr != NULL) { + esp_timer_delete(s_btdm_slp_tmr); + s_btdm_slp_tmr = NULL; + } #if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - btdm_deep_sleep_mem_deinit(); - sleep_backup_en = false; + if (s_lp_cntl.mac_bb_pd) { + btdm_deep_sleep_mem_deinit(); + s_lp_cntl.mac_bb_pd = 0; + } #endif + if (s_lp_cntl.enable) { + btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR); + if (s_wakeup_req_sem != NULL) { + semphr_delete_wrapper(s_wakeup_req_sem); + s_wakeup_req_sem = NULL; + } + } + } while (0); + esp_unregister_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop); return err; } @@ -1255,30 +1346,44 @@ esp_err_t esp_bt_controller_deinit(void) } btdm_controller_deinit(); -#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - btdm_deep_sleep_mem_deinit(); -#endif - esp_unregister_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop); periph_module_disable(PERIPH_BT_MODULE); esp_phy_disable(); + + // deinit low power control resources + do { +#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) + btdm_deep_sleep_mem_deinit(); +#endif #ifdef CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB - btdm_hw_mac_power_down_wrapper(); + btdm_hw_mac_power_down_wrapper(); #endif #ifdef CONFIG_PM_ENABLE - esp_pm_lock_delete(s_light_sleep_pm_lock); - s_light_sleep_pm_lock = NULL; - esp_pm_lock_delete(s_pm_lock); - s_pm_lock = NULL; - semphr_delete_wrapper(s_pm_lock_sem); - s_pm_lock_sem = NULL; -#endif -#if ( defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - esp_timer_stop(s_btdm_slp_tmr); - esp_timer_delete(s_btdm_slp_tmr); - s_btdm_slp_tmr = NULL; - btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR); + if (s_lp_cntl.no_light_sleep) { + esp_pm_lock_delete(s_light_sleep_pm_lock); + s_light_sleep_pm_lock = NULL; + } + + esp_pm_lock_delete(s_pm_lock); + s_pm_lock = NULL; + s_lp_stat.pm_lock_released = 0; #endif + if (s_lp_cntl.wakeup_timer_required) { + esp_timer_stop(s_btdm_slp_tmr); + esp_timer_delete(s_btdm_slp_tmr); + s_btdm_slp_tmr = NULL; + } + + if (s_lp_cntl.enable) { + btdm_vnd_offload_task_deregister(BTDM_VND_OL_SIG_WAKEUP_TMR); + + semphr_delete_wrapper(s_wakeup_req_sem); + s_wakeup_req_sem = NULL; + } + } while (0); + + esp_unregister_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop); + #if CONFIG_SPIRAM_USE_MALLOC vSemaphoreDelete(btdm_queue_table_mux); btdm_queue_table_mux = NULL; @@ -1306,30 +1411,44 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) ESP_LOGE(BTDM_LOG_TAG, "invalid mode %d, controller support mode is %d", mode, btdm_controller_get_mode()); return ESP_ERR_INVALID_ARG; } -#ifdef CONFIG_PM_ENABLE - esp_pm_lock_acquire(s_light_sleep_pm_lock); - esp_pm_lock_acquire(s_pm_lock); -#endif - - // esp_phy_enable(); #if CONFIG_SW_COEXIST_ENABLE coex_enable(); #endif - if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1) { - btdm_controller_enable_sleep(true); - } + // enable low power mode + do { +#ifdef CONFIG_PM_ENABLE + if (s_lp_cntl.no_light_sleep) { + esp_pm_lock_acquire(s_light_sleep_pm_lock); + } + + esp_pm_lock_acquire(s_pm_lock); + s_lp_stat.pm_lock_released = 0; +#endif + + if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1) { + btdm_controller_enable_sleep(true); + } + } while (0); + // inititalize bluetooth baseband btdm_check_and_init_bb(); - ret = btdm_controller_enable(mode); if (ret) { - // esp_phy_disable(); + // disable low power mode + do { + btdm_controller_enable_sleep(false); #ifdef CONFIG_PM_ENABLE - esp_pm_lock_release(s_light_sleep_pm_lock); - esp_pm_lock_release(s_pm_lock); + if (s_lp_cntl.no_light_sleep) { + esp_pm_lock_release(s_light_sleep_pm_lock); + } + if (s_lp_stat.pm_lock_released == 0) { + esp_pm_lock_release(s_pm_lock); + s_lp_stat.pm_lock_released = 1; + } #endif + } while (0); return ESP_ERR_INVALID_STATE; } @@ -1343,28 +1462,36 @@ esp_err_t esp_bt_controller_disable(void) if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { return ESP_ERR_INVALID_STATE; } - // disable modem sleep and wake up from sleep mode - if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1) { - btdm_controller_enable_sleep(false); - if (!btdm_power_state_active()) { - btdm_wakeup_request(); - } - while (!btdm_power_state_active()) { - esp_rom_delay_us(1000); - } - } + + async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_DISA); + btdm_controller_disable(); + async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_DISA); + #if CONFIG_SW_COEXIST_ENABLE coex_disable(); #endif // esp_phy_disable(); btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; + + // disable low power mode + do { #ifdef CONFIG_PM_ENABLE - esp_pm_lock_release(s_light_sleep_pm_lock); - esp_pm_lock_release(s_pm_lock); + if (s_lp_cntl.no_light_sleep) { + esp_pm_lock_release(s_light_sleep_pm_lock); + } + + if (s_lp_stat.pm_lock_released == 0) { + esp_pm_lock_release(s_pm_lock); + s_lp_stat.pm_lock_released = 1; + } else { + assert(0); + } #endif + } while (0); + return ESP_OK; } @@ -1449,18 +1576,6 @@ int IRAM_ATTR esp_bt_h4tl_eif_io_event_notify(int event) return btdm_hci_tl_io_event_post(event); } -void force_wifi_mode(int arg) -{ -} - -void unforce_wifi_mode(void) -{ -} - -void bt_bb_init_cmplx_reg(void) -{ -} - uint16_t esp_bt_get_tx_buf_num(void) { return l2c_ble_link_get_tx_buf_num();