Merge branch 'feat/bt_in_psram_v6.1' into 'release/v6.1'

feat(bluedroid): Add config to place btu and hci task stack in psram (v6.1)

See merge request espressif/esp-idf!51489
This commit is contained in:
Wang Meng Yang
2026-08-27 17:38:13 +08:00
6 changed files with 103 additions and 12 deletions

View File

@@ -543,7 +543,7 @@ bt_status_t btc_init(void)
{
const size_t workqueue_len[] = {BTC_TASK_WORKQUEUE0_LEN, BTC_TASK_WORKQUEUE1_LEN};
btc_thread = osi_thread_create(BTC_TASK_NAME, BTC_TASK_STACK_SIZE, BTC_TASK_PRIO, BTC_TASK_PINNED_TO_CORE,
BTC_TASK_WORKQUEUE_NUM, workqueue_len);
BTC_TASK_WORKQUEUE_NUM, workqueue_len, false);
if (btc_thread == NULL) {
return BT_STATUS_NOMEM;
}

View File

@@ -36,10 +36,11 @@ typedef enum {
* param stack_size: thread stack size
* param priority: thread priority
* param core: the CPU core which this thread run, OSI_THREAD_CORE_AFFINITY means unspecific CPU core
* param work_queue_num: speicify queue number, the queue[0] has highest priority, and the priority is decrease by index
* param work_queue_num: specify queue number, the queue[0] has highest priority, and the priority is decrease by index
* param in_psram: place the task in PSRAM
* return : if create successfully, return thread handler; otherwise return NULL.
*/
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num, const size_t work_queue_len[]);
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num, const size_t work_queue_len[], bool in_psram);
/*
* brief: Destroy a thread or task

View File

@@ -43,6 +43,10 @@ struct osi_thread {
struct work_queue **work_queues; /*!< Point to queue array, and the priority inverse array index */
osi_sem_t work_sem;
osi_sem_t stop_sem;
#if (CONFIG_BT_BLUEDROID_TASK_STACK_IN_EXT_MEM)
StackType_t *stack;
StaticTask_t *task;
#endif
};
struct osi_thread_start_arg {
@@ -179,10 +183,9 @@ static void osi_thread_run(void *arg)
}
}
thread->thread_handle = NULL;
osi_sem_give(&thread->stop_sem);
vTaskDelete(NULL);
vTaskSuspend(NULL);
}
static int osi_thread_join(osi_thread_t *thread, uint32_t wait_ms)
@@ -204,14 +207,20 @@ static void osi_thread_stop(osi_thread_t *thread)
//join
ret = osi_thread_join(thread, 1000); //wait 1000ms
//if join failed, delete the task here
if (ret != 0 && thread->thread_handle) {
//delete the task here
if (thread->thread_handle) {
if (ret == 0) {
while (eTaskGetState(thread->thread_handle) != eSuspended) {
vTaskDelay(1);
}
}
vTaskDelete(thread->thread_handle);
thread->thread_handle = NULL;
}
}
//in linux, the stack_size, priority and core may not be set here, the code will be ignore the arguments
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num, const size_t work_queue_len[])
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num, const size_t work_queue_len[], bool in_psram)
{
int ret;
struct osi_thread_start_arg start_arg = {0};
@@ -257,9 +266,32 @@ osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priorit
if (ret != 0) {
goto _err;
}
if (xTaskCreatePinnedToCore(osi_thread_run, name, stack_size, &start_arg, priority, &thread->thread_handle, core) != pdPASS) {
if (in_psram) {
#if (CONFIG_BT_BLUEDROID_TASK_STACK_IN_EXT_MEM)
thread->task = heap_caps_calloc(1, sizeof(StaticTask_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (thread->task == NULL) {
goto _err;
}
thread->stack = heap_caps_calloc_prefer(1, stack_size * sizeof(StackType_t),
2, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT,
MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (thread->stack == NULL) {
goto _err;
}
thread->thread_handle = xTaskCreateStaticPinnedToCore(osi_thread_run, name,
stack_size, &start_arg,
priority, thread->stack,
thread->task, core);
if (thread->thread_handle == NULL) {
goto _err;
}
#else
goto _err;
#endif
}else{
if (xTaskCreatePinnedToCore(osi_thread_run, name, stack_size, &start_arg, priority, &thread->thread_handle, core) != pdPASS) {
goto _err;
}
}
osi_sem_take(&start_arg.start_sem, OSI_SEM_MAX_TIMEOUT);
@@ -297,6 +329,16 @@ _err:
if (thread->stop_sem) {
osi_sem_free(&thread->stop_sem);
}
#if (CONFIG_BT_BLUEDROID_TASK_STACK_IN_EXT_MEM)
if (thread->stack) {
heap_caps_free(thread->stack);
thread->stack = NULL;
}
if (thread->task) {
heap_caps_free(thread->task);
thread->task = NULL;
}
#endif
osi_free(thread);
}
@@ -330,6 +372,16 @@ void osi_thread_free(osi_thread_t *thread)
if (thread->stop_sem) {
osi_sem_free(&thread->stop_sem);
}
#if (CONFIG_BT_BLUEDROID_TASK_STACK_IN_EXT_MEM)
if (thread->stack) {
heap_caps_free(thread->stack);
thread->stack = NULL;
}
if (thread->task) {
heap_caps_free(thread->task);
thread->task = NULL;
}
#endif
osi_free(thread);

View File

@@ -1356,6 +1356,34 @@ config BT_ALLOCATION_FROM_SPIRAM_FIRST
help
This select can save the internal RAM if there have the PSRAM
config BT_BLUEDROID_TASK_STACK_IN_EXT_MEM
bool "Place BT task stack in external memory"
depends on FREERTOS_TASK_CREATE_ALLOW_EXT_MEM && (!IDF_TARGET_ESP32 || SPIRAM_CACHE_WORKAROUND)
default n
help
Common prerequisites for placing Bluedroid host
task stacks in PSRAM.
config BT_BLUEDROID_BTU_TASK_STACK_IN_EXT_MEM
bool "Place BTU task stack in external memory"
depends on BT_BLUEDROID_TASK_STACK_IN_EXT_MEM
default n
help
Allocate BTU_TASK stack from external SPIRAM using static task
allocation. TCB remains in internal DRAM.
BTU does not perform NVS operations directly.
config BT_BLUEDROID_HCI_TASK_STACK_IN_EXT_MEM
bool "Place HCI host task stack in external memory"
depends on BT_BLUEDROID_TASK_STACK_IN_EXT_MEM
default n
help
Allocate HCI host task (hciT) stack from external SPIRAM using
static task allocation. TCB remains in internal DRAM.
HCI does not perform NVS operations.
config BT_BLE_DYNAMIC_ENV_MEMORY
bool "Use dynamic memory allocation in BT/BLE stack"
depends on BT_BLUEDROID_ENABLED

View File

@@ -114,8 +114,13 @@ int hci_start_up(void)
}
const size_t workqueue_len[] = {HCI_HOST_TASK_WORKQUEUE0_LEN, HCI_HOST_TASK_WORKQUEUE1_LEN};
#if (!CONFIG_BT_BLUEDROID_HCI_TASK_STACK_IN_EXT_MEM)
hci_host_thread = osi_thread_create(HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, HCI_HOST_TASK_PRIO, HCI_HOST_TASK_PINNED_TO_CORE,
HCI_HOST_TASK_WORKQUEUE_NUM, workqueue_len);
HCI_HOST_TASK_WORKQUEUE_NUM, workqueue_len, false);
#else
hci_host_thread = osi_thread_create(HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, HCI_HOST_TASK_PRIO, HCI_HOST_TASK_PINNED_TO_CORE,
HCI_HOST_TASK_WORKQUEUE_NUM, workqueue_len, true);
#endif
if (hci_host_thread == NULL) {
goto error;
}

View File

@@ -184,8 +184,13 @@ bool BTU_StartUp(void)
osi_mutex_new(&btu_l2cap_alarm_lock);
const size_t workqueue_len[] = {BTU_TASK_WORKQUEUE0_LEN};
#if (!CONFIG_BT_BLUEDROID_BTU_TASK_STACK_IN_EXT_MEM)
btu_thread = osi_thread_create(BTU_TASK_NAME, BTU_TASK_STACK_SIZE, BTU_TASK_PRIO, BTU_TASK_PINNED_TO_CORE,
BTU_TASK_WORKQUEUE_NUM, workqueue_len);
BTU_TASK_WORKQUEUE_NUM, workqueue_len, false);
#else
btu_thread = osi_thread_create(BTU_TASK_NAME, BTU_TASK_STACK_SIZE, BTU_TASK_PRIO, BTU_TASK_PINNED_TO_CORE,
BTU_TASK_WORKQUEUE_NUM, workqueue_len, true);
#endif
if (btu_thread == NULL) {
goto error_exit;
}