Procházet zdrojové kódy

heap_caps: Allow for possibility a region is too small to register a heap

May happen due to sdkconfig, static allocation of RAM.

Closes https://github.com/espressif/esp-idf/issues/802
Angus Gratton před 8 roky
rodič
revize
0feb40833a

+ 13 - 5
components/heap/heap_caps.c

@@ -68,6 +68,11 @@ inline static uint32_t get_all_caps(const heap_t *heap)
     return all_caps;
 }
 
+bool heap_caps_match(const heap_t *heap, uint32_t caps)
+{
+    return heap->heap != NULL && ((get_all_caps(heap) & caps) == caps);
+}
+
 /*
 Routine to allocate a bit of memory with certain capabilities. caps is a bitfield of MALLOC_CAP_* bits.
 */
@@ -91,6 +96,9 @@ IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps )
         //Iterate over heaps and check capabilities at this priority
         for (int heap_idx = 0; heap_idx < num_registered_heaps; heap_idx++) {
             heap_t *heap = &registered_heaps[heap_idx];
+            if (heap->heap == NULL) {
+                continue;
+            }
             if ((heap->caps[prio] & caps) != 0) {
                 //Heap has at least one of the caps requested. If caps has other bits set that this prio
                 //doesn't cover, see if they're available in other prios.
@@ -136,7 +144,7 @@ IRAM_ATTR static heap_t *find_containing_heap(void *ptr )
     intptr_t p = (intptr_t)ptr;
     for (size_t i = 0; i < num_registered_heaps; i++) {
         heap_t *heap = &registered_heaps[i];
-        if (p >= heap->start && p < heap->end) {
+        if (heap->heap != NULL && p >= heap->start && p < heap->end) {
             return heap;
         }
     }
@@ -210,7 +218,7 @@ size_t heap_caps_get_free_size( uint32_t caps )
     size_t ret = 0;
     for (int i = 0; i < num_registered_heaps; i++) {
         heap_t *heap = &registered_heaps[i];
-        if ((get_all_caps(heap) & caps) == caps) {
+        if (heap_caps_match(heap, caps)) {
             ret += multi_heap_free_size(heap->heap);
         }
     }
@@ -222,7 +230,7 @@ size_t heap_caps_get_minimum_free_size( uint32_t caps )
     size_t ret = 0;
     for (int i = 0; i < num_registered_heaps; i++) {
         heap_t *heap = &registered_heaps[i];
-        if ((get_all_caps(heap) & caps) == caps) {
+        if (heap_caps_match(heap, caps)) {
             ret += multi_heap_minimum_free_size(heap->heap);
         }
     }
@@ -242,7 +250,7 @@ void heap_caps_get_info( multi_heap_info_t *info, uint32_t caps )
 
     for (int i = 0; i < num_registered_heaps; i++) {
         heap_t *heap = &registered_heaps[i];
-        if ((get_all_caps(heap) & caps) == caps) {
+        if (heap_caps_match(heap, caps)) {
             multi_heap_info_t hinfo;
             multi_heap_get_info(heap->heap, &hinfo);
 
@@ -264,7 +272,7 @@ void heap_caps_print_heap_info( uint32_t caps )
     printf("Heap summary for capabilities 0x%08X:\n", caps);
     for (int i = 0; i < num_registered_heaps; i++) {
         heap_t *heap = &registered_heaps[i];
-        if ((get_all_caps(heap) & caps) == caps) {
+        if (heap_caps_match(heap, caps)) {
             multi_heap_get_info(heap->heap, &info);
 
             printf("  At 0x%08x len %d free %d allocated %d min_free %d\n",

+ 21 - 9
components/heap/heap_caps_init.c

@@ -16,6 +16,7 @@
 #include <string.h>
 #include <esp_log.h>
 #include <multi_heap.h>
+#include <esp_heap_caps.h>
 #include <soc/soc_memory_layout.h>
 
 static const char *TAG = "heap_init";
@@ -26,8 +27,9 @@ size_t num_registered_heaps;
 static void register_heap(heap_t *region)
 {
     region->heap = multi_heap_register((void *)region->start, region->end - region->start);
-    ESP_EARLY_LOGD(TAG, "New heap initialised at %p", region->heap);
-    assert(region->heap);
+    if (region->heap != NULL) {
+        ESP_EARLY_LOGD(TAG, "New heap initialised at %p", region->heap);
+    }
 }
 
 void heap_caps_enable_nonos_stack_heaps()
@@ -38,7 +40,9 @@ void heap_caps_enable_nonos_stack_heaps()
         heap_t *heap = &registered_heaps[i];
         if (heap->heap == NULL) {
             register_heap(heap);
-            multi_heap_set_lock(heap->heap, &heap->heap_mux);
+            if (heap->heap != NULL) {
+                multi_heap_set_lock(heap->heap, &heap->heap_mux);
+            }
         }
     }
 }
@@ -132,7 +136,6 @@ void heap_caps_init()
 
        Once we have a heap to copy it to, we will copy it to a heap buffer.
     */
-    multi_heap_handle_t first_heap = NULL;
     heap_t temp_heaps[num_registered_heaps];
     size_t heap_idx = 0;
 
@@ -161,15 +164,24 @@ void heap_caps_init()
             heap->heap = NULL;
         } else {
             register_heap(heap);
-            if (first_heap == NULL) {
-                first_heap = heap->heap;
-            }
         }
     }
 
-    /* Allocate the permanent heap data that we'll use for runtime */
     assert(heap_idx == num_registered_heaps);
-    registered_heaps = multi_heap_malloc(first_heap, sizeof(heap_t) * num_registered_heaps);
+
+    /* Allocate the permanent heap data that we'll use for runtime */
+    registered_heaps = NULL;
+    for (int i = 0; i < num_registered_heaps; i++) {
+        if (heap_caps_match(&temp_heaps[i], MALLOC_CAP_8BIT)) {
+            /* use the first DRAM heap which can fit the data */
+            registered_heaps = multi_heap_malloc(temp_heaps[i].heap, sizeof(heap_t) * num_registered_heaps);
+            if (registered_heaps != NULL) {
+                break;
+            }
+        }
+    }
+    assert(registered_heaps != NULL); /* if NULL, there's not enough free startup heap space */
+
     memcpy(registered_heaps, temp_heaps, sizeof(heap_t)*num_registered_heaps);
 
     /* Now the heap_mux fields live on the heap, assign them */

+ 3 - 1
components/heap/heap_private.h

@@ -26,7 +26,7 @@
 /* Type for describing each registered heap */
 typedef struct {
     size_t type;
-    uint32_t caps[SOC_MEMORY_TYPE_NO_PRIOS]; ///< Capabilities for the type of memory in this healp (as a prioritised set). Copied from soc_memory_types so it's in RAM not flash.
+    uint32_t caps[SOC_MEMORY_TYPE_NO_PRIOS]; ///< Capabilities for the type of memory in this heap (as a prioritised set). Copied from soc_memory_types so it's in RAM not flash.
     intptr_t start;
     intptr_t end;
     portMUX_TYPE heap_mux;
@@ -36,3 +36,5 @@ typedef struct {
 extern heap_t *registered_heaps;
 extern size_t num_registered_heaps;
 
+bool heap_caps_match(const heap_t *heap, uint32_t caps);
+