Add reserved DMA/internal region

This commit is contained in:
Jeroen Domburg 2017-05-18 16:48:52 +08:00
parent 74a535ff70
commit b52788e764
4 changed files with 82 additions and 26 deletions

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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