From 9742aa6f0507a8e7d92ba22f052a0176106a600c Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Mon, 21 Dec 2020 21:02:24 +0800 Subject: [PATCH 1/5] component/bt: handle sleep wakeup event in the context of controller task instead of timer task --- components/bt/controller/esp32c3/bt.c | 30 ++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index f274e27455..27a47f13f5 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -89,6 +89,14 @@ do{\ /* Types definition ************************************************************************ */ +/* vendor dependent signals to be posted to controller task */ +typedef enum { + BTDM_VND_OL_SIG_WAKEUP_TMR = 0, + BTDM_VND_OL_SIG_NUM, +} btdm_vnd_ol_sig_t; + +/* prototype of function to handle vendor dependent signals */ +typedef void (* btdm_vnd_ol_task_func_t)(void *param); /* VHCI function interface */ typedef struct vhci_host_callback { @@ -194,6 +202,13 @@ 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); + +/* 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); +extern int btdm_vnd_offload_task_deregister(btdm_vnd_ol_sig_t sig); +extern int btdm_vnd_offload_post_from_isr(btdm_vnd_ol_sig_t sig, void *param, bool need_yield); +extern int btdm_vnd_offload_post(btdm_vnd_ol_sig_t sig, void *param); + /* Low Power Clock */ extern bool btdm_lpclk_select_src(uint32_t sel); extern bool btdm_lpclk_set_div(uint32_t div); @@ -924,7 +939,7 @@ static void btdm_sleep_exit_phase3_wrapper(void) } #if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) -static void IRAM_ATTR btdm_slp_tmr_callback(void *arg) +static void IRAM_ATTR btdm_sleep_exit_phase0(void *param) { #ifdef CONFIG_PM_ENABLE if (semphr_take_wrapper(s_pm_lock_sem, 0) == pdTRUE) { @@ -938,7 +953,12 @@ static void IRAM_ATTR btdm_slp_tmr_callback(void *arg) sleep_backup_done = false; } #endif +} +static void IRAM_ATTR btdm_slp_tmr_callback(void *arg) +{ + btdm_vnd_offload_post_from_isr(BTDM_VND_OL_SIG_WAKEUP_TMR, NULL, false); + esp_timer_isr_dispatch_need_yield(); } #endif @@ -1139,11 +1159,13 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) esp_timer_create_args_t create_args = { .callback = btdm_slp_tmr_callback, .arg = NULL, - .name = "btSlp" + .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 do {// todo: rewrite this block of code for chip @@ -1211,10 +1233,11 @@ error: } #endif #if (defined CONFIG_PM_ENABLE) || (defined CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) - if (s_btdm_slp_tmr != NULL) { + 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 (CONFIG_PM_POWER_DOWN_WIFI_BT_MAC_BB) @@ -1254,6 +1277,7 @@ esp_err_t esp_bt_controller_deinit(void) 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); #endif #if CONFIG_SPIRAM_USE_MALLOC vSemaphoreDelete(btdm_queue_table_mux); From 086b36d737e53c1b30f72b983f9b054f9233b522 Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Fri, 25 Dec 2020 11:53:08 +0800 Subject: [PATCH 2/5] 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 --- components/bt/controller/esp32c3/bt.c | 569 ++++++++++++++++---------- 1 file changed, 342 insertions(+), 227 deletions(-) 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(); From 06ea8a30280a46af893a1feb8afa8632d138aec4 Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Sat, 26 Dec 2020 23:38:07 +0800 Subject: [PATCH 3/5] remove use of macro "CONFIG_SPIRAM_USE_MALLOC" --- components/bt/controller/esp32c3/bt.c | 248 -------------------------- 1 file changed, 248 deletions(-) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index b43514a8a0..514c9cf37c 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -111,11 +111,6 @@ do{\ #define OSI_VERSION 0x00010006 #define OSI_MAGIC_VALUE 0xFADEBEAD -/* SPIRAM Configuration */ -#if CONFIG_SPIRAM_USE_MALLOC -#define BTDM_MAX_QUEUE_NUM (5) -#endif - /* Types definition ************************************************************************ */ @@ -141,15 +136,6 @@ typedef struct { intptr_t end; } btdm_dram_available_region_t; -/* PSRAM configuration */ -#if CONFIG_SPIRAM_USE_MALLOC -typedef struct { - QueueHandle_t handle; - void *storage; - void *buffer; -} btdm_queue_item_t; -#endif - typedef void (* osi_intr_handler)(void); static uint8_t own_bda[6]; @@ -287,10 +273,6 @@ extern char _bt_tmp_bss_end; /* Local Function Declare ********************************************************************* */ -#if CONFIG_SPIRAM_USE_MALLOC -static bool btdm_queue_generic_register(const btdm_queue_item_t *queue); -static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue); -#endif /* CONFIG_SPIRAM_USE_MALLOC */ static void interrupt_set_wrapper(int cpu_no, int intr_source, int intr_num, int intr_prio); static void interrupt_clear_wrapper(int intr_source, int intr_num); static void interrupt_handler_set_wrapper(int n, intr_handler_t fn, void *arg); @@ -400,11 +382,6 @@ static const struct osi_funcs_t osi_funcs_ro = { static DRAM_ATTR struct osi_funcs_t *osi_funcs_p; -#if CONFIG_SPIRAM_USE_MALLOC -static DRAM_ATTR btdm_queue_item_t btdm_queue_table[BTDM_MAX_QUEUE_NUM]; -static DRAM_ATTR SemaphoreHandle_t btdm_queue_table_mux = NULL; -#endif /* #if CONFIG_SPIRAM_USE_MALLOC */ - /* Static variable declare */ // timestamp when PHY/RF was switched on // static DRAM_ATTR int64_t s_time_phy_rf_just_enabled = 0; @@ -467,52 +444,6 @@ void btdm_backup_dma_copy_wrapper(uint32_t reg, uint32_t mem_addr, uint32_t num, #endif } -#if CONFIG_SPIRAM_USE_MALLOC -static bool btdm_queue_generic_register(const btdm_queue_item_t *queue) -{ - if (!btdm_queue_table_mux || !queue) { - return NULL; - } - - bool ret = false; - btdm_queue_item_t *item; - xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY); - for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) { - item = &btdm_queue_table[i]; - if (item->handle == NULL) { - memcpy(item, queue, sizeof(btdm_queue_item_t)); - ret = true; - break; - } - } - xSemaphoreGive(btdm_queue_table_mux); - return ret; -} - -static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue) -{ - if (!btdm_queue_table_mux || !queue) { - return false; - } - - bool ret = false; - btdm_queue_item_t *item; - xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY); - for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) { - item = &btdm_queue_table[i]; - if (item->handle == queue->handle) { - memcpy(queue, item, sizeof(btdm_queue_item_t)); - memset(item, 0, sizeof(btdm_queue_item_t)); - ret = true; - break; - } - } - xSemaphoreGive(btdm_queue_table_mux); - return ret; -} - -#endif /* CONFIG_SPIRAM_USE_MALLOC */ - static void interrupt_set_wrapper(int cpu_no, int intr_source, int intr_num, int intr_prio) { intr_matrix_route(intr_source, intr_num); @@ -565,63 +496,12 @@ static void IRAM_ATTR task_yield_from_isr(void) static void *semphr_create_wrapper(uint32_t max, uint32_t init) { -#if !CONFIG_SPIRAM_USE_MALLOC return (void *)xSemaphoreCreateCounting(max, init); -#else - StaticQueue_t *queue_buffer = NULL; - QueueHandle_t handle = NULL; - - queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - if (!queue_buffer) { - goto error; - } - - handle = xSemaphoreCreateCountingStatic(max, init, queue_buffer); - if (!handle) { - goto error; - } - - btdm_queue_item_t item = { - .handle = handle, - .storage = NULL, - .buffer = queue_buffer, - }; - - if (!btdm_queue_generic_register(&item)) { - goto error; - } - return handle; - - error: - if (handle) { - vSemaphoreDelete(handle); - } - if (queue_buffer) { - free(queue_buffer); - } - - return NULL; -#endif } static void semphr_delete_wrapper(void *semphr) { -#if !CONFIG_SPIRAM_USE_MALLOC vSemaphoreDelete(semphr); -#else - btdm_queue_item_t item = { - .handle = semphr, - .storage = NULL, - .buffer = NULL, - }; - - if (btdm_queue_generic_deregister(&item)) { - vSemaphoreDelete(item.handle); - free(item.buffer); - } - - return; -#endif } static int IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw) @@ -650,63 +530,12 @@ static int semphr_give_wrapper(void *semphr) static void *mutex_create_wrapper(void) { -#if CONFIG_SPIRAM_USE_MALLOC - StaticQueue_t *queue_buffer = NULL; - QueueHandle_t handle = NULL; - - queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - if (!queue_buffer) { - goto error; - } - - handle = xSemaphoreCreateMutexStatic(queue_buffer); - if (!handle) { - goto error; - } - - btdm_queue_item_t item = { - .handle = handle, - .storage = NULL, - .buffer = queue_buffer, - }; - - if (!btdm_queue_generic_register(&item)) { - goto error; - } - return handle; - - error: - if (handle) { - vSemaphoreDelete(handle); - } - if (queue_buffer) { - free(queue_buffer); - } - - return NULL; -#else return (void *)xSemaphoreCreateMutex(); -#endif } static void mutex_delete_wrapper(void *mutex) { -#if !CONFIG_SPIRAM_USE_MALLOC vSemaphoreDelete(mutex); -#else - btdm_queue_item_t item = { - .handle = mutex, - .storage = NULL, - .buffer = NULL, - }; - - if (btdm_queue_generic_deregister(&item)) { - vSemaphoreDelete(item.handle); - free(item.buffer); - } - - return; -#endif } static int mutex_lock_wrapper(void *mutex) @@ -721,74 +550,12 @@ static int mutex_unlock_wrapper(void *mutex) static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size) { -#if CONFIG_SPIRAM_USE_MALLOC - StaticQueue_t *queue_buffer = NULL; - uint8_t *queue_storage = NULL; - QueueHandle_t handle = NULL; - - queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - if (!queue_buffer) { - goto error; - } - - queue_storage = heap_caps_malloc((queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); - if (!queue_storage ) { - goto error; - } - - handle = xQueueCreateStatic(queue_len, item_size, queue_storage, queue_buffer); - if (!handle) { - goto error; - } - - btdm_queue_item_t item = { - .handle = handle, - .storage = queue_storage, - .buffer = queue_buffer, - }; - - if (!btdm_queue_generic_register(&item)) { - goto error; - } - - return handle; - - error: - if (handle) { - vQueueDelete(handle); - } - if (queue_storage) { - free(queue_storage); - } - if (queue_buffer) { - free(queue_buffer); - } - - return NULL; -#else return (void *)xQueueCreate(queue_len, item_size); -#endif } static void queue_delete_wrapper(void *queue) { -#if !CONFIG_SPIRAM_USE_MALLOC vQueueDelete(queue); -#else - btdm_queue_item_t item = { - .handle = queue, - .storage = NULL, - .buffer = NULL, - }; - - if (btdm_queue_generic_deregister(&item)) { - vQueueDelete(item.handle); - free(item.storage); - free(item.buffer); - } - - return; -#endif } static int queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms) @@ -1192,15 +959,6 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGI(BTDM_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version()); -#if CONFIG_SPIRAM_USE_MALLOC - btdm_queue_table_mux = xSemaphoreCreateMutex(); - if (btdm_queue_table_mux == NULL) { - err = ESP_ERR_NO_MEM; - goto error; - } - memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM); -#endif - // init low-power control resources do { // set default values for global states or resources @@ -1384,12 +1142,6 @@ esp_err_t esp_bt_controller_deinit(void) 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; - memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM); -#endif - free(osi_funcs_p); osi_funcs_p = NULL; From ee480b77760e3e2503c72c808d496aa6514101fc Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Sat, 26 Dec 2020 23:44:23 +0800 Subject: [PATCH 4/5] 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 --- components/bt/controller/esp32c3/bt.c | 170 +++++++++++++++----------- 1 file changed, 100 insertions(+), 70 deletions(-) diff --git a/components/bt/controller/esp32c3/bt.c b/components/bt/controller/esp32c3/bt.c index 514c9cf37c..1970529297 100644 --- a/components/bt/controller/esp32c3/bt.c +++ b/components/bt/controller/esp32c3/bt.c @@ -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 From eef66789d443a9fa05c8c2dda478159a0bb4628b Mon Sep 17 00:00:00 2001 From: baohongde Date: Thu, 28 Jan 2021 22:28:04 +0800 Subject: [PATCH 5/5] Mac BB power down in light sleep components/bt: Do not use feature: timer support isr dispatch method disable controller after wake up finished. protect critical section of power down choose clk in sleep components/coex: mac bb power down in light sleep components/coex: Macro changed components/os: protect reserved interrupt number update phy to phy_version 300,6e46ba7,Jan 25 2021 some bugfix --- components/bt/controller/esp32c3/Kconfig.in | 17 ++ components/bt/controller/esp32c3/bt.c | 169 +++++++++++------- components/bt/controller/lib | 2 +- .../bt/include/esp32c3/include/esp_bt.h | 3 +- components/esp_rom/esp32c3/ld/esp32c3.rom.ld | 1 + components/esp_system/include/esp_sleep.h | 45 +++++ components/esp_system/sleep_modes.c | 97 ++++++++++ components/esp_wifi/Kconfig | 2 +- components/esp_wifi/include/esp_phy_init.h | 1 + .../esp_wifi/include/esp_private/wifi.h | 10 ++ components/esp_wifi/lib | 2 +- components/esp_wifi/src/phy_init.c | 10 +- components/esp_wifi/src/wifi_init.c | 29 ++- components/hal/interrupt_controller_hal.c | 4 +- components/soc/esp32c3/include/soc/soc.h | 26 +-- 15 files changed, 327 insertions(+), 91 deletions(-) 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 ************************************************************************************************************* */