diff --git a/components/heap/heap_caps.c b/components/heap/heap_caps.c index 3484312c8..137d1a160 100644 --- a/components/heap/heap_caps.c +++ b/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 = ®istered_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 = ®istered_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 = ®istered_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 = ®istered_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 = ®istered_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 = ®istered_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", diff --git a/components/heap/heap_caps_init.c b/components/heap/heap_caps_init.c index f98bbf39a..eac375011 100644 --- a/components/heap/heap_caps_init.c +++ b/components/heap/heap_caps_init.c @@ -16,6 +16,7 @@ #include #include #include +#include #include 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 = ®istered_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 */ diff --git a/components/heap/heap_private.h b/components/heap/heap_private.h index ed5fd6b53..e655e8060 100644 --- a/components/heap/heap_private.h +++ b/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); +