]> granicus.if.org Git - esp-idf/commitdiff
esp32/bt/driver: support static allocation of FreeRTOS queues used by ISR routine
authorLiu Zhi Fu <liuzhifu@espressif.com>
Fri, 30 Mar 2018 03:39:42 +0000 (11:39 +0800)
committerLiu Zhi Fu <liuzhifu@espressif.com>
Fri, 27 Apr 2018 07:02:30 +0000 (15:02 +0800)
Support static allocation of FreeRTOS queues used by ISR routine in WiFi/BT/esp_timer/driver etc

components/bt/bt.c
components/driver/ledc.c
components/esp32/Kconfig
components/esp32/esp_timer.c
components/esp32/include/esp_wifi_internal.h
components/esp32/lib
components/esp32/wifi_internal.c

index 1b92a20cc95c1bdcb4f0c8673774fbecfca96e3f..3a274a703337556845857c77c119d7e1f24281aa 100644 (file)
@@ -17,6 +17,8 @@
 #include <stdio.h>
 #include <string.h>
 
+#include "sdkconfig.h"
+#include "esp_heap_caps.h"
 #include "esp_heap_caps_init.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
@@ -115,6 +117,17 @@ static btdm_dram_available_region_t btdm_dram_available_region[] = {
     {ESP_BT_MODE_BTDM,          0x3ffbdb28, 0x3ffc0000},
 };
 
+#if CONFIG_SPIRAM_USE_MALLOC
+typedef struct {
+    QueueHandle_t handle;
+    void *storage;
+    void *buffer;
+} btdm_queue_item_t;
+#define BTDM_MAX_QUEUE_NUM       (5)
+static btdm_queue_item_t btdm_queue_table[BTDM_MAX_QUEUE_NUM];
+SemaphoreHandle_t btdm_queue_table_mux = NULL;
+#endif /* #if CONFIG_SPIRAM_USE_MALLOC */
+
 struct osi_funcs_t {
     xt_handler (*_set_isr)(int n, xt_handler f, void *arg);
     void (*_ints_on)(unsigned int mask);
@@ -159,6 +172,52 @@ static portMUX_TYPE global_int_mux = portMUX_INITIALIZER_UNLOCKED;
 static esp_pm_lock_handle_t s_pm_lock;
 #endif
 
+#if CONFIG_SPIRAM_USE_MALLOC
+bool IRAM_ATTR 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;
+}
+
+bool IRAM_ATTR 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 */
+
 static void IRAM_ATTR interrupt_disable(void)
 {
     portENTER_CRITICAL(&global_int_mux);
@@ -176,12 +235,63 @@ static void IRAM_ATTR task_yield_from_isr(void)
 
 static void *IRAM_ATTR semphr_create_wrapper(uint32_t max, uint32_t init)
 {
+#if !CONFIG_SPIRAM_USE_MALLOC
     return (void *)xSemaphoreCreateCounting(max, init);
+#else
+    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 = 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;
+    }
+    return handle;
+
+ error:
+    if (handle) {
+        vSemaphoreDelete(handle);
+    }
+    if (queue_buffer) {
+        free(queue_buffer);
+    }
+
+    return NULL;
+#endif
 }
 
 static void IRAM_ATTR semphr_delete_wrapper(void *semphr)
 {
+#if !CONFIG_SPIRAM_USE_MALLOC
     vSemaphoreDelete(semphr);
+#else
+    btdm_queue_item_t item = {
+        .handle = semphr,
+        .storage = NULL,
+        .buffer = NULL,
+    };
+
+    if (btdm_queue_generic_deregister(&item)) {
+        vSemaphoreDelete(item.handle);
+        free(item.buffer);
+    }
+
+    return;
+#endif
 }
 
 static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
@@ -210,12 +320,63 @@ static int32_t IRAM_ATTR semphr_give_wrapper(void *semphr)
 
 static void *IRAM_ATTR 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 IRAM_ATTR 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 IRAM_ATTR mutex_lock_wrapper(void *mutex)
@@ -230,12 +391,74 @@ static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex)
 
 static void *IRAM_ATTR 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 IRAM_ATTR 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
 }
 
 static int32_t IRAM_ATTR queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms)
@@ -482,6 +705,18 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
 
     ESP_LOGI(BTDM_LOG_TAG, "BT controller compile version [%s]\n", btdm_controller_get_compile_version());
 
+#if CONFIG_SPIRAM_USE_MALLOC
+    btdm_queue_table_mux = xSemaphoreCreateMutex();
+    if (btdm_queue_table == NULL) {
+#ifdef CONFIG_PM_ENABLE
+        esp_pm_lock_delete(s_pm_lock);
+        s_pm_lock = NULL;
+#endif
+        return ESP_ERR_NO_MEM;
+    }
+    memset(btdm_queue_table, 0, sizeof(btdm_queue_item_t) * BTDM_MAX_QUEUE_NUM);
+#endif
+
     btdm_osi_funcs_register(&osi_funcs);
 
     btdm_controller_mem_init();
@@ -515,6 +750,12 @@ esp_err_t esp_bt_controller_deinit(void)
 
     periph_module_disable(PERIPH_BT_MODULE);
 
+#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
+
     btdm_controller_status = ESP_BT_CONTROLLER_STATUS_IDLE;
 
 #ifdef CONFIG_PM_ENABLE
index 881f01ba539ed783421ac4f20c76a52ab0084d56..0365deb2ead700609dad5b50f75414ee24e98a97 100644 (file)
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 #include <esp_types.h>
+#include <string.h>
 #include "esp_intr.h"
 #include "esp_intr_alloc.h"
 #include "freertos/FreeRTOS.h"
@@ -40,6 +41,9 @@ typedef struct {
     ledc_fade_mode_t mode;
     xSemaphoreHandle ledc_fade_sem;
     xSemaphoreHandle ledc_fade_mux;
+#if CONFIG_SPIRAM_USE_MALLOC
+    StaticQueue_t ledc_fade_sem_storage;
+#endif
 } ledc_fade_t;
 
 static ledc_fade_t *s_ledc_fade_rec[LEDC_SPEED_MODE_MAX][LEDC_CHANNEL_MAX];
@@ -485,9 +489,20 @@ static esp_err_t ledc_fade_channel_deinit(ledc_mode_t speed_mode, ledc_channel_t
 static esp_err_t ledc_fade_channel_init_check(ledc_mode_t speed_mode, ledc_channel_t channel)
 {
     if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
+#if CONFIG_SPIRAM_USE_MALLOC
+        s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) heap_caps_calloc(1, sizeof(ledc_fade_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+        if (!s_ledc_fade_rec[speed_mode][channel]) {
+            ledc_fade_channel_deinit(speed_mode, channel);
+            return ESP_FAIL;
+        }
+
+        memset(&s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem_storage, 0, sizeof(StaticQueue_t));
+        s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinaryStatic(&s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem_storage);
+#else
         s_ledc_fade_rec[speed_mode][channel] = (ledc_fade_t *) calloc(1, sizeof(ledc_fade_t));
-        s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = xSemaphoreCreateMutex();
         s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem = xSemaphoreCreateBinary();
+#endif
+        s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux = xSemaphoreCreateMutex();
     }
     if (s_ledc_fade_rec[speed_mode][channel]
         && s_ledc_fade_rec[speed_mode][channel]->ledc_fade_mux
index 3c94b0e9581af2cceb8a3fb4df228d899a38df93..3c12667220d2742a41c864541be2cdabe3050e8b 100644 (file)
@@ -62,6 +62,7 @@ config SPIRAM_USE_CAPS_ALLOC
     bool "Make RAM allocatable using heap_caps_malloc(..., MALLOC_CAP_SPIRAM)"
 config SPIRAM_USE_MALLOC
     bool "Make RAM allocatable using malloc() as well"
+    select SUPPORT_STATIC_ALLOCATION
 endchoice
 
 choice SPIRAM_TYPE
index 6987b4c64cb28084ee36678042e006ede46d893c..67ae2dd727f20f09b7334e467ce8688be5b60c53 100644 (file)
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include <sys/param.h>
+#include <string.h>
 #include "esp_types.h"
 #include "esp_attr.h"
 #include "esp_err.h"
@@ -82,6 +83,12 @@ static esp_timer_handle_t s_timer_in_callback;
 static TaskHandle_t s_timer_task;
 // counting semaphore used to notify the timer task from ISR
 static SemaphoreHandle_t s_timer_semaphore;
+
+#if CONFIG_SPIRAM_USE_MALLOC
+// memory for s_timer_semaphore
+static StaticQueue_t s_timer_semaphore_memory;
+#endif
+
 // lock protecting s_timers, s_inactive_timers, s_timer_in_callback
 static portMUX_TYPE s_timer_lock = portMUX_INITIALIZER_UNLOCKED;
 
@@ -329,7 +336,12 @@ esp_err_t esp_timer_init(void)
         return ESP_ERR_INVALID_STATE;
     }
 
+#if CONFIG_SPIRAM_USE_MALLOC
+    memset(&s_timer_semaphore_memory, 0, sizeof(StaticQueue_t));
+    s_timer_semaphore = xSemaphoreCreateCountingStatic(TIMER_EVENT_QUEUE_SIZE, 0, &s_timer_semaphore_memory);
+#else
     s_timer_semaphore = xSemaphoreCreateCounting(TIMER_EVENT_QUEUE_SIZE, 0);
+#endif
     if (!s_timer_semaphore) {
         return ESP_ERR_NO_MEM;
     }
index b1984082de508ce203caaf3f1042d5e05a32e2d6..8eb7c0b6bdbac964f905a1dd26bbcc05e124efe7 100755 (executable)
 extern "C" {
 #endif
 
+typedef struct {
+    QueueHandle_t handle; /**< FreeRTOS queue handler */
+    void *storage;        /**< storage for FreeRTOS queue */
+} wifi_static_queue_t;
+
 /**
  * @brief Initialize Wi-Fi Driver
  *     Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer,
index e9e4579336a539590a88ccac05ab9d0422506c3d..8cd9fd455e98a5c818f2796b4b83107884b7874c 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e9e4579336a539590a88ccac05ab9d0422506c3d
+Subproject commit 8cd9fd455e98a5c818f2796b4b83107884b7874c
index 350f2cb860dfeef3d10491c21f410c895f12ef41..7d7a77209895106f14bfc15f98a77b3ae237f1ba 100644 (file)
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <string.h>
 #include "esp_attr.h"
 #include "esp_heap_caps.h"
 #include "sdkconfig.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "esp_wifi.h"
+#include "esp_wifi_internal.h"
 
 /*
  If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
@@ -54,3 +59,58 @@ IRAM_ATTR void *wifi_calloc( size_t n, size_t size )
     return calloc(n, size);
 #endif
 }
+
+wifi_static_queue_t* wifi_create_queue( int queue_len, int item_size)
+{
+    wifi_static_queue_t *queue = NULL;
+
+    queue = (wifi_static_queue_t*)heap_caps_malloc(sizeof(wifi_static_queue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+    if (!queue) {
+        return NULL;
+    }
+
+#if CONFIG_SPIRAM_USE_MALLOC
+
+    queue->storage = heap_caps_calloc(1, sizeof(StaticQueue_t) + (queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+    if (!queue->storage) {
+        goto _error;
+    }
+
+    queue->handle = xQueueCreateStatic( queue_len, item_size, ((uint8_t*)(queue->storage)) + sizeof(StaticQueue_t), (StaticQueue_t*)(queue->storage));
+
+    if (!queue->handle) {
+        goto _error;
+    }
+
+    return queue;
+
+_error:
+    if (queue) {
+        if (queue->storage) {
+            free(queue->storage);
+        }
+
+        free(queue);
+    }
+
+    return NULL;
+#else
+    queue->handle = xQueueCreate( queue_len, item_size);
+    return queue;
+#endif
+}
+
+void wifi_delete_queue(wifi_static_queue_t *queue)
+{
+    if (queue) {
+        vQueueDelete(queue->handle);
+
+#if CONFIG_SPIRAM_USE_MALLOC
+        if (queue->storage) {
+            free(queue->storage);
+        }
+#endif
+
+        free(queue);
+    }
+}