diff --git a/components/bt/Kconfig b/components/bt/Kconfig index fd805bd7f6..174b2deefa 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -31,15 +31,6 @@ config CLASSIC_BT_ENABLED help For now this option needs "SMP_ENABLE" to be set to yes -config BT_DRAM_RELEASE - bool "Release DRAM from Classic BT controller" - depends on BT_ENABLED && (!BLUEDROID_ENABLED || (BLUEDROID_ENABLED && !CLASSIC_BT_ENABLED)) - default n - help - This option should only be used when BLE only. - Enabling this option will release about 30K DRAM from Classic BT. - The released DRAM will be used as system heap memory. - config GATTS_ENABLE bool "Include GATT server module(GATTS)" depends on BLUEDROID_ENABLED diff --git a/components/bt/bt.c b/components/bt/bt.c index 580d576b46..12e1d44074 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -41,10 +41,9 @@ #define BTDM_INIT_PERIOD (5000) /* ms */ /* Bluetooth system and controller config */ -#define BTDM_CFG_BT_EM_RELEASE (1<<0) -#define BTDM_CFG_BT_DATA_RELEASE (1<<1) -#define BTDM_CFG_HCI_UART (1<<2) -#define BTDM_CFG_CONTROLLER_RUN_APP_CPU (1<<3) +#define BTDM_CFG_BT_DATA_RELEASE (1<<0) +#define BTDM_CFG_HCI_UART (1<<1) +#define BTDM_CFG_CONTROLLER_RUN_APP_CPU (1<<2) /* Other reserved for future */ /* not for user call, so don't put to include file */ @@ -69,6 +68,13 @@ extern void API_vhci_host_register_callback(const vhci_host_callback_t *callback extern int ble_txpwr_set(int power_type, int power_level); extern int ble_txpwr_get(int power_type); +extern char _bss_start_btdm; +extern char _bss_end_btdm; +extern char _data_start_btdm; +extern char _data_end_btdm; +extern uint32_t _data_start_btdm_rom; +extern uint32_t _data_end_btdm_rom; + #define BT_DEBUG(...) #define BT_API_CALL_CHECK(info, api_call, ret) \ do{\ @@ -81,6 +87,27 @@ do{\ #define OSI_FUNCS_TIME_BLOCKING 0xffffffff +typedef struct { + esp_bt_mode_t mode; + intptr_t start; + intptr_t end; +} btdm_dram_available_region_t; + +/* the mode column will be modifid by release function to indicate the available region */ +static btdm_dram_available_region_t btdm_dram_available_region[] = { + //following is .data + {ESP_BT_MODE_BTDM, 0x3ffae6e0, 0x3ffaff10}, + //following is memory which HW will use + {ESP_BT_MODE_BTDM, 0x3ffb0000, 0x3ffb09a8}, + {ESP_BT_MODE_BLE, 0x3ffb09a8, 0x3ffb1ddc}, + {ESP_BT_MODE_BTDM, 0x3ffb1ddc, 0x3ffb2730}, + {ESP_BT_MODE_CLASSIC_BT, 0x3ffb2730, 0x3ffb8000}, + //following is .bss + {ESP_BT_MODE_BTDM, 0x3ffb8000, 0x3ffbbb28}, + {ESP_BT_MODE_CLASSIC_BT, 0x3ffbbb28, 0x3ffbdb28}, + {ESP_BT_MODE_BTDM, 0x3ffbdb28, 0x3ffc0000}, +}; + struct osi_funcs_t { xt_handler (*_set_isr)(int n, xt_handler f, void *arg); void (*_ints_on)(unsigned int mask); @@ -309,9 +336,10 @@ static uint32_t btdm_config_mask_load(void) { uint32_t mask = 0x0; -#ifdef CONFIG_BT_DRAM_RELEASE - mask |= (BTDM_CFG_BT_EM_RELEASE | BTDM_CFG_BT_DATA_RELEASE); -#endif + if (btdm_dram_available_region[0].mode == ESP_BT_MODE_BLE) { + mask |= BTDM_CFG_BT_DATA_RELEASE; + } + #ifdef CONFIG_BT_HCI_UART mask |= BTDM_CFG_HCI_UART; #endif @@ -321,22 +349,74 @@ static uint32_t btdm_config_mask_load(void) return mask; } -static void btdm_controller_release_mem(void) +static void btdm_controller_mem_init(void) { - uint32_t bt_mem_start, bt_mem_end; -#if CONFIG_BT_DRAM_RELEASE - bt_mem_start = 0x3ffb0000; bt_mem_end = 0x3ffb3000; //Reserve BT data region - ESP_ERROR_CHECK( heap_caps_add_region((intptr_t)bt_mem_start, (intptr_t)bt_mem_end)); - bt_mem_start = 0x3ffb8000; bt_mem_end = 0x3ffbbb28; //Reserve BT data region - ESP_ERROR_CHECK( heap_caps_add_region((intptr_t)bt_mem_start, (intptr_t)bt_mem_end)); - bt_mem_start = 0x3ffbdb28; bt_mem_end = 0x3ffc0000; //Reserve BT data region - ESP_ERROR_CHECK( heap_caps_add_region((intptr_t)bt_mem_start, (intptr_t)bt_mem_end)); -#else - bt_mem_start = 0x3ffb0000; bt_mem_end = 0x3ffc0000; //Reserve BT hardware shared memory & BT data region - ESP_ERROR_CHECK( heap_caps_add_region((intptr_t)bt_mem_start, (intptr_t)bt_mem_end)); -#endif - bt_mem_start = 0x3ffae2a0; bt_mem_end = 0x3ffaff10; //Reserve ROM data region - ESP_ERROR_CHECK( heap_caps_add_region((intptr_t)bt_mem_start, (intptr_t)bt_mem_end)); + /* initialise .bss, .data and .etc section */ + memcpy(&_data_start_btdm, (void *)_data_start_btdm_rom, &_data_end_btdm - &_data_start_btdm); + ESP_LOGD(BTDM_LOG_TAG, ".data initialise [0x%08x] <== [0x%08x]\n", (uint32_t)&_data_start_btdm, _data_start_btdm_rom); + + for (int i = 1; i < sizeof(btdm_dram_available_region)/sizeof(btdm_dram_available_region_t); i++) { + if (btdm_dram_available_region[i].mode != ESP_BT_MODE_IDLE) { + memset((void *)btdm_dram_available_region[i].start, 0x0, btdm_dram_available_region[i].end - btdm_dram_available_region[i].start); + ESP_LOGD(BTDM_LOG_TAG, ".bss initialise [0x%08x] - [0x%08x]\n", btdm_dram_available_region[i].start, btdm_dram_available_region[i].end); + } + } +} + +esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode) +{ + bool update = true; + intptr_t mem_start, mem_end; + + //get the mode which can be released, skip the mode which is running + mode &= ~btdm_controller_get_mode(); + if (mode == 0x0) { + return ESP_ERR_INVALID_ARG; + } + + //already relesed + if (!(mode & btdm_dram_available_region[0].mode)) { + return ESP_ERR_INVALID_STATE; + } + + for (int i = 0; i < sizeof(btdm_dram_available_region)/sizeof(btdm_dram_available_region_t); i++) { + //skip the share mode, idle mode and other mode + if (btdm_dram_available_region[i].mode == ESP_BT_MODE_IDLE + || (mode & btdm_dram_available_region[i].mode) != btdm_dram_available_region[i].mode) { + //clear the bit of the mode which will be released + btdm_dram_available_region[i].mode &= ~mode; + continue; + } else { + //clear the bit of the mode which will be released + btdm_dram_available_region[i].mode &= ~mode; + } + + if (update) { + mem_start = btdm_dram_available_region[i].start; + mem_end = btdm_dram_available_region[i].end; + update = false; + } + + if (i < sizeof(btdm_dram_available_region)/sizeof(btdm_dram_available_region_t) - 1) { + mem_end = btdm_dram_available_region[i].end; + if (btdm_dram_available_region[i+1].mode != ESP_BT_MODE_IDLE + && (mode & btdm_dram_available_region[i+1].mode) == btdm_dram_available_region[i+1].mode + && mem_end == btdm_dram_available_region[i+1].start) { + continue; + } else { + ESP_LOGD(BTDM_LOG_TAG, "Release DRAM [0x%08x] - [0x%08x]\n", mem_start, mem_end); + ESP_ERROR_CHECK( heap_caps_add_region(mem_start, mem_end)); + update = true; + } + } else { + mem_end = btdm_dram_available_region[i].end; + ESP_LOGD(BTDM_LOG_TAG, "Release DRAM [0x%08x] - [0x%08x]\n", mem_start, mem_end); + ESP_ERROR_CHECK( heap_caps_add_region(mem_start, mem_end)); + update = true; + } + } + + return ESP_OK; } esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) @@ -348,6 +428,11 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) return ESP_ERR_INVALID_STATE; } + //if all the bt available memory was already released, cannot initialize bluetooth controller + if (btdm_dram_available_region[0].mode == ESP_BT_MODE_IDLE) { + return ESP_ERR_INVALID_STATE; + } + if (cfg == NULL) { return ESP_ERR_INVALID_ARG; } @@ -359,6 +444,8 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) btdm_osi_funcs_register(&osi_funcs); + btdm_controller_mem_init(); + btdm_cfg_mask = btdm_config_mask_load(); ret = btdm_controller_init(btdm_cfg_mask, cfg); @@ -380,8 +467,6 @@ esp_err_t esp_bt_controller_deinit(void) return ESP_ERR_NO_MEM; } - btdm_controller_release_mem(); - btdm_controller_status = ESP_BT_CONTROLLER_STATUS_SHUTDOWN; return ESP_OK; } @@ -393,13 +478,9 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_INITED) { return ESP_ERR_INVALID_STATE; } -#if CONFIG_BT_DRAM_RELEASE - if (mode != ESP_BT_MODE_BLE) { -#else - if (mode != ESP_BT_MODE_BLE - && mode != ESP_BT_MODE_CLASSIC_BT - && mode != ESP_BT_MODE_BTDM) { -#endif + + //check the mode is available mode + if (mode & ~btdm_dram_available_region[0].mode) { return ESP_ERR_INVALID_ARG; } @@ -420,7 +501,7 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode) return ESP_OK; } -esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode) +esp_err_t esp_bt_controller_disable(void) { int ret; @@ -428,13 +509,7 @@ esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode) return ESP_ERR_INVALID_STATE; } - if (mode != btdm_controller_get_mode()) { - ESP_LOGW(BTDM_LOG_TAG, "The input mode should be equal %d, but ignore error, use %d instead of %d\n", - btdm_controller_get_mode(), btdm_controller_get_mode(), mode); - mode = btdm_controller_get_mode(); - } - - ret = btdm_controller_disable(mode); + ret = btdm_controller_disable(btdm_controller_get_mode()); if (ret < 0) { return ESP_ERR_INVALID_STATE; } diff --git a/components/bt/include/bt.h b/components/bt/include/bt.h index c8aab8fa00..9976960442 100644 --- a/components/bt/include/bt.h +++ b/components/bt/include/bt.h @@ -154,30 +154,25 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg); * * This function should be called only once, after any other BT functions are called. * This function is not whole completed, esp_bt_controller_init cannot called after this function. - * After call this function, it will release all the .bss/.data and .etc memory to heap dynamically. - * The release memory about 64K bytes (if CONFIG_BT_DRAM_RELEASE=y, it's about 36K bytes) * @return ESP_OK - success, other - failed */ esp_err_t esp_bt_controller_deinit(void); /** * @brief Enable BT controller. - * By a knowned issue, if the function already set mode, it can not set another mode dynamically. - * If want to change mode type, should call esp_bt_controller_disable, then call esp_bt_controller_enable. + * Due to a known issue, you cannot call esp_bt_controller_enable() a second time + * to change the controller mode dynamically. To change controller mode, call + * esp_bt_controller_disable() and then call esp_bt_controller_enable() with the new mode. * @param mode : the mode(BLE/BT/BTDM) to enable. - * If CONFIG_BT_DRAM_RELEASE=y, the param mode should only be ESP_BT_MODE_BLE. * @return ESP_OK - success, other - failed */ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode); /** * @brief Disable BT controller - * @param mode : the mode(BLE/BT/BTDM) to disable. - * the mode should be equal to which esp_bt_controller_enable set. - * If not, the function will give warning, then use the correct mode to do disable. * @return ESP_OK - success, other - failed */ -esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode); +esp_err_t esp_bt_controller_disable(void); /** * @brief Get BT controller is initialised/de-initialised/enabled/disabled @@ -213,6 +208,36 @@ void esp_vhci_host_send_packet(uint8_t *data, uint16_t len); */ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback); +/** @brief esp_bt_controller_mem_release + * release the memory by mode, if never use the bluetooth mode + * it can release the .bbs, .data and other section to heap. + * The total size is about 70k bytes. + * + * If esp_bt_controller_enable(mode) has already been called, calling + * esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) will automatically + * release all memory which is not needed for the currently enabled + * Bluetooth controller mode. + * + * For example, calling esp_bt_controller_enable(ESP_BT_MODE_BLE) then + * esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) will enable BLE modes + * and release memory only used by BT Classic. Also, call esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT) + * is the same. + * + * Note that once BT controller memory is released, the process cannot be reversed. + * If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled) + * then do not call this function. + * + * If user never use bluetooth controller, could call esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) + * before esp_bt_controller_init or after esp_bt_controller_deinit. + * + * For example, user only use bluetooth to config SSID and PASSWORD of WIFI, after config, will never use bluetooth. + * Then, could call esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) after esp_bt_controller_deinit. + * + * @param mode : the mode want to release memory + * @return ESP_OK - success, other - failed + */ +esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode); + #ifdef __cplusplus } #endif diff --git a/components/bt/lib b/components/bt/lib index a3aee13381..f75b0b9ed8 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit a3aee13381c21c10590cf8b5a6be3010abf3d4a6 +Subproject commit f75b0b9ed881640b79ea2034719ba569d51162f8 diff --git a/components/soc/esp32/soc_memory_layout.c b/components/soc/esp32/soc_memory_layout.c index dce4ff8b4c..02bced2630 100644 --- a/components/soc/esp32/soc_memory_layout.c +++ b/components/soc/esp32/soc_memory_layout.c @@ -150,16 +150,10 @@ const soc_reserved_region_t soc_reserved_regions[] = { { 0x3ffe4000, 0x3ffe4350 }, //Reserve ROM APP data region #if CONFIG_BT_ENABLED -#if CONFIG_BT_DRAM_RELEASE - { 0x3ffb0000, 0x3ffb3000 }, //Reserve BT data region - { 0x3ffb8000, 0x3ffbbb28 }, //Reserve BT data region - { 0x3ffbdb28, 0x3ffc0000 }, //Reserve BT data region -#else { 0x3ffb0000, 0x3ffc0000 }, //Reserve BT hardware shared memory & BT data region -#endif { 0x3ffae000, 0x3ffaff10 }, //Reserve ROM data region, inc region needed for BT ROM routines #else - { 0x3ffae000, 0x3ffae2a0 }, //Reserve ROM data region + { 0x3ffae000, 0x3ffae6e0 }, //Reserve ROM data region #endif #if CONFIG_MEMMAP_TRACEMEM diff --git a/examples/bluetooth/ble_adv/main/app_bt.c b/examples/bluetooth/ble_adv/main/app_bt.c index 0955f4a02f..f6c01a2dba 100644 --- a/examples/bluetooth/ble_adv/main/app_bt.c +++ b/examples/bluetooth/ble_adv/main/app_bt.c @@ -227,6 +227,12 @@ void app_main() ESP_ERROR_CHECK( ret ); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + ret = esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); + if (ret) { + ESP_LOGI(tag, "Bluetooth controller release classic bt memory failed"); + return; + } + if (esp_bt_controller_init(&bt_cfg) != ESP_OK) { ESP_LOGI(tag, "Bluetooth controller initialize failed"); return; @@ -237,6 +243,19 @@ void app_main() return; } + /* + * If call mem release here, also work. Input ESP_BT_MODE_CLASSIC_BT, the function will + * release the memory of classic bt mdoe. + * esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); + * + */ + + /* + * If call mem release here, also work. Input ESP_BT_MODE_BTDM, the function will calculate + * that the BLE mode is already used, so it will release of only classic bt mode. + * esp_bt_controller_mem_release(ESP_BT_MODE_BTDM); + */ + xTaskCreatePinnedToCore(&bleAdvtTask, "bleAdvtTask", 2048, NULL, 5, NULL, 0); }