Update bt fork to be based on v5.3

This commit is contained in:
jacqueline
2024-08-13 06:02:54 +00:00
committed by cooljqln
parent be9725c1c7
commit 5a02f34ed9
508 changed files with 42429 additions and 5168 deletions
+17 -3
View File
@@ -23,7 +23,7 @@ config BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB
default 0
help
BLE ACL buffer have two methods to be allocated. One is persistent allocating
(alloate when controller initialise, never free until controller de-initialise)
(allocate when controller initialise, never free until controller de-initialise)
another is dynamically allocating (allocate before TX and free after TX).
choice BT_CTRL_PINNED_TO_CORE_CHOICE
@@ -72,11 +72,11 @@ config BT_CTRL_HCI_TL
HCI mode as VHCI or UART(H4)
config BT_CTRL_ADV_DUP_FILT_MAX
int "The maxinum number of 5.0 extend duplicate scan filter"
int "The maximum number of 5.0 extend duplicate scan filter"
range 1 500
default 30
help
The maxinum number of suplicate scan filter
The maximum number of suplicate scan filter
choice BT_BLE_CCA_MODE
prompt "BLE CCA mode"
@@ -475,3 +475,17 @@ config BT_BLE_ADV_DATA_LENGTH_ZERO_AUX
When this option is enabled, auxiliary packets will be present in the events of
'Non-Connectable and Non-Scannable' regardless of whether the advertising length is 0.
If this option is not enabled, auxiliary packets will only be present when the advertising length is not 0.
config BT_CTRL_CHAN_ASS_EN
bool "Enable channel assessment"
default y
help
If this option is enabled, The Controller will records the communication quality
for each channel and then start a timer to check and update the channel map every 4 seconds.
config BT_CTRL_LE_PING_EN
bool "Enable LE Ping procedure"
default y
help
If this option is disabled, The Controller will not start the LE authenticated payload timer.
This option is used for some compatibility problems related to LE ping procedure.
+478 -330
View File
@@ -22,7 +22,10 @@
#include "esp_random.h"
#include "esp_task.h"
#include "esp_attr.h"
#ifdef CONFIG_ESP_PHY_ENABLED
#include "esp_phy_init.h"
#include "esp_private/phy.h"
#endif
#include "esp_bt.h"
#include "esp_err.h"
#include "esp_log.h"
@@ -34,11 +37,12 @@
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/soc_memory_layout.h"
#ifdef CONFIG_ESP_COEX_ENABLED
#include "private/esp_coexist_internal.h"
#endif
#include "esp_timer.h"
#include "esp_sleep.h"
#include "esp_rom_sys.h"
#include "esp_private/phy.h"
#if CONFIG_IDF_TARGET_ESP32C3
#include "riscv/interrupt.h"
#include "esp32c3/rom/rom_layout.h"
@@ -64,6 +68,7 @@
// wakeup request sources
enum {
BTDM_ASYNC_WAKEUP_SRC_VHCI = 0,
BTDM_ASYNC_WAKEUP_REQ_COEX,
BTDM_ASYNC_WAKEUP_SRC_DISA,
BTDM_ASYNC_WAKEUP_SRC_TMR,
BTDM_ASYNC_WAKEUP_SRC_MAX,
@@ -73,12 +78,12 @@ enum {
typedef union {
struct {
uint32_t enable : 1; // whether low power mode is required
uint32_t lpclk_sel : 2; // low power clock source
uint32_t lpclk_sel : 3; // 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 main_xtal_pu : 1; // power up main XTAL
uint32_t reserved : 25; // reserved
uint32_t reserved : 24; // reserved
};
uint32_t val;
} btdm_lpcntl_t;
@@ -110,7 +115,7 @@ do{\
} while(0)
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
#define OSI_VERSION 0x00010007
#define OSI_VERSION 0x00010008
#define OSI_MAGIC_VALUE 0xFADEBEAD
/* Types definition
@@ -184,8 +189,12 @@ struct osi_funcs_t {
void (* _btdm_sleep_exit_phase3)(void); /* called from task */
void (* _coex_wifi_sleep_set)(bool sleep);
int (* _coex_core_ble_conn_dyn_prio_get)(bool *low, bool *high);
int (* _coex_schm_register_btdm_callback)(void *callback);
void (* _coex_schm_status_bit_set)(uint32_t type, uint32_t status);
void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
uint32_t (* _coex_schm_interval_get)(void);
uint8_t (* _coex_schm_curr_period_get)(void);
void *(* _coex_schm_curr_phase_get)(void);
void (* _interrupt_on)(int intr_num);
void (* _interrupt_off)(int intr_num);
void (* _esp_hw_power_down)(void);
@@ -193,6 +202,8 @@ struct osi_funcs_t {
void (* _ets_backup_dma_copy)(uint32_t reg, uint32_t mem_addr, uint32_t num, bool to_rem);
void (* _ets_delay_us)(uint32_t us);
void (* _btdm_rom_table_ready)(void);
bool (* _coex_bt_wakeup_request)(void);
void (* _coex_bt_wakeup_request_end)(void);
};
@@ -256,16 +267,12 @@ extern void btdm_cca_feature_enable(void);
extern uint32_t _bt_bss_start;
extern uint32_t _bt_bss_end;
extern uint32_t _btdm_bss_start;
extern uint32_t _btdm_bss_end;
extern uint32_t _nimble_bss_start;
extern uint32_t _nimble_bss_end;
extern uint32_t _bt_controller_bss_start;
extern uint32_t _bt_controller_bss_end;
extern uint32_t _bt_data_start;
extern uint32_t _bt_data_end;
extern uint32_t _btdm_data_start;
extern uint32_t _btdm_data_end;
extern uint32_t _nimble_data_start;
extern uint32_t _nimble_data_end;
extern uint32_t _bt_controller_data_start;
extern uint32_t _bt_controller_data_end;
/* Local Function Declare
*********************************************************************
@@ -306,14 +313,20 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles);
static void btdm_sleep_enter_phase2_wrapper(void);
static void btdm_sleep_exit_phase3_wrapper(void);
static void coex_wifi_sleep_set_hook(bool sleep);
static int coex_schm_register_btdm_callback_wrapper(void *callback);
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status);
static uint32_t coex_schm_interval_get_wrapper(void);
static uint8_t coex_schm_curr_period_get_wrapper(void);
static void * coex_schm_curr_phase_get_wrapper(void);
static void interrupt_on_wrapper(int intr_num);
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_funcs_table_ready_wrapper(void);
static bool coex_bt_wakeup_request(void);
static void coex_bt_wakeup_request_end(void);
static void btdm_slp_tmr_callback(void *arg);
@@ -371,8 +384,12 @@ static const struct osi_funcs_t osi_funcs_ro = {
._btdm_sleep_exit_phase3 = btdm_sleep_exit_phase3_wrapper,
._coex_wifi_sleep_set = coex_wifi_sleep_set_hook,
._coex_core_ble_conn_dyn_prio_get = NULL,
._coex_schm_register_btdm_callback = coex_schm_register_btdm_callback_wrapper,
._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
._coex_schm_interval_get = coex_schm_interval_get_wrapper,
._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper,
._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
._interrupt_on = interrupt_on_wrapper,
._interrupt_off = interrupt_off_wrapper,
._esp_hw_power_down = btdm_hw_mac_power_down_wrapper,
@@ -380,6 +397,8 @@ static const struct osi_funcs_t osi_funcs_ro = {
._ets_backup_dma_copy = btdm_backup_dma_copy_wrapper,
._ets_delay_us = esp_rom_delay_us,
._btdm_rom_table_ready = btdm_funcs_table_ready_wrapper,
._coex_bt_wakeup_request = coex_bt_wakeup_request,
._coex_bt_wakeup_request_end = coex_bt_wakeup_request_end,
};
static DRAM_ATTR struct osi_funcs_t *osi_funcs_p;
@@ -400,7 +419,7 @@ 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 DRAM_ATTR esp_timer_handle_t s_btdm_slp_tmr = NULL;
#ifdef CONFIG_PM_ENABLE
static DRAM_ATTR esp_pm_lock_handle_t s_pm_lock;
@@ -463,9 +482,8 @@ static void interrupt_set_wrapper(int cpu_no, int intr_source, int intr_num, int
{
esp_rom_route_intr_matrix(cpu_no, intr_source, intr_num);
#if __riscv
esprv_intc_int_set_priority(intr_num, intr_prio);
//esprv_intc_int_enable_level(1 << intr_num);
esprv_intc_int_set_type(intr_num, 0);
esprv_int_set_priority(intr_num, intr_prio);
esprv_int_set_type(intr_num, 0);
#endif
}
@@ -637,7 +655,7 @@ static int IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *
static int task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id)
{
return (uint32_t)xTaskCreatePinnedToCore(task_func, name, stack_depth, param, prio, task_handle, (core_id < portNUM_PROCESSORS ? core_id : tskNO_AFFINITY));
return (uint32_t)xTaskCreatePinnedToCore(task_func, name, stack_depth, param, prio, task_handle, (core_id < CONFIG_FREERTOS_NUMBER_OF_CORES ? core_id : tskNO_AFFINITY));
}
static void task_delete_wrapper(void *task_handle)
@@ -853,6 +871,22 @@ static bool async_wakeup_request(int event)
semphr_take_wrapper(s_wakeup_req_sem, OSI_FUNCS_TIME_BLOCKING);
}
break;
case BTDM_ASYNC_WAKEUP_REQ_COEX:
if (!btdm_power_state_active()) {
do_wakeup_request = true;
#if CONFIG_PM_ENABLE
if (s_lp_stat.pm_lock_released) {
esp_pm_lock_acquire(s_pm_lock);
s_lp_stat.pm_lock_released = 0;
}
#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;
}
}
default:
break;
}
@@ -872,6 +906,9 @@ static void async_wakeup_request_end(int event)
case BTDM_ASYNC_WAKEUP_SRC_DISA:
allow_to_sleep = true;
break;
case BTDM_ASYNC_WAKEUP_REQ_COEX:
allow_to_sleep = false;
break;
default:
allow_to_sleep = true;
break;
@@ -891,18 +928,25 @@ static void btdm_funcs_table_ready_wrapper(void)
#endif
}
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
bool bt_async_wakeup_request(void)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_schm_status_bit_set(type, status);
#endif
return async_wakeup_request(BTDM_ASYNC_WAKEUP_SRC_VHCI);
}
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status)
void bt_wakeup_request_end(void)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_schm_status_bit_clear(type, status);
#endif
async_wakeup_request_end(BTDM_ASYNC_WAKEUP_SRC_VHCI);
}
static bool coex_bt_wakeup_request(void)
{
return async_wakeup_request(BTDM_ASYNC_WAKEUP_REQ_COEX);
}
static void coex_bt_wakeup_request_end(void)
{
async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_COEX);
return;
}
bool esp_vhci_host_check_send_available(void)
@@ -939,145 +983,175 @@ static void btdm_controller_mem_init(void)
btdm_controller_rom_data_init();
}
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
/**
* Release two memory areas to the heap. If both areas are consecutive, they will be released as
* a single area.
*/
typedef struct {
intptr_t start;
intptr_t end;
const char* name;
} bt_area_t;
static esp_err_t esp_bt_mem_release_area(const bt_area_t *area)
{
intptr_t mem_start=(intptr_t) NULL, mem_end=(intptr_t) NULL;
esp_err_t ret = ESP_OK;
intptr_t mem_start = area->start;
intptr_t mem_end = area->end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release %s [0x%08x] - [0x%08x], len %d", area->name, mem_start, mem_end, mem_end - mem_start);
ret = try_heap_caps_add_region(mem_start, mem_end);
}
return ret;
}
static esp_err_t esp_bt_mem_release_areas(const bt_area_t *area1, const bt_area_t *area2)
{
esp_err_t ret = ESP_OK;
if (area1->end == area2->start) {
bt_area_t merged_area = {
.start = area1->start,
.end = area2->end,
.name = area1->name
};
ret = esp_bt_mem_release_area(&merged_area);
} else {
esp_bt_mem_release_area(area1);
ret = esp_bt_mem_release_area(area2);
}
return ret;
}
esp_err_t esp_bt_controller_rom_mem_release(esp_bt_mode_t mode)
{
esp_err_t ret = ESP_OK;
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
return ESP_ERR_INVALID_STATE;
}
if (mode & ESP_BT_MODE_BLE) {
/* if the addresses of rom btdm .data and .bss are consecutive,
they are registered in the system heap as a piece of memory
*/
if(ets_rom_layout_p->data_end_btdm == ets_rom_layout_p->bss_start_btdm) {
mem_start = (intptr_t)ets_rom_layout_p->data_start_btdm;
mem_end = (intptr_t)ets_rom_layout_p->bss_end_btdm;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release rom btdm [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
} else {
mem_start = (intptr_t)ets_rom_layout_p->bss_start_btdm;
mem_end = (intptr_t)ets_rom_layout_p->bss_end_btdm;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release rom btdm BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
mem_start = (intptr_t)ets_rom_layout_p->data_start_btdm;
mem_end = (intptr_t)ets_rom_layout_p->data_end_btdm;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release rom btdm Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
}
/* if the addresses of rom interface btdm .data and .bss are consecutive,
they are registered in the system heap as a piece of memory
*/
if(ets_rom_layout_p->data_end_interface_btdm == ets_rom_layout_p->bss_start_interface_btdm) {
mem_start = (intptr_t)ets_rom_layout_p->data_start_interface_btdm;
mem_end = (intptr_t)ets_rom_layout_p->bss_end_interface_btdm;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release rom interface btdm [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
} else {
mem_start = (intptr_t)ets_rom_layout_p->data_start_interface_btdm;
mem_end = (intptr_t)ets_rom_layout_p->data_end_interface_btdm;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release rom interface btdm Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
mem_start = (intptr_t)ets_rom_layout_p->bss_start_interface_btdm;
mem_end = (intptr_t)ets_rom_layout_p->bss_end_interface_btdm;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release rom interface btdm BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
}
bt_area_t rom_btdm_data = {
.start = (intptr_t) ets_rom_layout_p->data_start_btdm,
.end = (intptr_t) ets_rom_layout_p->data_end_btdm,
.name = "ROM btdm data",
};
bt_area_t rom_btdm_bss = {
.start = (intptr_t)ets_rom_layout_p->bss_start_btdm,
.end = (intptr_t)ets_rom_layout_p->bss_end_btdm,
.name = "ROM btdm BSS",
};
bt_area_t rom_btdm_inter_data = {
.start = (intptr_t) ets_rom_layout_p->data_start_interface_btdm,
.end = (intptr_t) ets_rom_layout_p->data_end_interface_btdm,
.name = "ROM interface btdm data",
};
bt_area_t rom_btdm_inter_bss = {
.start = (intptr_t)ets_rom_layout_p->bss_start_interface_btdm,
.end = (intptr_t)ets_rom_layout_p->bss_end_interface_btdm,
.name = "ROM interface btdm BSS",
};
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
ret = ESP_ERR_INVALID_STATE;
}
return ESP_OK;
if (mode & ESP_BT_MODE_BLE) {
/* Free BTDM memory used by the ROM */
if (ret == ESP_OK) {
ret = esp_bt_mem_release_areas(&rom_btdm_data, &rom_btdm_bss);
}
if (ret == ESP_OK) {
ret = esp_bt_mem_release_areas(&rom_btdm_inter_data, &rom_btdm_inter_bss);
}
}
return ret;
}
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
{
esp_err_t ret = ESP_OK;
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
return ESP_ERR_INVALID_STATE;
}
bt_area_t cont_bss = {
.start = (intptr_t)&_bt_controller_bss_start,
.end = (intptr_t)&_bt_controller_bss_end,
.name = "BT Controller BSS",
};
bt_area_t cont_data = {
.start = (intptr_t)&_bt_controller_data_start,
.end = (intptr_t)&_bt_controller_data_end,
.name = "BT Controller Data"
};
if (mode & ESP_BT_MODE_BLE) {
/* free data and BSS section for libbtdm_app.a */
if (ret == ESP_OK) {
ret = esp_bt_mem_release_areas(&cont_data, &cont_bss);
}
/* free data and BSS section for Bluetooth controller ROM code */
if (ret == ESP_OK) {
ret = esp_bt_controller_rom_mem_release(mode);
}
}
return ret;
}
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
{
int ret;
intptr_t mem_start, mem_end;
esp_err_t ret = ESP_OK;
ret = esp_bt_controller_mem_release(mode);
if (ret != ESP_OK) {
return ret;
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
return ESP_ERR_INVALID_STATE;
}
bt_area_t bss = {
.start = (intptr_t)&_bt_bss_start,
.end = (intptr_t)&_bt_bss_end,
.name = "BT BSS",
};
bt_area_t cont_bss = {
.start = (intptr_t)&_bt_controller_bss_start,
.end = (intptr_t)&_bt_controller_bss_end,
.name = "BT Controller BSS",
};
bt_area_t data = {
.start = (intptr_t)&_bt_data_start,
.end = (intptr_t)&_bt_data_end,
.name = "BT Data",
};
bt_area_t cont_data = {
.start = (intptr_t)&_bt_controller_data_start,
.end = (intptr_t)&_bt_controller_data_end,
.name = "BT Controller Data"
};
if (mode & ESP_BT_MODE_BLE) {
/* if the addresses of btdm .bss and bt .bss are consecutive,
they are registered in the system heap as a piece of memory
*/
if(_bt_bss_end == _btdm_bss_start) {
mem_start = (intptr_t)&_bt_bss_start;
mem_end = (intptr_t)&_btdm_bss_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
} else {
mem_start = (intptr_t)&_bt_bss_start;
mem_end = (intptr_t)&_bt_bss_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release BT BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
mem_start = (intptr_t)&_btdm_bss_start;
mem_end = (intptr_t)&_btdm_bss_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release BTDM BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
}
/* if the addresses of btdm .data and bt .data are consecutive,
they are registered in the system heap as a piece of memory
*/
if(_bt_data_end == _btdm_data_start) {
mem_start = (intptr_t)&_bt_data_start;
mem_end = (intptr_t)&_btdm_data_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
} else {
mem_start = (intptr_t)&_bt_data_start;
mem_end = (intptr_t)&_bt_data_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
mem_start = (intptr_t)&_btdm_data_start;
mem_end = (intptr_t)&_btdm_data_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release BTDM Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
/* Start by freeing Bluetooth BSS section */
if (ret == ESP_OK) {
ret = esp_bt_mem_release_areas(&bss, &cont_bss);
}
mem_start = (intptr_t)&_nimble_bss_start;
mem_end = (intptr_t)&_nimble_bss_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release NimBLE BSS [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
/* Do the same thing with the Bluetooth data section */
if (ret == ESP_OK) {
ret = esp_bt_mem_release_areas(&data, &cont_data);
}
mem_start = (intptr_t)&_nimble_data_start;
mem_end = (intptr_t)&_nimble_data_end;
if (mem_start != mem_end) {
ESP_LOGD(BT_LOG_TAG, "Release NimBLE Data [0x%08x] - [0x%08x], len %d", mem_start, mem_end, mem_end - mem_start);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
/* free data and BSS section for Bluetooth controller ROM code */
if (ret == ESP_OK) {
ret = esp_bt_controller_rom_mem_release(mode);
}
}
return ESP_OK;
return ret;
}
static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end)
@@ -1112,6 +1186,147 @@ static void IRAM_ATTR btdm_mac_bb_power_up_cb(void)
}
#endif
// init low-power control resources
static esp_err_t btdm_low_power_mode_init(esp_bt_controller_config_t *cfg)
{
esp_err_t err = ESP_OK;
do {
// set default values for global states or resources
s_lp_stat.val = 0;
s_lp_cntl.val = 0;
s_lp_cntl.main_xtal_pu = 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.lpclk_sel = (cfg->sleep_mode == ESP_BT_SLEEP_MODE_1) ? cfg->sleep_clock : ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
s_lp_cntl.no_light_sleep = 0;
if (s_lp_cntl.enable) {
#if CONFIG_MAC_BB_PD
if (!btdm_deep_sleep_mem_init()) {
err = ESP_ERR_NO_MEM;
break;
}
s_lp_cntl.mac_bb_pd = 1;
#endif
#ifdef CONFIG_PM_ENABLE
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;
break;
}
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,
.name = "btSlp",
};
if ((err = esp_timer_create(&create_args, &s_btdm_slp_tmr)) != ESP_OK) {
break;
}
}
// 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);
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_EXT_32K_XTAL) { // External 32 kHz XTAL
// check whether or not EXT_CRYS is working
if (rtc_clk_slow_src_get() != SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock");
s_lp_cntl.lpclk_sel = ESP_BT_SLEEP_CLOCK_MAIN_XTAL;
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
s_lp_cntl.no_light_sleep = 1;
#endif
}
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_RTC_SLOW) { // Internal 136kHz RC oscillator
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
ESP_LOGW(BT_LOG_TAG, "Internal 136kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is "
"required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.");
} else {
ESP_LOGW(BT_LOG_TAG, "Internal 136kHz RC oscillator not detected.");
assert(0);
}
} else if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
ESP_LOGI(BT_LOG_TAG, "Bluetooth will use main XTAL as Bluetooth sleep clock.");
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
s_lp_cntl.no_light_sleep = 1;
#endif
}
} else {
s_lp_cntl.no_light_sleep = 1;
}
bool select_src_ret __attribute__((unused));
bool set_div_ret __attribute__((unused));
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
s_lp_cntl.main_xtal_pu = 1;
#endif
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() / MHZ);
assert(select_src_ret && set_div_ret);
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
btdm_lpcycle_us = 1 << (btdm_lpcycle_us_frac);
} else if (s_lp_cntl.lpclk_sel == 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 = (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 == ESP_BT_SLEEP_CLOCK_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 {
err = ESP_ERR_INVALID_ARG;
break;
}
#if CONFIG_SW_COEXIST_ENABLE
coex_update_lpclk_interval();
#endif
#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) {
break;
}
ESP_LOGW(BT_LOG_TAG, "light sleep mode will not be able to apply when bluetooth is enabled.");
}
if ((err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "bt", &s_pm_lock)) != ESP_OK) {
break;
} else {
s_lp_stat.pm_lock_released = 1;
}
#endif
} while (0);
return err;
}
esp_bt_sleep_clock_t esp_bt_get_lpclk_src(void)
{
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED &&
btdm_controller_status != ESP_BT_CONTROLLER_STATUS_ENABLED) {
return ESP_BT_SLEEP_CLOCK_NONE;
}
return s_lp_cntl.lpclk_sel;
}
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
{
esp_err_t err = ESP_FAIL;
@@ -1147,6 +1362,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
ESP_LOGE(BT_LOG_TAG, "SLEEP_MODE_1 enabled but sleep clock not configured");
return ESP_ERR_INVALID_ARG;
}
if (cfg->sleep_clock > ESP_BT_SLEEP_CLOCK_RTC_SLOW) {
ESP_LOGE(BT_LOG_TAG, "SLEEP_MODE_1 is enabled but this sleep clock is not supported");
return ESP_ERR_INVALID_ARG;
}
}
// overwrite some parameters
@@ -1172,133 +1391,10 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
ESP_LOGI(BT_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version());
// 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_lp_cntl.main_xtal_pu = 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 = 0;
if (s_lp_cntl.enable) {
#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
#ifdef CONFIG_PM_ENABLE
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,
.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; // set default value
#if CONFIG_BT_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) {
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_XTAL32K; // External 32 kHz XTAL
} else {
ESP_LOGW(BT_LOG_TAG, "32.768kHz XTAL not detected, fall back to main XTAL as Bluetooth sleep clock");
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
s_lp_cntl.no_light_sleep = 1;
#endif
}
#elif (CONFIG_BT_CTRL_LPCLK_SEL_MAIN_XTAL)
ESP_LOGI(BT_LOG_TAG, "Bluetooth will use main XTAL as Bluetooth sleep clock.");
#if !CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
s_lp_cntl.no_light_sleep = 1;
#endif
#elif (CONFIG_BT_CTRL_LPCLK_SEL_RTC_SLOW)
// check whether or not internal 150 kHz RC oscillator is working
if (rtc_clk_slow_src_get() == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
s_lp_cntl.lpclk_sel = BTDM_LPCLK_SEL_RTC_SLOW; // Internal 150 kHz RC oscillator
ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC osciallator. The accuracy of this clock is a lot larger than 500ppm which is "
"required in Bluetooth communication, so don't select this option in scenarios such as BLE connection state.");
} else {
ESP_LOGW(BT_LOG_TAG, "Internal 150kHz RC oscillator not detected.");
assert(0);
}
#endif
bool select_src_ret __attribute__((unused));
bool set_div_ret __attribute__((unused));
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON));
s_lp_cntl.main_xtal_pu = 1;
#endif
select_src_ret = btdm_lpclk_select_src(BTDM_LPCLK_SEL_XTAL);
set_div_ret = btdm_lpclk_set_div(esp_clk_xtal_freq() / MHZ);
assert(select_src_ret && set_div_ret);
btdm_lpcycle_us_frac = RTC_CLK_CAL_FRACT;
btdm_lpcycle_us = 1 << (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 {
err = ESP_ERR_INVALID_ARG;
goto error;
}
#if CONFIG_SW_COEXIST_ENABLE
coex_update_lpclk_interval();
#endif
#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;
}
ESP_LOGW(BT_LOG_TAG, "light sleep mode will not be able to apply when bluetooth is enabled.");
}
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;
}
#endif
} while (0);
if ((err = btdm_low_power_mode_init(cfg)) != ESP_OK) {
ESP_LOGE(BT_LOG_TAG, "Low power module initialization failed");
goto error;
}
#if CONFIG_SW_COEXIST_ENABLE
coex_init();
@@ -1336,69 +1432,70 @@ esp_err_t esp_bt_controller_deinit(void)
return ESP_OK;
}
// deinit low power control resources
static void btdm_low_power_mode_deinit(void)
{
#if CONFIG_MAC_BB_PD
if (s_lp_cntl.mac_bb_pd) {
btdm_deep_sleep_mem_deinit();
s_lp_cntl.mac_bb_pd = 0;
}
#endif
#ifdef CONFIG_PM_ENABLE
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;
}
#endif
if (s_lp_cntl.wakeup_timer_required && s_btdm_slp_tmr != NULL) {
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;
}
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;
}
}
if (s_lp_cntl.lpclk_sel == ESP_BT_SLEEP_CLOCK_MAIN_XTAL) {
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
if (s_lp_cntl.main_xtal_pu) {
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
s_lp_cntl.main_xtal_pu = 0;
}
#endif
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
btdm_lpclk_set_div(0);
#if CONFIG_SW_COEXIST_ENABLE
coex_update_lpclk_interval();
#endif
}
btdm_lpcycle_us = 0;
}
static void bt_controller_deinit_internal(void)
{
periph_module_disable(PERIPH_BT_MODULE);
// deinit low power control resources
do {
#if CONFIG_MAC_BB_PD
if (s_lp_cntl.mac_bb_pd) {
btdm_deep_sleep_mem_deinit();
s_lp_cntl.mac_bb_pd = 0;
}
#endif
#ifdef CONFIG_PM_ENABLE
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;
}
#endif
if (s_lp_cntl.wakeup_timer_required) {
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;
}
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;
}
}
if (s_lp_cntl.lpclk_sel == BTDM_LPCLK_SEL_XTAL) {
#ifdef CONFIG_BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP
if (s_lp_cntl.main_xtal_pu) {
ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF));
s_lp_cntl.main_xtal_pu = 0;
}
#endif
btdm_lpclk_select_src(BTDM_LPCLK_SEL_RTC_SLOW);
btdm_lpclk_set_div(0);
#if CONFIG_SW_COEXIST_ENABLE
coex_update_lpclk_interval();
#endif
}
btdm_lpcycle_us = 0;
} while (0);
btdm_low_power_mode_deinit();
esp_bt_power_domain_off();
#if CONFIG_MAC_BB_PD
@@ -1677,4 +1774,55 @@ static void coex_wifi_sleep_set_hook(bool sleep)
{
}
static int coex_schm_register_btdm_callback_wrapper(void *callback)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_register_callback(COEX_SCHM_CALLBACK_TYPE_BT, callback);
#else
return 0;
#endif
}
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_schm_status_bit_clear(type, status);
#endif
}
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
{
#if CONFIG_SW_COEXIST_ENABLE
coex_schm_status_bit_set(type, status);
#endif
}
static uint32_t coex_schm_interval_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_interval_get();
#else
return 0;
#endif
}
static uint8_t coex_schm_curr_period_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_curr_period_get();
#else
return 1;
#endif
}
static void * coex_schm_curr_phase_get_wrapper(void)
{
#if CONFIG_SW_COEXIST_ENABLE
return coex_schm_curr_phase_get();
#else
return NULL;
#endif
}
#endif /* CONFIG_BT_ENABLED */