From b52788e764e33997d7d25f415f887e250b335574 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Thu, 18 May 2017 16:48:52 +0800 Subject: [PATCH] Add reserved DMA/internal region --- components/esp32/Kconfig | 37 ++++++++-- components/esp32/heap_alloc_caps.c | 68 ++++++++++++++----- .../esp32/include/esp_heap_alloc_caps.h | 1 + .../freertos/include/freertos/heap_regions.h | 2 +- 4 files changed, 82 insertions(+), 26 deletions(-) diff --git a/components/esp32/Kconfig b/components/esp32/Kconfig index 73597b70d..8c526da49 100644 --- a/components/esp32/Kconfig +++ b/components/esp32/Kconfig @@ -216,6 +216,7 @@ config MEMMAP_SPIRAM_SIZE help Size of external SPI RAM + config MEMMAP_SPIRAM_NO_HEAPALLOC bool "Initialize PSRAM memory but do not add to heap allocator" default "n" @@ -224,13 +225,6 @@ config MEMMAP_SPIRAM_NO_HEAPALLOC memory region. You can use the memory region from 0x3F800000-0x3FBFFFFF freely, but need to do your own memory management there. -config MEMMAP_SPIRAM_TEST - bool "On SPI RAM init, do a quick memory test" - depends on !MEMMAP_SPIRAM_NO_HEAPALLOC - default "n" - help - This does a quick memory test on boot-up. This takes about a second for 4MiB of SPI RAM. - config MEMMAP_SPIRAM_ENABLE_MALLOC bool "malloc() can also allocate in SPI SRAM" depends on !MEMMAP_SPIRAM_NO_HEAPALLOC @@ -241,6 +235,14 @@ config MEMMAP_SPIRAM_ENABLE_MALLOC heuristic is to allocate internal RAM for anything smaller than MEMMAP_SPIRAM_ALLOC_LIMIT_INTERNAL bytes and external RAM for bigger sizes. +config MEMMAP_SPIRAM_TEST + bool "On SPI RAM init, do a quick memory test" + depends on !MEMMAP_SPIRAM_NO_HEAPALLOC + default "n" + help + This does a quick memory test on boot-up. This takes about a second for 4MiB of SPI RAM. + + config MEMMAP_SPIRAM_ALLOC_LIMIT_INTERNAL int "Always put malloc()s smaller than this size, in bytes, in internal RAM" depends on MEMMAP_SPIRAM_ENABLE_MALLOC @@ -252,6 +254,27 @@ config MEMMAP_SPIRAM_ALLOC_LIMIT_INTERNAL go to PSRAM. If either of these initial allocations fails, allocation in the other memory region will be attempted as a backup option. +config MEMMAP_RESERVE_DMA + bool "Reserve a region of memory for allocations that need to be in internal memory or DMA'able memory" + depends on MEMMAP_SPIRAM_ENABLE_MALLOC + default y + help + This option reserves a region of memory that is not given out when usinn normal malloc(), + but can only be requested using pvPortMallocCaps with the MALLOC_CAP_DMA or MALLOC_CAP_INTERNAL + caps. The stacks of tasks, as well as memory used for DMA transmissions in drivers, will be + allocated here. + + +config MEMMAP_RESERVE_DMA_BYTES + int "Number of bytes in reserved DMA region + depends on MEMMAP_RESERVE_DMA + default 32768 + range 4096 131072 + help + The number of bytes in the reserved region. Be aware that the actual number of bytes reserved + be up to 4K bigger than given here. + + endif choice NUMBER_OF_UNIVERSAL_MAC_ADDRESS diff --git a/components/esp32/heap_alloc_caps.c b/components/esp32/heap_alloc_caps.c index e8bb14000..93e3cf9ad 100644 --- a/components/esp32/heap_alloc_caps.c +++ b/components/esp32/heap_alloc_caps.c @@ -52,7 +52,7 @@ WARNING: The current code assumes the ROM stacks are located in tag 1; no alloca the FreeRTOS scheduler has started. */ static const tag_desc_t tag_desc[]={ - { "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, MALLOC_CAP_INTERNAL }, false}, //Tag 0: Plain ole D-port RAM + { "DRAM", { MALLOC_CAP_8BIT, MALLOC_CAP_DMA|MALLOC_CAP_32BIT, MALLOC_CAP_INTERNAL }, false}, //Tag 0: Plain ole D-port RAM { "D/IRAM", { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC|MALLOC_CAP_INTERNAL }, true}, //Tag 1: Plain ole D-port RAM which has an alias on the I-port { "IRAM", { MALLOC_CAP_EXEC|MALLOC_CAP_32BIT, 0, MALLOC_CAP_INTERNAL }, false}, //Tag 2: IRAM { "PID2IRAM", { MALLOC_CAP_PID2, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL }, false}, //Tag 3-8: PID 2-7 IRAM @@ -67,10 +67,21 @@ static const tag_desc_t tag_desc[]={ { "PID5DRAM", { MALLOC_CAP_PID5, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL }, false}, // { "PID6DRAM", { MALLOC_CAP_PID6, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL }, false}, // { "PID7DRAM", { MALLOC_CAP_PID7, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL }, false}, // - { "SPIRAM", { MALLOC_CAP_SPIRAM, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false}, //Tag 15: SPI SRAM data + { "SPIRAM", { MALLOC_CAP_SPIRAM, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false}, //Tag 15: SPI SRAM data + { "DMAONLY", {MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL|MALLOC_CAP_DMAONLY, MALLOC_CAP_32BIT, 0}, false}, //Tag 16: Reserved for DMA/internal { "", { MALLOC_CAP_INVALID, MALLOC_CAP_INVALID, MALLOC_CAP_INVALID }, false} //End }; +#if CONFIG_MEMMAP_RESERVE_DMA +//DMAONLY_TAG is the tag for the DMAONLY region. Initially, a fair few selected regions are marked with this. The +//logic underneath will change the tag to DMAONLY_UNTAG for all but the configured regions. +#define DMAONLY_TAG 16 +#define DMAONLY_UNTAG 0 +#else +//DMA reserved memory regions can be ignored and tagged as normal memory. +#define DMAONLY_TAG 0 +#endif + /* Region descriptors. These describe all regions of memory available, and tag them according to the capabilities the hardware has. This array is not marked constant; the initialization code may want to @@ -95,22 +106,22 @@ static HeapRegionTagged_t regions[]={ { (uint8_t *)0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code { (uint8_t *)0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory { (uint8_t *)0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions. - { (uint8_t *)0x3FFC0000, 0x2000, 0, 0}, //pool 10-13, mmu page 0 - { (uint8_t *)0x3FFC2000, 0x2000, 0, 0}, //pool 10-13, mmu page 1 - { (uint8_t *)0x3FFC4000, 0x2000, 0, 0}, //pool 10-13, mmu page 2 - { (uint8_t *)0x3FFC6000, 0x2000, 0, 0}, //pool 10-13, mmu page 3 - { (uint8_t *)0x3FFC8000, 0x2000, 0, 0}, //pool 10-13, mmu page 4 - { (uint8_t *)0x3FFCA000, 0x2000, 0, 0}, //pool 10-13, mmu page 5 - { (uint8_t *)0x3FFCC000, 0x2000, 0, 0}, //pool 10-13, mmu page 6 - { (uint8_t *)0x3FFCE000, 0x2000, 0, 0}, //pool 10-13, mmu page 7 - { (uint8_t *)0x3FFD0000, 0x2000, 0, 0}, //pool 10-13, mmu page 8 - { (uint8_t *)0x3FFD2000, 0x2000, 0, 0}, //pool 10-13, mmu page 9 - { (uint8_t *)0x3FFD4000, 0x2000, 0, 0}, //pool 10-13, mmu page 10 - { (uint8_t *)0x3FFD6000, 0x2000, 0, 0}, //pool 10-13, mmu page 11 - { (uint8_t *)0x3FFD8000, 0x2000, 0, 0}, //pool 10-13, mmu page 12 - { (uint8_t *)0x3FFDA000, 0x2000, 0, 0}, //pool 10-13, mmu page 13 - { (uint8_t *)0x3FFDC000, 0x2000, 0, 0}, //pool 10-13, mmu page 14 - { (uint8_t *)0x3FFDE000, 0x2000, 0, 0}, //pool 10-13, mmu page 15 + { (uint8_t *)0x3FFC0000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 0 + { (uint8_t *)0x3FFC2000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 1 + { (uint8_t *)0x3FFC4000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 2 + { (uint8_t *)0x3FFC6000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 3 + { (uint8_t *)0x3FFC8000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 4 + { (uint8_t *)0x3FFCA000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 5 + { (uint8_t *)0x3FFCC000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 6 + { (uint8_t *)0x3FFCE000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 7 + { (uint8_t *)0x3FFD0000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 8 + { (uint8_t *)0x3FFD2000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 9 + { (uint8_t *)0x3FFD4000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 10 + { (uint8_t *)0x3FFD6000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 11 + { (uint8_t *)0x3FFD8000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 12 + { (uint8_t *)0x3FFDA000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 13 + { (uint8_t *)0x3FFDC000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 14 + { (uint8_t *)0x3FFDE000, 0x2000, DMAONLY_TAG, 0}, //pool 10-13, mmu page 15 { (uint8_t *)0x3FFE0000, 0x4000, 1, 0x400BC000}, //pool 9 blk 1 { (uint8_t *)0x3FFE4000, 0x4000, 1, 0x400B8000}, //pool 9 blk 0 { (uint8_t *)0x3FFE8000, 0x8000, 1, 0x400B0000}, //pool 8 <- can be remapped to ROM, used for MAC dump @@ -307,6 +318,21 @@ void heap_alloc_caps_init() { disable_mem_region((void*)0x3f800000, (void*)0x3fc00000); //SPI SRAM not installed #endif + +#if CONFIG_MEMMAP_RESERVE_DMA + int resv=CONFIG_MEMMAP_RESERVE_DMA_BYTES; + for (int i=0; regions[i].xSizeInBytes!=0; i++) { + if (regions[i].xTag==DMAONLY_TAG) { + if (resv>0) { + resv-=regions[i].xSizeInBytes; + } else { + //We have all the reserved memory we need. Un-tag this region as reserved. + regions[i].xTag=DMAONLY_UNTAG; + } + } + } +#endif + //The heap allocator will treat every region given to it as separate. In order to get bigger ranges of contiguous memory, //it's useful to coalesce adjacent regions that have the same tag. @@ -428,6 +454,12 @@ void *pvPortMallocCaps( size_t xWantedSize, uint32_t caps ) //Non-os stack lives here and is still in use. Don't alloc here. continue; } +#if CONFIG_MEMMAP_RESERVE_DMA + if (tag==DMAONLY_TAG && (!(caps & (MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL)))) { + //Never allocate memory that doesn't specifically ask for it in DMA-reserved region. + continue; + } +#endif if ((tag_desc[tag].prio[prio]&caps)!=0) { //Tag 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. diff --git a/components/esp32/include/esp_heap_alloc_caps.h b/components/esp32/include/esp_heap_alloc_caps.h index 0c4b81262..ab5cb6b1b 100644 --- a/components/esp32/include/esp_heap_alloc_caps.h +++ b/components/esp32/include/esp_heap_alloc_caps.h @@ -29,6 +29,7 @@ #define MALLOC_CAP_PID7 (1<<9) ///< Memory must be mapped to PID7 memory space #define MALLOC_CAP_SPIRAM (1<<10) ///< Memory must be in SPI-attached RAM #define MALLOC_CAP_INTERNAL (1<<11) ///< Memory must be internal to the chip +#define MALLOC_CAP_DMAONLY (1<<12) ///< Memory is in DMAONLY reserved region. Used to query free memory there. #define MALLOC_CAP_INVALID (1<<31) ///< Memory can't be used / list end marker diff --git a/components/freertos/include/freertos/heap_regions.h b/components/freertos/include/freertos/heap_regions.h index 090c5b9b3..a08e38c37 100644 --- a/components/freertos/include/freertos/heap_regions.h +++ b/components/freertos/include/freertos/heap_regions.h @@ -17,7 +17,7 @@ #include "freertos/FreeRTOS.h" /* The maximum amount of tags in use */ -#define HEAPREGIONS_MAX_TAGCOUNT 16 +#define HEAPREGIONS_MAX_TAGCOUNT 17 /** * @brief Structure to define a memory region