Merge branch 'bugfix/btdm_enable_limit' into 'master'

BT controller: add function to release unused memory to the heap

See merge request !1248
This commit is contained in:
Ivan Grokhotkov 2017-09-21 17:33:09 +08:00
commit 0a6fdc3a96
8 changed files with 185 additions and 42 deletions

View file

@ -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

View file

@ -17,6 +17,7 @@
#include <stdio.h>
#include <string.h>
#include "esp_heap_caps_init.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
@ -30,16 +31,19 @@
#include "esp_attr.h"
#include "esp_phy_init.h"
#include "bt.h"
#include "esp_err.h"
#include "esp_log.h"
#if CONFIG_BT_ENABLED
#define BTDM_LOG_TAG "BTDM_INIT"
#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 */
@ -48,6 +52,7 @@ extern int btdm_controller_init(uint32_t config_mask, esp_bt_controller_config_t
extern int btdm_controller_deinit(void);
extern int btdm_controller_enable(esp_bt_mode_t mode);
extern int btdm_controller_disable(esp_bt_mode_t mode);
extern uint8_t btdm_controller_get_mode(void);
extern void btdm_rf_bb_init(void);
/* VHCI function interface */
@ -63,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{\
@ -75,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);
@ -303,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
@ -315,6 +349,76 @@ static uint32_t btdm_config_mask_load(void)
return mask;
}
static void btdm_controller_mem_init(void)
{
/* 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)
{
BaseType_t ret;
@ -324,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;
}
@ -335,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);
@ -356,7 +467,7 @@ esp_err_t esp_bt_controller_deinit(void)
return ESP_ERR_NO_MEM;
}
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
btdm_controller_status = ESP_BT_CONTROLLER_STATUS_SHUTDOWN;
return ESP_OK;
}
@ -368,7 +479,8 @@ esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode)
return ESP_ERR_INVALID_STATE;
}
if (mode != ESP_BT_MODE_BTDM) {
//check the mode is available mode
if (mode & ~btdm_dram_available_region[0].mode) {
return ESP_ERR_INVALID_ARG;
}
@ -389,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;
@ -397,11 +509,7 @@ esp_err_t esp_bt_controller_disable(esp_bt_mode_t mode)
return ESP_ERR_INVALID_STATE;
}
if (mode != ESP_BT_MODE_BTDM) {
return ESP_ERR_INVALID_ARG;
}
ret = btdm_controller_disable(mode);
ret = btdm_controller_disable(btdm_controller_get_mode());
if (ret < 0) {
return ESP_ERR_INVALID_STATE;
}
@ -435,5 +543,4 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type)
return (esp_power_level_t)ble_txpwr_get(power_type);
}
#endif
#endif /* CONFIG_BT_ENABLED */

View file

@ -78,6 +78,7 @@ typedef enum {
ESP_BT_CONTROLLER_STATUS_IDLE = 0,
ESP_BT_CONTROLLER_STATUS_INITED,
ESP_BT_CONTROLLER_STATUS_ENABLED,
ESP_BT_CONTROLLER_STATUS_SHUTDOWN,
ESP_BT_CONTROLLER_STATUS_NUM,
} esp_bt_controller_status_t;
@ -158,20 +159,20 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg);
esp_err_t esp_bt_controller_deinit(void);
/**
* @brief Enable BT controller
* @brief Enable BT controller.
* 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.
* Now only support BTDM.
* @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.
* Now only support BTDM.
* @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
@ -207,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

@ -1 +1 @@
Subproject commit d41e3512971612a4903e1ea1189968408811a1ae
Subproject commit f75b0b9ed881640b79ea2034719ba569d51162f8

View file

@ -213,7 +213,8 @@ esp_err_t heap_caps_add_region(intptr_t start, intptr_t end)
for (int i = 0; i < soc_memory_region_count; i++) {
const soc_memory_region_t *region = &soc_memory_regions[i];
if (region->start <= start && (region->start + region->size) > end) {
// Test requested start only as 'end' may be in a different region entry, assume 'end' has same caps
if (region->start <= start && (region->start + region->size) > start) {
const uint32_t *caps = soc_memory_types[region->type].caps;
return heap_caps_add_region_with_caps(caps, start, end);
}

View file

@ -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

View file

@ -58,7 +58,7 @@ void app_main()
return;
}
if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) {
if (esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT) != ESP_OK) {
ESP_LOGE(BT_AV_TAG, "%s enable controller failed\n", __func__);
return;
}

View file

@ -227,16 +227,35 @@ 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;
}
if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK) {
if (esp_bt_controller_enable(ESP_BT_MODE_BLE) != ESP_OK) {
ESP_LOGI(tag, "Bluetooth controller enable failed");
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);
}