mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
Refactor Bluetooth init/deinit mechanism
free osi_funcs struct memory duiring failure of controller_init when necessary components/bt: use s_lp_stat.phy_enabled to control the on/off of phy module clean up style for controller_disable clean up some empty functions and unnecessary comments Added async wakeup src "BTDM_ASYNC_WAKEUP_SRC_TMR" remove use of assert in controller_init, set error code upon some exceptions move stop esp_timer early to phase0, add state variable wakeup_timer_started
This commit is contained in:
@@ -65,6 +65,7 @@
|
||||
enum {
|
||||
BTDM_ASYNC_WAKEUP_SRC_VHCI = 0,
|
||||
BTDM_ASYNC_WAKEUP_SRC_DISA,
|
||||
BTDM_ASYNC_WAKEUP_SRC_TMR,
|
||||
BTDM_ASYNC_WAKEUP_SRC_MAX,
|
||||
};
|
||||
|
||||
@@ -86,7 +87,9 @@ 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 phy_enabled : 1; // whether phy is switched on
|
||||
uint32_t wakeup_timer_started : 1; // whether wakeup timer is started
|
||||
uint32_t reserved : 28; // reserved
|
||||
};
|
||||
uint32_t val;
|
||||
} btdm_lpstat_t;
|
||||
@@ -95,8 +98,6 @@ typedef union {
|
||||
#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
|
||||
|
||||
#define BTDM_MODEM_SLEEP_IN_EFFECT (1)
|
||||
|
||||
#define BT_DEBUG(...)
|
||||
#define BT_API_CALL_CHECK(info, api_call, ret) \
|
||||
do{\
|
||||
@@ -316,6 +317,8 @@ static void interrupt_off_wrapper(int intr_num);
|
||||
static void btdm_hw_mac_power_up_wrapper(void);
|
||||
static void btdm_hw_mac_power_down_wrapper(void);
|
||||
static void btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_mem);
|
||||
|
||||
static void btdm_slp_tmr_callback(void *arg);
|
||||
/* Local variable definition
|
||||
***************************************************************************
|
||||
*/
|
||||
@@ -364,15 +367,10 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
||||
._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,
|
||||
._coex_wifi_sleep_set = coex_wifi_sleep_set_hook,
|
||||
._coex_core_ble_conn_dyn_prio_get = coex_core_ble_conn_dyn_prio_get,
|
||||
._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
|
||||
._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
|
||||
//._coex_bt_release = coex_bt_release_wrapper,
|
||||
// ._coex_register_bt_cb = coex_register_bt_cb_wrapper,
|
||||
// ._coex_bb_reset_lock = coex_bb_reset_lock_wrapper,
|
||||
//._coex_bb_reset_unlock = coex_bb_reset_unlock_wrapper,
|
||||
._interrupt_on = interrupt_on_wrapper,
|
||||
._interrupt_off = interrupt_off_wrapper,
|
||||
._esp_hw_power_down = btdm_hw_mac_power_down_wrapper,
|
||||
@@ -383,37 +381,28 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
||||
static DRAM_ATTR struct osi_funcs_t *osi_funcs_p;
|
||||
|
||||
/* Static variable declare */
|
||||
// timestamp when PHY/RF was switched on
|
||||
// static DRAM_ATTR int64_t s_time_phy_rf_just_enabled = 0;
|
||||
static DRAM_ATTR esp_bt_controller_status_t btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
|
||||
|
||||
static DRAM_ATTR portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
// measured average low power clock period in micro seconds
|
||||
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;
|
||||
// low power status struct
|
||||
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
|
||||
#endif
|
||||
|
||||
// used low power clock
|
||||
// measured average low power clock period in micro seconds
|
||||
static DRAM_ATTR uint32_t btdm_lpcycle_us = 0;
|
||||
// number of fractional bit for btdm_lpcycle_us
|
||||
static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0;
|
||||
// semaphore used for blocking VHCI API to wait for controller to wake up
|
||||
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);
|
||||
|
||||
static inline void btdm_check_and_init_bb(void)
|
||||
{
|
||||
// todo:
|
||||
// btdm_rf_bb_init_phase2();
|
||||
}
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock;
|
||||
// pm_lock to prevent light sleep due to incompatibility currently
|
||||
static DRAM_ATTR esp_pm_lock_handle_t s_light_sleep_pm_lock;
|
||||
#endif
|
||||
|
||||
void btdm_hw_mac_power_down_wrapper(void)
|
||||
{
|
||||
@@ -609,7 +598,7 @@ static void *malloc_internal_wrapper(size_t size)
|
||||
static int IRAM_ATTR read_mac_wrapper(uint8_t mac[6])
|
||||
{
|
||||
int ret = esp_read_mac(mac, ESP_MAC_BT);
|
||||
ESP_LOGI(BTDM_LOG_TAG, "Bluetooth MAC: 0x%02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
ESP_LOGI(BTDM_LOG_TAG, "Bluetooth MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
return ret;
|
||||
@@ -680,17 +669,24 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles)
|
||||
uncertainty = BTDM_MIN_TIMER_UNCERTAINTY_US;
|
||||
}
|
||||
|
||||
if (esp_timer_start_once(s_btdm_slp_tmr, us_to_sleep - uncertainty) != ESP_OK) {
|
||||
ESP_LOGW(BTDM_LOG_TAG, "timer start failed");
|
||||
assert (s_lp_stat.wakeup_timer_started == 0);
|
||||
if (esp_timer_start_once(s_btdm_slp_tmr, us_to_sleep - uncertainty) == ESP_OK) {
|
||||
s_lp_stat.wakeup_timer_started = 1;
|
||||
} else {
|
||||
ESP_LOGE(BTDM_LOG_TAG, "timer start failed");
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
static void btdm_sleep_enter_phase2_wrapper(void)
|
||||
{
|
||||
if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1) {
|
||||
#if BTDM_MODEM_SLEEP_IN_EFFECT
|
||||
esp_phy_disable();
|
||||
#endif /* BTDM_MODEM_SLEEP_IN_EFFECT */
|
||||
if (s_lp_stat.phy_enabled) {
|
||||
esp_phy_disable();
|
||||
s_lp_stat.phy_enabled = 0;
|
||||
} else {
|
||||
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)
|
||||
@@ -715,13 +711,9 @@ static void btdm_sleep_exit_phase3_wrapper(void)
|
||||
assert(0);
|
||||
}
|
||||
if (btdm_controller_get_sleep_mode() == ESP_BT_SLEEP_MODE_1) {
|
||||
#if BTDM_MODEM_SLEEP_IN_EFFECT
|
||||
esp_phy_enable();
|
||||
#endif /* BTDM_MODEM_SLEEP_IN_EFFECT */
|
||||
btdm_check_and_init_bb();
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
if (s_lp_stat.phy_enabled == 0) {
|
||||
esp_phy_enable();
|
||||
s_lp_stat.phy_enabled = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -745,6 +737,10 @@ static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
|
||||
#endif
|
||||
btdm_wakeup_request();
|
||||
|
||||
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;
|
||||
}
|
||||
int event = (int) param;
|
||||
if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI || event == BTDM_ASYNC_WAKEUP_SRC_DISA) {
|
||||
semphr_give_wrapper(s_wakeup_req_sem);
|
||||
@@ -754,8 +750,12 @@ 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)
|
||||
btdm_vnd_offload_post_from_isr(BTDM_VND_OL_SIG_WAKEUP_TMR, NULL, false);
|
||||
#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
|
||||
btdm_vnd_offload_post(BTDM_VND_OL_SIG_WAKEUP_TMR, (void *)BTDM_ASYNC_WAKEUP_SRC_TMR);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -901,7 +901,7 @@ esp_err_t esp_bluetooth_stop(void)
|
||||
|
||||
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_err_t err = ESP_FAIL;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
@@ -936,7 +936,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
//overwrite some parameters
|
||||
// overwrite some parameters
|
||||
cfg->magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL;
|
||||
|
||||
btdm_controller_mem_init();
|
||||
@@ -974,6 +974,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
if (s_lp_cntl.enable) {
|
||||
#if (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB)
|
||||
if (!btdm_deep_sleep_mem_init()) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
s_lp_cntl.mac_bb_pd = 1;
|
||||
@@ -991,10 +992,17 @@ 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) {
|
||||
@@ -1018,16 +1026,19 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac);
|
||||
} else {
|
||||
ESP_LOGW(BTDM_LOG_TAG, "%s sleep clock not supported", __func__);
|
||||
assert(0);
|
||||
err = ESP_ERR_NOT_SUPPORTED;
|
||||
goto error;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
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) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto error;
|
||||
} else {
|
||||
s_lp_stat.pm_lock_released = 1;
|
||||
@@ -1046,6 +1057,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
#endif
|
||||
|
||||
esp_phy_enable();
|
||||
s_lp_stat.phy_enabled = 1;
|
||||
|
||||
if (btdm_controller_init(cfg) != 0) {
|
||||
err = ESP_ERR_NO_MEM;
|
||||
@@ -1057,6 +1069,11 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
return ESP_OK;
|
||||
|
||||
error:
|
||||
if (s_lp_stat.phy_enabled) {
|
||||
esp_phy_disable();
|
||||
s_lp_stat.phy_enabled = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
// deinit low power control resources
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
@@ -1094,6 +1111,11 @@ error:
|
||||
} while (0);
|
||||
|
||||
esp_unregister_shutdown_handler((shutdown_handler_t)esp_bluetooth_stop);
|
||||
|
||||
if (osi_funcs_p != NULL) {
|
||||
free(osi_funcs_p);
|
||||
osi_funcs_p = NULL;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1106,7 +1128,12 @@ esp_err_t esp_bt_controller_deinit(void)
|
||||
btdm_controller_deinit();
|
||||
periph_module_disable(PERIPH_BT_MODULE);
|
||||
|
||||
esp_phy_disable();
|
||||
if (s_lp_stat.phy_enabled) {
|
||||
esp_phy_disable();
|
||||
s_lp_stat.phy_enabled = 0;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// deinit low power control resources
|
||||
do {
|
||||
@@ -1127,7 +1154,10 @@ esp_err_t esp_bt_controller_deinit(void)
|
||||
s_lp_stat.pm_lock_released = 0;
|
||||
#endif
|
||||
if (s_lp_cntl.wakeup_timer_required) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
if (s_lp_stat.wakeup_timer_started) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
}
|
||||
s_lp_stat.wakeup_timer_started = 0;
|
||||
esp_timer_delete(s_btdm_slp_tmr);
|
||||
s_btdm_slp_tmr = NULL;
|
||||
}
|
||||
@@ -1152,7 +1182,7 @@ esp_err_t esp_bt_controller_deinit(void)
|
||||
|
||||
esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
|
||||
{
|
||||
int ret;
|
||||
int ret = ESP_OK;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
@@ -1174,39 +1204,40 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
|
||||
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) {
|
||||
if (s_lp_cntl.enable) {
|
||||
btdm_controller_enable_sleep(true);
|
||||
}
|
||||
} while (0);
|
||||
|
||||
// inititalize bluetooth baseband
|
||||
btdm_check_and_init_bb();
|
||||
ret = btdm_controller_enable(mode);
|
||||
if (ret) {
|
||||
// disable low power mode
|
||||
do {
|
||||
btdm_controller_enable_sleep(false);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
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;
|
||||
if (btdm_controller_enable(mode) != 0) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_ENABLED;
|
||||
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
|
||||
error:
|
||||
// disable low power mode
|
||||
do {
|
||||
btdm_controller_enable_sleep(false);
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
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 ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_controller_disable(void)
|
||||
@@ -1225,7 +1256,6 @@ esp_err_t esp_bt_controller_disable(void)
|
||||
coex_disable();
|
||||
#endif
|
||||
|
||||
// esp_phy_disable();
|
||||
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED;
|
||||
|
||||
// disable low power mode
|
||||
|
Reference in New Issue
Block a user