From 57eeb4d95393388b2db2b49d1e102d80a14d26b7 Mon Sep 17 00:00:00 2001 From: baohongde Date: Fri, 3 Sep 2021 16:51:09 +0800 Subject: [PATCH] components/driver: support static allocation of FreeRTOS queues used by ISR routine --- components/bt/controller/esp32/bt.c | 287 ++++++++++++++++++++++++++-- 1 file changed, 270 insertions(+), 17 deletions(-) diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index ec9587d82b..60c3aa1535 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -98,6 +98,11 @@ do{\ #define OSI_VERSION 0x00010003 #define OSI_MAGIC_VALUE 0xFADEBEAD +/* SPIRAM Configuration */ +#if CONFIG_SPIRAM_USE_MALLOC +#define BTDM_MAX_QUEUE_NUM (5) +#endif + /* Types definition ************************************************************************ */ @@ -115,6 +120,15 @@ typedef struct { intptr_t end; } btdm_dram_available_region_t; +/* PSRAM configuration */ +#if CONFIG_SPIRAM_USE_MALLOC +typedef struct { + QueueHandle_t handle; + void *storage; + void *buffer; +} btdm_queue_item_t; +#endif + /* OSI function */ struct osi_funcs_t { uint32_t _version; @@ -257,6 +271,11 @@ extern uint32_t _btdm_data_end; /* Local Function Declare ********************************************************************* */ +#if CONFIG_SPIRAM_USE_MALLOC +static bool btdm_queue_generic_register(const btdm_queue_item_t *queue); +static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue); +#endif /* CONFIG_SPIRAM_USE_MALLOC */ + #if CONFIG_BTDM_CTRL_HLI static xt_handler set_isr_hlevel_wrapper(int n, xt_handler f, void *arg); static void IRAM_ATTR interrupt_hlevel_disable(void); @@ -436,6 +455,11 @@ SOC_RESERVE_MEMORY_REGION(SOC_MEM_BT_DATA_START, SOC_MEM_BT_DATA_END, static DRAM_ATTR struct osi_funcs_t *osi_funcs_p; +#if CONFIG_SPIRAM_USE_MALLOC +static DRAM_ATTR btdm_queue_item_t btdm_queue_table[BTDM_MAX_QUEUE_NUM]; +static DRAM_ATTR SemaphoreHandle_t btdm_queue_table_mux = NULL; +#endif /* #if CONFIG_SPIRAM_USE_MALLOC */ + /* Static variable declare */ // timestamp when PHY/RF was switched on static DRAM_ATTR int64_t s_time_phy_rf_just_enabled = 0; @@ -475,6 +499,52 @@ static inline void btdm_check_and_init_bb(void) } } +#if CONFIG_SPIRAM_USE_MALLOC +static bool btdm_queue_generic_register(const btdm_queue_item_t *queue) +{ + if (!btdm_queue_table_mux || !queue) { + return NULL; + } + + bool ret = false; + btdm_queue_item_t *item; + xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY); + for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) { + item = &btdm_queue_table[i]; + if (item->handle == NULL) { + memcpy(item, queue, sizeof(btdm_queue_item_t)); + ret = true; + break; + } + } + xSemaphoreGive(btdm_queue_table_mux); + return ret; +} + +static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue) +{ + if (!btdm_queue_table_mux || !queue) { + return false; + } + + bool ret = false; + btdm_queue_item_t *item; + xSemaphoreTake(btdm_queue_table_mux, portMAX_DELAY); + for (int i = 0; i < BTDM_MAX_QUEUE_NUM; ++i) { + item = &btdm_queue_table[i]; + if (item->handle == queue->handle) { + memcpy(queue, item, sizeof(btdm_queue_item_t)); + memset(item, 0, sizeof(btdm_queue_item_t)); + ret = true; + break; + } + } + xSemaphoreGive(btdm_queue_table_mux); + return ret; +} + +#endif /* CONFIG_SPIRAM_USE_MALLOC */ + #if CONFIG_BTDM_CTRL_HLI struct interrupt_hlevel_cb{ uint32_t status; @@ -546,28 +616,84 @@ static void IRAM_ATTR task_yield_from_isr(void) static void *semphr_create_wrapper(uint32_t max, uint32_t init) { + void *handle = NULL; + +#if !CONFIG_SPIRAM_USE_MALLOC + handle = (void *)xSemaphoreCreateCounting(max, init); +#else + StaticQueue_t *queue_buffer = NULL; + + queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if (!queue_buffer) { + goto error; + } + + handle = (void *)xSemaphoreCreateCountingStatic(max, init, queue_buffer); + if (!handle) { + goto error; + } + + btdm_queue_item_t item = { + .handle = handle, + .storage = NULL, + .buffer = queue_buffer, + }; + + if (!btdm_queue_generic_register(&item)) { + goto error; + } +#endif + #if CONFIG_BTDM_CTRL_HLI - SemaphoreHandle_t downstream_semaphore = xSemaphoreCreateCounting(max, init); + SemaphoreHandle_t downstream_semaphore = handle; assert(downstream_semaphore); hli_queue_handle_t s_semaphore = hli_semaphore_create(max, downstream_semaphore); assert(downstream_semaphore); return s_semaphore; #else - return (void *)xSemaphoreCreateCounting(max, init); + return handle; #endif /* CONFIG_BTDM_CTRL_HLI */ + +#if CONFIG_SPIRAM_USE_MALLOC + error: + if (handle) { + vSemaphoreDelete(handle); + } + if (queue_buffer) { + free(queue_buffer); + } + + return NULL; +#endif } static void semphr_delete_wrapper(void *semphr) { + void *handle = NULL; #if CONFIG_BTDM_CTRL_HLI if (((hli_queue_handle_t)semphr)->downstream != NULL) { - vSemaphoreDelete(((hli_queue_handle_t)semphr)->downstream); + handle = ((hli_queue_handle_t)semphr)->downstream; } hli_queue_delete(semphr); #else - vSemaphoreDelete(semphr); + handle = semphr; #endif /* CONFIG_BTDM_CTRL_HLI */ + +#if !CONFIG_SPIRAM_USE_MALLOC + vSemaphoreDelete(handle); +#else + btdm_queue_item_t item = { + .handle = handle, + .storage = NULL, + .buffer = NULL, + }; + + if (btdm_queue_generic_deregister(&item)) { + vSemaphoreDelete(item.handle); + free(item.buffer); + } +#endif } static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw) @@ -620,12 +746,63 @@ static int32_t semphr_give_wrapper(void *semphr) static void *mutex_create_wrapper(void) { +#if CONFIG_SPIRAM_USE_MALLOC + StaticQueue_t *queue_buffer = NULL; + QueueHandle_t handle = NULL; + + queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if (!queue_buffer) { + goto error; + } + + handle = xSemaphoreCreateMutexStatic(queue_buffer); + if (!handle) { + goto error; + } + + btdm_queue_item_t item = { + .handle = handle, + .storage = NULL, + .buffer = queue_buffer, + }; + + if (!btdm_queue_generic_register(&item)) { + goto error; + } + return handle; + + error: + if (handle) { + vSemaphoreDelete(handle); + } + if (queue_buffer) { + free(queue_buffer); + } + + return NULL; +#else return (void *)xSemaphoreCreateMutex(); +#endif } static void mutex_delete_wrapper(void *mutex) { +#if !CONFIG_SPIRAM_USE_MALLOC vSemaphoreDelete(mutex); +#else + btdm_queue_item_t item = { + .handle = mutex, + .storage = NULL, + .buffer = NULL, + }; + + if (btdm_queue_generic_deregister(&item)) { + vSemaphoreDelete(item.handle); + free(item.buffer); + } + + return; +#endif } static int32_t mutex_lock_wrapper(void *mutex) @@ -638,10 +815,82 @@ static int32_t mutex_unlock_wrapper(void *mutex) return (int32_t)xSemaphoreGive(mutex); } +static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size) +{ +#if CONFIG_SPIRAM_USE_MALLOC + StaticQueue_t *queue_buffer = NULL; + uint8_t *queue_storage = NULL; + QueueHandle_t handle = NULL; + + queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if (!queue_buffer) { + goto error; + } + + queue_storage = heap_caps_malloc((queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT); + if (!queue_storage ) { + goto error; + } + + handle = xQueueCreateStatic(queue_len, item_size, queue_storage, queue_buffer); + if (!handle) { + goto error; + } + + btdm_queue_item_t item = { + .handle = handle, + .storage = queue_storage, + .buffer = queue_buffer, + }; + + if (!btdm_queue_generic_register(&item)) { + goto error; + } + + return handle; + + error: + if (handle) { + vQueueDelete(handle); + } + if (queue_storage) { + free(queue_storage); + } + if (queue_buffer) { + free(queue_buffer); + } + + return NULL; +#else + return (void *)xQueueCreate(queue_len, item_size); +#endif +} + +static void queue_delete_wrapper(void *queue) +{ +#if !CONFIG_SPIRAM_USE_MALLOC + vQueueDelete(queue); +#else + btdm_queue_item_t item = { + .handle = queue, + .storage = NULL, + .buffer = NULL, + }; + + if (btdm_queue_generic_deregister(&item)) { + vQueueDelete(item.handle); + free(item.storage); + free(item.buffer); + } + + return; +#endif +} + #if CONFIG_BTDM_CTRL_HLI static void *queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size) { - QueueHandle_t downstream_queue = xQueueCreate(queue_len, item_size); + QueueHandle_t downstream_queue = queue_create_wrapper(queue_len, item_size); assert(downstream_queue); hli_queue_handle_t queue = hli_queue_create(queue_len, item_size, downstream_queue); assert(queue); @@ -650,7 +899,7 @@ static void *queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size) static void *customer_queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size) { - QueueHandle_t downstream_queue = xQueueCreate(queue_len, item_size); + QueueHandle_t downstream_queue = queue_create_wrapper(queue_len, item_size); assert(downstream_queue); hli_queue_handle_t queue = hli_customer_queue_create(queue_len, item_size, downstream_queue); assert(queue); @@ -660,7 +909,7 @@ static void *customer_queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t i static void queue_delete_hlevel_wrapper(void *queue) { if (((hli_queue_handle_t)queue)->downstream != NULL) { - vQueueDelete(((hli_queue_handle_t)queue)->downstream); + queue_delete_wrapper(((hli_queue_handle_t)queue)->downstream); } hli_queue_delete(queue); } @@ -711,16 +960,6 @@ static int32_t IRAM_ATTR queue_recv_from_isr_hlevel_wrapper(void *queue, void *i #else -static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size) -{ - return (void *)xQueueCreate(queue_len, item_size); -} - -static void queue_delete_wrapper(void *queue) -{ - vQueueDelete(queue); -} - static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms) { if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) { @@ -1367,6 +1606,14 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) ESP_LOGI(BTDM_LOG_TAG, "BT controller compile version [%s]", btdm_controller_get_compile_version()); +#if CONFIG_SPIRAM_USE_MALLOC + btdm_queue_table_mux = xSemaphoreCreateMutex(); + if (btdm_queue_table_mux == NULL) { + return ESP_ERR_NO_MEM; + } + memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM); +#endif + s_wakeup_req_sem = semphr_create_wrapper(1, 0); if (s_wakeup_req_sem == NULL) { err = ESP_ERR_NO_MEM; @@ -1512,6 +1759,12 @@ esp_err_t esp_bt_controller_deinit(void) semphr_delete_wrapper(s_wakeup_req_sem); s_wakeup_req_sem = NULL; +#if CONFIG_SPIRAM_USE_MALLOC + vSemaphoreDelete(btdm_queue_table_mux); + btdm_queue_table_mux = NULL; + memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM); +#endif + free(osi_funcs_p); osi_funcs_p = NULL;