From f610249bdd3fed343369c5aa0c2b640022c86a12 Mon Sep 17 00:00:00 2001 From: Hrishikesh Dhayagude Date: Wed, 11 Jul 2018 11:52:32 +0530 Subject: [PATCH] Reclaim BT/BTDM BSS and Data in bluetooth memory release function 1. Modify esp_bt_controller_mem_release() to release BTDM BSS and Data to heap if ESP_BT_MODE_BTDM mode is passed to it 2. Add a new API esp_bt_mem_release() which internally calls esp_bt_controller_mem_release() with the provided mode and then if mode is ESP_BT_MODE_BTDM, releases BT BSS and Data to heap. Background: For Wi-Fi and BT/BLE applications, for e.g. the usecase is like when Bluetooth is used for provisioning and once the device is connected to the Wi-Fi AP, we can turn off Bluetooth completely. In such scenarios, it should be possible to reclaim all the memory of Bluetooth. Although, currently this does not happen. Experiment: Made the following modifications to examples/bluetooth/gatt_server : 1. Added support of simple_wifi to it 2. Moved all the bluetooth related code under CONFIG_BT_ENABLED config option 3. Calculated the free heap in 2 similar scenarios: i. Disabled BT (CONFIG_BT_ENABLED undefined) and checked the free heap after STA connected ii. Kept BT enabled and disabled it after STA connected and checked the free heap Ideally, the numbers for i., ii. above should have been similar. But there was a delta of almost 30-31K. (i. > ii.) 4. Through make size-components checked the common BSS for libbta.a and libbtdm_app.a and found it to be almost 30K. Data is around 1K Solution: 1. Modified the linker script to mark the BSS and Data for these libraries and free it when ESP_BT_MODE_BTDM mode is passed to mem release APIs. 2. Verified that the free heap is comparable for i. and ii. above. Note: It is known that once this is done, Bluetooth can only be used again post reboot. Signed-off-by: Hrishikesh Dhayagude --- components/bt/bt.c | 45 ++++++++++++++++++++++++-- components/bt/include/esp_bt.h | 49 +++++++++++++++++++++++------ components/esp32/ld/esp32.common.ld | 16 ++++++++++ 3 files changed, 98 insertions(+), 12 deletions(-) diff --git a/components/bt/bt.c b/components/bt/bt.c index b90ccc8ea..c30f332a7 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -103,6 +103,14 @@ extern void bredr_sco_datapath_set(uint8_t data_path); extern char _bss_start_btdm; extern char _bss_end_btdm; +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 _bt_data_start; +extern uint32_t _bt_data_end; +extern uint32_t _btdm_data_start; +extern uint32_t _btdm_data_end; extern char _data_start_btdm; extern char _data_end_btdm; extern uint32_t _data_start_btdm_rom; @@ -769,17 +777,50 @@ esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode) 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)); + 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)); + ESP_ERROR_CHECK(heap_caps_add_region(mem_start, mem_end)); update = true; } } + if (mode == ESP_BT_MODE_BTDM) { + mem_start = (intptr_t)&_btdm_bss_start; + mem_end = (intptr_t)&_btdm_bss_end; + ESP_LOGD(BTDM_LOG_TAG, "Release BTDM BSS [0x%08x] - [0x%08x]\n", mem_start, mem_end); + ESP_ERROR_CHECK(heap_caps_add_region(mem_start, mem_end)); + mem_start = (intptr_t)&_btdm_data_start; + mem_end = (intptr_t)&_btdm_data_end; + ESP_LOGD(BTDM_LOG_TAG, "Release BTDM Data [0x%08x] - [0x%08x]\n", mem_start, mem_end); + ESP_ERROR_CHECK(heap_caps_add_region(mem_start, mem_end)); + } + return ESP_OK; +} + +esp_err_t esp_bt_mem_release(esp_bt_mode_t mode) +{ + int ret; + intptr_t mem_start, mem_end; + + ret = esp_bt_controller_mem_release(mode); + if (ret != ESP_OK) { + return ret; + } + + if (mode == ESP_BT_MODE_BTDM) { + mem_start = (intptr_t)&_bt_bss_start; + mem_end = (intptr_t)&_bt_bss_end; + ESP_LOGD(BTDM_LOG_TAG, "Release BT BSS [0x%08x] - [0x%08x]\n", mem_start, mem_end); + ESP_ERROR_CHECK(heap_caps_add_region(mem_start, mem_end)); + mem_start = (intptr_t)&_bt_data_start; + mem_end = (intptr_t)&_bt_data_end; + ESP_LOGD(BTDM_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x]\n", mem_start, mem_end); + ESP_ERROR_CHECK(heap_caps_add_region(mem_start, mem_end)); + } return ESP_OK; } diff --git a/components/bt/include/esp_bt.h b/components/bt/include/esp_bt.h index fe594b038..6ab606ff6 100644 --- a/components/bt/include/esp_bt.h +++ b/components/bt/include/esp_bt.h @@ -298,33 +298,62 @@ 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 .bss, .data and other section to heap. - * The total size is about 70k bytes. + * release the controller memory as per the mode + * + * This function releases the BSS, data and other sections of the controller to heap. The total size is about 70k bytes. * * esp_bt_controller_mem_release(mode) should be called only before esp_bt_controller_init() * or after esp_bt_controller_deinit(). * - * Note that once BT controller memory is released, the process cannot be reversed. It means you can not use the bluetooth + * Note that once BT controller memory is released, the process cannot be reversed. It means you cannot use the bluetooth * mode which you have released by this function. * * If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled) * then do not call this function. * * If the app calls esp_bt_controller_enable(ESP_BT_MODE_BLE) to use BLE only then it is safe to call - * esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT) at initialisation time to free unused BT Classic memory. + * esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT) at initialization time to free unused BT Classic memory. * - * 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. + * If the mode is ESP_BT_MODE_BTDM, then it may be useful to call API esp_bt_mem_release(ESP_BT_MODE_BTDM) instead, + * which internally calls esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) and additionally releases the BSS and data + * consumed by the BT/BLE host stack to heap. For more details about usage please refer to the documentation of + * esp_bt_mem_release() function * * @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); +/** @brief esp_bt_mem_release + * release controller memory and BSS and data section of the BT/BLE host stack as per the mode + * + * This function first releases controller memory by internally calling esp_bt_controller_mem_release(). + * Additionally, if the mode is set to ESP_BT_MODE_BTDM, it also releases the BSS and data consumed by the BT/BLE host stack to heap + * + * Note that once BT memory is released, the process cannot be reversed. It means you cannot use the bluetooth + * mode which you have released by this function. + * + * If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled) + * then do not call this function. + * + * If you never intend to use bluetooth in a current boot-up cycle, you can call esp_bt_mem_release(ESP_BT_MODE_BTDM) + * before esp_bt_controller_init or after esp_bt_controller_deinit. + * + * For example, if a user only uses bluetooth for setting the WiFi configuration, and does not use bluetooth in the rest of the product operation". + * In such cases, after receiving the WiFi configuration, you can disable/deinit bluetooth and release its memory. + * Below is the sequence of APIs to be called for such scenarios: + * + * esp_bluedroid_disable(); + * esp_bluedroid_deinit(); + * esp_bt_controller_disable(); + * esp_bt_controller_deinit(); + * esp_bt_mem_release(ESP_BT_MODE_BTDM); + * + * @param mode : the mode whose memory is to be released + * @return ESP_OK - success, other - failed + */ +esp_err_t esp_bt_mem_release(esp_bt_mode_t mode); + /** * @brief enable bluetooth to enter modem sleep * diff --git a/components/esp32/ld/esp32.common.ld b/components/esp32/ld/esp32.common.ld index 26acd7b2d..1f3947baa 100644 --- a/components/esp32/ld/esp32.common.ld +++ b/components/esp32/ld/esp32.common.ld @@ -116,6 +116,14 @@ SECTIONS .dram0.data : { _data_start = ABSOLUTE(.); + _bt_data_start = ABSOLUTE(.); + *libbt.a:(.data .data.*) + . = ALIGN (4); + _bt_data_end = ABSOLUTE(.); + _btdm_data_start = ABSOLUTE(.); + *libbtdm_app.a:(.data .data.*) + . = ALIGN (4); + _btdm_data_end = ABSOLUTE(.); *(.data) *(.data.*) *(.gnu.linkonce.d.*) @@ -159,6 +167,14 @@ SECTIONS { . = ALIGN (8); _bss_start = ABSOLUTE(.); + _bt_bss_start = ABSOLUTE(.); + *libbt.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _bt_bss_end = ABSOLUTE(.); + _btdm_bss_start = ABSOLUTE(.); + *libbtdm_app.a:(.bss .bss.* COMMON) + . = ALIGN (4); + _btdm_bss_end = ABSOLUTE(.); *(.dynsbss) *(.sbss) *(.sbss.*)