mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Refactor Bluetooth sleep mechanism
Refactor bluetooth hardware PowerUp/PowerDown functions component/bt: fix use of a deprecated MACRO "CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE" component/bt: fix sleep wakeup in controller disable procedure remove use of s_pm_lock_sem 1. Modified the waking up approach from async to sync: post a message to controller task upon vhci downstream packets or controller disable, and in response, controller task goes through the wake-up procedure 2. Added Controller status check for the esp_vhci APIs 3. Adjust the procedure during controller_init, check the validity of arguments first Some minor modifications for bluetooth sleep control and configuration 1. use variable flag s_btdm_allow_light_sleep to control the use of s_light_sleep_pm_lock 2. use variable btdm_lpclk_sel to choose bluetooth sleep clock, support only for external 32kHz crystal temporarily component/bt: improve async_wakeup function 1. check power state first and then decide if wakeup needs to be performed 2. change the meaning of the return value, if wakeup request is posted to controller task, then return true, otherwise return false put sleep control logics in controller init/deinit/enable/disable together Use s_lp_cntl struct: replace bool-typed variable sleep_backup_en with s_lp_cntl.mac_bb_pd Use s_lp_cntl struct: replace bool-typed variable s_btdm_allow_light_sleep with s_lp_cntl.no_light_sleep Use s_lp_cntl struct: replace global variable btdm_lpclk_sel with s_lp_cntl.lpclk_sel create semaphore s_wakeup_req_sem only when low power mode is required Use s_lp_cntl struct: use s_lp_cntl.wakeup_timer_required to control the wakeup timer use s_lp_stat to replace original state variable sleep_backup_done and s_pm_lock_acquired one minor change for mac_bb_pd settings init: return error status if memeory allocation failed
This commit is contained in:
parent
9742aa6f05
commit
086b36d737
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user