int "Reserve this amount of bytes for data that specifically needs to be in DMA or internal memory"
depends on SPIRAM_USE_MALLOC
default 32768
- range 0 131072
+ range 0 262144
help
Because the external/internal RAM allocation strategy is not always perfect, it sometimes may happen
that the internal memory is entirely filled up. This causes allocations that are specifically done in
Note that because FreeRTOS stacks are forced to internal memory, they will also use this memory pool;
be sure to keep this in mind when adjusting this value.
+ Note also that the DMA reserved pool may not be one single contiguous memory region, depending on the
+ configured size and the static memory usage of the app.
+
+
config SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
bool "Allow external memory as an argument to xTaskCreateStatic"
default n
ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
abort();
}
-#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
- r=esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
- if (r != ESP_OK) {
- ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool!");
- abort();
- }
-#endif
#if CONFIG_SPIRAM_USE_MALLOC
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
#endif
//Enable allocation in region where the startup stacks were located.
heap_caps_enable_nonos_stack_heaps();
+ // Now we have startup stack RAM available for heap, enable any DMA pool memory
+#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
+ esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
+ if (r != ESP_OK) {
+ ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
+ abort();
+ }
+#endif
+
//Initialize task wdt if configured to do so
#ifdef CONFIG_TASK_WDT_PANIC
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_TASK_WDT_TIMEOUT_S, true))
#include <stdint.h>
#include <string.h>
+#include <sys/param.h>
#include "sdkconfig.h"
#include "esp_attr.h"
static uint8_t *dma_heap;
esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
- if (size==0) return ESP_OK; //no-op
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
- dma_heap=heap_caps_malloc(size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
- if (!dma_heap) return ESP_ERR_NO_MEM;
- uint32_t caps[]={MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT};
- return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap+size-1);
+ /* Pool may be allocated in multiple non-contiguous chunks, depending on available RAM */
+ while (size > 0) {
+ size_t next_size = heap_caps_get_largest_free_block(MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
+ next_size = MIN(next_size, size);
+
+ ESP_EARLY_LOGD(TAG, "Allocating block of size %d bytes", next_size);
+ dma_heap = heap_caps_malloc(next_size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
+ if (!dma_heap || next_size == 0) {
+ return ESP_ERR_NO_MEM;
+ }
+
+ uint32_t caps[] = { MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT };
+ esp_err_t e = heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap+next_size-1);
+ if (e != ESP_OK) {
+ return e;
+ }
+ size -= next_size;
+ }
+ return ESP_OK;
}
size_t esp_spiram_get_size()