diff options
Diffstat (limited to 'lib/bt/controller/esp32/bt.c')
| -rw-r--r-- | lib/bt/controller/esp32/bt.c | 313 |
1 files changed, 222 insertions, 91 deletions
diff --git a/lib/bt/controller/esp32/bt.c b/lib/bt/controller/esp32/bt.c index f26dd4bc..4f95d120 100644 --- a/lib/bt/controller/esp32/bt.c +++ b/lib/bt/controller/esp32/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +48,10 @@ #include "esp_rom_sys.h" #include "hli_api.h" +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED +#include "ble_log/ble_log_spi_out.h" +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + #if CONFIG_BT_ENABLED /* Macro definition @@ -96,6 +100,7 @@ do{\ #define OSI_VERSION 0x00010005 #define OSI_MAGIC_VALUE 0xFADEBEAD +#define BLE_CONTROLLER_MALLOC_CAPS (MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL) /* Types definition ************************************************************************ */ @@ -248,6 +253,16 @@ extern void config_bt_funcs_reset(void); extern void config_ble_funcs_reset(void); extern void config_btdm_funcs_reset(void); +#ifdef CONFIG_BT_BLUEDROID_ENABLED +extern void bt_stack_enableSecCtrlVsCmd(bool en); +#endif // CONFIG_BT_BLUEDROID_ENABLED +#if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) +extern void bt_stack_enableCoexVsCmd(bool en); +extern void scan_stack_enableAdvFlowCtrlVsCmd(bool en); +extern void adv_stack_enableClearLegacyAdvVsCmd(bool en); +extern void advFilter_stack_enableDupExcListVsCmd(bool en); +#endif // (CONFIG_BT_NIMBLE_ENABLED) || (CONFIG_BT_BLUEDROID_ENABLED) + /* Local Function Declare ********************************************************************* */ @@ -448,7 +463,11 @@ static DRAM_ATTR uint8_t btdm_lpcycle_us_frac = 0; // number of fractional bit f #if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG // used low power clock -static DRAM_ATTR uint8_t btdm_lpclk_sel; +#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL +static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL; +#else +static DRAM_ATTR uint8_t btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL; +#endif /* CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL */ #endif /* #ifdef CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG */ static DRAM_ATTR QueueHandle_t s_wakeup_req_sem = NULL; @@ -868,7 +887,21 @@ static int IRAM_ATTR cause_sw_intr_to_core_wrapper(int core_id, int intr_no) static void *malloc_internal_wrapper(size_t size) { - return heap_caps_malloc(size, MALLOC_CAP_8BIT|MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL); + return heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); +} + +void *malloc_ble_controller_mem(size_t size) +{ + void *p = heap_caps_malloc(size, BLE_CONTROLLER_MALLOC_CAPS); + if(p == NULL) { + ESP_LOGE(BTDM_LOG_TAG, "Malloc failed"); + } + return p; +} + +uint32_t get_ble_controller_free_heap_size(void) +{ + return heap_caps_get_free_size(BLE_CONTROLLER_MALLOC_CAPS); } static int32_t IRAM_ATTR read_mac_wrapper(uint8_t mac[6]) @@ -932,7 +965,7 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles) assert(us_to_sleep > BTDM_MIN_TIMER_UNCERTAINTY_US); // allow a maximum time uncertainty to be about 488ppm(1/2048) at least as clock drift // and set the timer in advance - uint32_t uncertainty = (us_to_sleep >> 11); + uint32_t uncertainty = (us_to_sleep / 1000); if (uncertainty < BTDM_MIN_TIMER_UNCERTAINTY_US) { uncertainty = BTDM_MIN_TIMER_UNCERTAINTY_US; } @@ -1027,9 +1060,8 @@ static bool async_wakeup_request(int event) switch (event) { case BTDM_ASYNC_WAKEUP_REQ_HCI: - btdm_in_wakeup_requesting_set(true); - // NO break case BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA: + btdm_in_wakeup_requesting_set(true); if (!btdm_power_state_active()) { do_wakeup_request = true; @@ -1062,10 +1094,10 @@ static void async_wakeup_request_end(int event) bool request_lock = false; switch (event) { case BTDM_ASYNC_WAKEUP_REQ_HCI: + case BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA: request_lock = true; break; case BTDM_ASYNC_WAKEUP_REQ_COEX: - case BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA: request_lock = false; break; default: @@ -1330,7 +1362,8 @@ static esp_err_t esp_bt_controller_rom_mem_release(esp_bt_mode_t mode) //already released if (!(mode & btdm_dram_available_region[0].mode)) { - return ESP_ERR_INVALID_STATE; + ESP_LOGW(BTDM_LOG_TAG, "%s already released, mode %d",__func__, mode); + return ESP_OK; } for (int i = 0; i < sizeof(btdm_dram_available_region)/sizeof(btdm_dram_available_region_t); i++) { @@ -1432,6 +1465,14 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) .name = "BT Controller Data" }; + /* + * Free data and BSS section for Bluetooth controller ROM code. + * Note that rom mem release must be performed before section _bt_data_start to _bt_data_end is released, + * otherwise `btdm_dram_available_region` will no longer be available when performing rom mem release and + * thus causing heap corruption. + */ + ret = esp_bt_controller_rom_mem_release(mode); + if (mode == ESP_BT_MODE_BTDM) { /* Start by freeing Bluetooth BSS section */ if (ret == ESP_OK) { @@ -1444,11 +1485,6 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) } } - /* free data and BSS section for Bluetooth controller ROM code */ - if (ret == ESP_OK) { - ret = esp_bt_controller_rom_mem_release(mode); - } - return ret; } @@ -1472,6 +1508,117 @@ static void hli_queue_setup_pinned_to_core(int core_id) } #endif /* CONFIG_BTDM_CTRL_HLI */ +// init low-power control resources +static esp_err_t btdm_low_power_mode_init(void) +{ + esp_err_t err = ESP_OK; + +#ifdef CONFIG_PM_ENABLE + s_btdm_allow_light_sleep = false; +#endif + + // set default sleep clock cycle and its fractional bits + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); + +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { + // check whether or not EXT_CRYS is working + if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { +#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"); + btdm_lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL; // set default value + } + } else if (btdm_lpclk_sel != ESP_BT_SLEEP_CLOCK_MAIN_XTAL) { + assert(0); + } + + bool select_src_ret __attribute__((unused)); + bool set_div_ret __attribute__((unused)); + if (btdm_lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) { + select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); + set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1); + assert(select_src_ret && set_div_ret); + btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; + btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); + } else { // btdm_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); + } + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); + +#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); +#else + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +#endif + +#ifdef CONFIG_PM_ENABLE + if (!s_btdm_allow_light_sleep) { + if ((err = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "btLS", &s_light_sleep_pm_lock)) != ESP_OK) { + return err; + } + } + if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) { + return err; + } + esp_timer_create_args_t create_args = { + .callback = btdm_slp_tmr_callback, + .arg = NULL, + .name = "btSlp" + }; + if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { + return err; + } + + s_pm_lock_acquired = true; +#endif + + return err; +} + +esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void) +{ +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED && + btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { + return ESP_BT_SLEEP_CLOCK_NONE; + } + return btdm_lpclk_sel; +#else + return ESP_BT_SLEEP_CLOCK_NONE; +#endif +} + +esp_err_t esp_bt_set_lpclk_src(esp_bt_sleep_clock_t lpclk) +{ +#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG + if (lpclk < ESP_BT_SLEEP_CLOCK_MAIN_XTAL || lpclk > ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { + return ESP_ERR_INVALID_ARG; + } + + if (btdm_controller_status == ESP_BT_CONTROLLER_STATUS_INITED || + btdm_controller_status == ESP_BT_CONTROLLER_STATUS_ENABLED) { + ESP_LOGW(BTDM_LOG_TAG, "Please set the Bluetooth sleep clock source before Bluetooth initialization"); + return ESP_ERR_INVALID_STATE; + } + + btdm_lpclk_sel = lpclk; + return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif +} + esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) { esp_err_t err; @@ -1534,58 +1681,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) btdm_controller_mem_init(); periph_module_enable(PERIPH_BT_MODULE); - -#ifdef CONFIG_PM_ENABLE - s_btdm_allow_light_sleep = false; -#endif - - // set default sleep clock cycle and its fractional bits - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - -#if CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG - - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value -#if CONFIG_BTDM_CTRL_LPCLK_SEL_EXT_32K_XTAL - // check whether or not EXT_CRYS is working - if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_XTAL32K) { - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32kHz XTAL -#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"); - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value - } -#else - btdm_lpclk_sel = BTDM_LPCLK_SEL_XTAL; // set default value -#endif - - bool select_src_ret __attribute__((unused)); - bool set_div_ret __attribute__((unused)); - if (btdm_lpclk_sel == BTDM_LPCLK_SEL_XTAL) { - select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL); - set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() * 2 / MHZ - 1); - assert(select_src_ret && set_div_ret); - btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT; - btdm_lpcycle_us = 2 << (btdm_lpcycle_us_frac); - } else { // btdm_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); - } - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_ORIG); - -#elif CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_EVED); -#else - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); -#endif + periph_module_reset(PERIPH_BT_MODULE); #if CONFIG_BTDM_CTRL_HCI_UART_FLOW_CTRL_EN sdk_config_set_uart_flow_ctrl_enable(true); @@ -1593,44 +1689,53 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) sdk_config_set_uart_flow_ctrl_enable(false); #endif -#ifdef CONFIG_PM_ENABLE - if (!s_btdm_allow_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; - } - esp_timer_create_args_t create_args = { - .callback = btdm_slp_tmr_callback, - .arg = NULL, - .name = "btSlp" - }; - if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) { + if ((err = btdm_low_power_mode_init()) != ESP_OK) { + ESP_LOGE(BTDM_LOG_TAG, "Low power module initialization failed"); goto error; } - s_pm_lock_acquired = true; -#endif - #if CONFIG_SW_COEXIST_ENABLE coex_init(); #endif +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + if (ble_log_spi_out_init() != 0) { + ESP_LOGE(BTDM_LOG_TAG, "BLE Log SPI output init failed"); + err = ESP_ERR_NO_MEM; + goto error; + } +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + btdm_cfg_mask = btdm_config_mask_load(); - if (btdm_controller_init(btdm_cfg_mask, cfg) != 0) { + err = btdm_controller_init(btdm_cfg_mask, cfg); + + if (err != 0) { + ESP_LOGE(BTDM_LOG_TAG, "%s %d\n",__func__,err); err = ESP_ERR_NO_MEM; goto error; } +#ifdef CONFIG_BT_BLUEDROID_ENABLED + bt_stack_enableSecCtrlVsCmd(true); +#endif // CONFIG_BT_BLUEDROID_ENABLED +#if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) + bt_stack_enableCoexVsCmd(true); + scan_stack_enableAdvFlowCtrlVsCmd(true); + adv_stack_enableClearLegacyAdvVsCmd(true); + advFilter_stack_enableDupExcListVsCmd(true); +#endif // (CONFIG_BT_NIMBLE_ENABLED) || (CONFIG_BT_BLUEDROID_ENABLED) + btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; return ESP_OK; error: +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + bt_controller_deinit_internal(); return err; @@ -1642,17 +1747,30 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_ERR_INVALID_STATE; } +#if CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + ble_log_spi_out_deinit(); +#endif // CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED + btdm_controller_deinit(); bt_controller_deinit_internal(); +#ifdef CONFIG_BT_BLUEDROID_ENABLED + bt_stack_enableSecCtrlVsCmd(false); +#endif // CONFIG_BT_BLUEDROID_ENABLED +#if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) + bt_stack_enableCoexVsCmd(false); + scan_stack_enableAdvFlowCtrlVsCmd(false); + adv_stack_enableClearLegacyAdvVsCmd(false); + advFilter_stack_enableDupExcListVsCmd(false); +#endif // (CONFIG_BT_NIMBLE_ENABLED) || (CONFIG_BT_BLUEDROID_ENABLED) + return ESP_OK; } -static void bt_controller_deinit_internal(void) +// deinit low power control resources +static void btdm_low_power_mode_deinit(void) { - periph_module_disable(PERIPH_BT_MODULE); - #ifdef CONFIG_PM_ENABLE if (!s_btdm_allow_light_sleep) { esp_pm_lock_delete(s_light_sleep_pm_lock); @@ -1673,6 +1791,16 @@ static void bt_controller_deinit_internal(void) s_pm_lock_acquired = false; #endif + btdm_lpcycle_us = 0; + btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); +} + +static void bt_controller_deinit_internal(void) +{ + periph_module_disable(PERIPH_BT_MODULE); + + btdm_low_power_mode_deinit(); + if (s_wakeup_req_sem) { semphr_delete_wrapper(s_wakeup_req_sem); s_wakeup_req_sem = NULL; @@ -1685,9 +1813,6 @@ static void bt_controller_deinit_internal(void) btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE; - btdm_lpcycle_us = 0; - btdm_controller_set_sleep_mode(BTDM_MODEM_SLEEP_MODE_NONE); - esp_bt_power_domain_off(); esp_phy_modem_deinit(); @@ -1798,6 +1923,7 @@ esp_err_t esp_bt_controller_disable(void) while (!btdm_power_state_active()) { esp_rom_delay_us(1000); } + async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_CTRL_DISA); } btdm_controller_disable(); @@ -1910,7 +2036,7 @@ esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path) return ESP_OK; } -esp_err_t esp_ble_scan_dupilcate_list_flush(void) +esp_err_t esp_ble_scan_duplicate_list_flush(void) { if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) { return ESP_ERR_INVALID_STATE; @@ -1919,6 +2045,11 @@ esp_err_t esp_ble_scan_dupilcate_list_flush(void) return ESP_OK; } +esp_err_t esp_ble_scan_dupilcate_list_flush(void) +{ + return esp_ble_scan_duplicate_list_flush(); +} + /** * This function re-write controller's function, * As coredump can not show parameters in function which is in a .a file. |
