mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
heap: Rename memory "tags" to "types" to avoid confusion w/ old tag allocator API
This commit is contained in:
committed by
Angus Gratton
parent
ee28fafcdf
commit
ad60c30de0
@@ -62,7 +62,7 @@ inline static uint32_t get_all_caps(const heap_t *heap)
|
||||
return 0;
|
||||
}
|
||||
uint32_t all_caps = 0;
|
||||
for (int prio = 0; prio < SOC_HEAP_TAG_NO_PRIOS; prio++) {
|
||||
for (int prio = 0; prio < SOC_MEMORY_TYPE_NO_PRIOS; prio++) {
|
||||
all_caps |= heap->caps[prio];
|
||||
}
|
||||
return all_caps;
|
||||
@@ -87,7 +87,7 @@ IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps )
|
||||
//If any, EXEC memory should be 32-bit aligned, so round up to the next multiple of 4.
|
||||
size = (size + 3) & (~3);
|
||||
}
|
||||
for (int prio = 0; prio < SOC_HEAP_TAG_NO_PRIOS; prio++) {
|
||||
for (int prio = 0; prio < SOC_MEMORY_TYPE_NO_PRIOS; prio++) {
|
||||
//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];
|
||||
@@ -96,7 +96,7 @@ IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps )
|
||||
//doesn't cover, see if they're available in other prios.
|
||||
remCaps = caps & (~heap->caps[prio]); //Remaining caps to be fulfilled
|
||||
int j = prio + 1;
|
||||
while (remCaps != 0 && j < SOC_HEAP_TAG_NO_PRIOS) {
|
||||
while (remCaps != 0 && j < SOC_MEMORY_TYPE_NO_PRIOS) {
|
||||
remCaps = remCaps & (~heap->caps[j]);
|
||||
j++;
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ static void disable_mem_region(soc_memory_region_t *regions, intptr_t from, intp
|
||||
intptr_t regEnd = region->start + region->size;
|
||||
if (regStart >= from && regEnd <= to) {
|
||||
//Entire region falls in the range. Disable entirely.
|
||||
regions[i].tag = -1;
|
||||
regions[i].type = -1;
|
||||
} else if (regStart >= from && regEnd > to && regStart < to) {
|
||||
//Start of the region falls in the range. Modify address/len.
|
||||
intptr_t overlap = to - regStart;
|
||||
@@ -72,7 +72,7 @@ static void disable_mem_region(soc_memory_region_t *regions, intptr_t from, intp
|
||||
} else if (regStart < from && regEnd > to) {
|
||||
//Range punches a hole in the region! We do not support this.
|
||||
ESP_EARLY_LOGE(TAG, "region %d: hole punching is not supported!", i);
|
||||
regions->tag = -1; //Just disable memory region. That'll teach them!
|
||||
regions->type = -1; //Just disable memory region. That'll teach them!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,13 +108,13 @@ void heap_caps_init()
|
||||
}
|
||||
|
||||
//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.
|
||||
//it's useful to coalesce adjacent regions that have the same type.
|
||||
|
||||
for (int i = 1; i < soc_memory_region_count; i++) {
|
||||
soc_memory_region_t *a = ®ions[i - 1];
|
||||
soc_memory_region_t *b = ®ions[i];
|
||||
if (b->start == a->start + a->size && b->tag == a->tag ) {
|
||||
a->tag = -1;
|
||||
if (b->start == a->start + a->size && b->type == a->type ) {
|
||||
a->type = -1;
|
||||
b->start = a->start;
|
||||
b->size += a->size;
|
||||
}
|
||||
@@ -123,7 +123,7 @@ void heap_caps_init()
|
||||
/* Count the heaps left after merging */
|
||||
num_registered_heaps = 0;
|
||||
for (int i = 0; i < soc_memory_region_count; i++) {
|
||||
if (regions[i].tag != -1) {
|
||||
if (regions[i].type != -1) {
|
||||
num_registered_heaps++;
|
||||
}
|
||||
}
|
||||
@@ -139,24 +139,24 @@ void heap_caps_init()
|
||||
ESP_EARLY_LOGI(TAG, "Initializing. RAM available for dynamic allocation:");
|
||||
for (int i = 0; i < soc_memory_region_count; i++) {
|
||||
soc_memory_region_t *region = ®ions[i];
|
||||
const soc_memory_tag_desc_t *tag = &soc_memory_tags[region->tag];
|
||||
const soc_memory_type_desc_t *type = &soc_memory_types[region->type];
|
||||
heap_t *heap = &temp_heaps[heap_idx];
|
||||
if (region->tag == -1) {
|
||||
if (region->type == -1) {
|
||||
continue;
|
||||
}
|
||||
heap_idx++;
|
||||
assert(heap_idx <= num_registered_heaps);
|
||||
|
||||
heap->tag = region->tag;
|
||||
heap->type = region->type;
|
||||
heap->start = region->start;
|
||||
heap->end = region->start + region->size;
|
||||
memcpy(heap->caps, tag->caps, sizeof(heap->caps));
|
||||
memcpy(heap->caps, type->caps, sizeof(heap->caps));
|
||||
vPortCPUInitializeMutex(&heap->heap_mux);
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "At %08X len %08X (%d KiB): %s",
|
||||
region->start, region->size, region->size / 1024, tag->name);
|
||||
region->start, region->size, region->size / 1024, type->name);
|
||||
|
||||
if (tag->startup_stack) {
|
||||
if (type->startup_stack) {
|
||||
/* Will be registered when OS scheduler starts */
|
||||
heap->heap = NULL;
|
||||
} else {
|
||||
|
@@ -25,8 +25,8 @@
|
||||
|
||||
/* Type for describing each registered heap */
|
||||
typedef struct {
|
||||
size_t tag;
|
||||
uint32_t caps[SOC_HEAP_TAG_NO_PRIOS]; ///< Capabilities for this tag (as a prioritised set). Copied from soc_memory_tags so it's in RAM not flash.
|
||||
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.
|
||||
intptr_t start;
|
||||
intptr_t end;
|
||||
portMUX_TYPE heap_mux;
|
||||
|
@@ -24,53 +24,53 @@
|
||||
/* Memory layout for ESP32 SoC */
|
||||
|
||||
/*
|
||||
Tag descriptors. These describe the capabilities of a bit of memory that's tagged with the index into this table.
|
||||
Each tag contains NO_PRIOS entries; later entries are only taken if earlier ones can't fulfill the memory request.
|
||||
*/
|
||||
const soc_memory_tag_desc_t soc_memory_tags[] = {
|
||||
//Tag 0: Plain ole D-port RAM
|
||||
{ "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }, false, false},
|
||||
//Tag 1: Plain ole D-port RAM which has an alias on the I-port
|
||||
//(This DRAM is also the region used by ROM during startup)
|
||||
{ "D/IRAM", { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC }, true, true},
|
||||
//Tag 2: IRAM
|
||||
{ "IRAM", { MALLOC_CAP_EXEC|MALLOC_CAP_32BIT, 0, 0 }, false, false},
|
||||
//Tag 3-8: PID 2-7 IRAM
|
||||
{ "PID2IRAM", { MALLOC_CAP_PID2, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID3IRAM", { MALLOC_CAP_PID3, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID4IRAM", { MALLOC_CAP_PID4, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID5IRAM", { MALLOC_CAP_PID5, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID6IRAM", { MALLOC_CAP_PID6, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID7IRAM", { MALLOC_CAP_PID7, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
//Tag 9-14: PID 2-7 DRAM
|
||||
{ "PID2DRAM", { MALLOC_CAP_PID2, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID3DRAM", { MALLOC_CAP_PID3, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID4DRAM", { MALLOC_CAP_PID4, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID5DRAM", { MALLOC_CAP_PID5, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID6DRAM", { MALLOC_CAP_PID6, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID7DRAM", { MALLOC_CAP_PID7, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
//Tag 15: SPI SRAM data
|
||||
{ "SPISRAM", { MALLOC_CAP_SPISRAM, 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false, false},
|
||||
};
|
||||
Memory type descriptors. These describe the capabilities of a type of memory in the SoC. Each type of memory
|
||||
map consist of one or more regions in the address space.
|
||||
|
||||
const size_t soc_memory_tag_count = sizeof(soc_memory_tags)/sizeof(soc_memory_tag_desc_t);
|
||||
Each type contains an array of prioritised capabilities; types with later entries are only taken if earlier
|
||||
ones can't fulfill the memory request.
|
||||
|
||||
/*
|
||||
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
|
||||
change the tags of some regions because eg BT is detected, applications are loaded etc.
|
||||
|
||||
The priorities here roughly work like this:
|
||||
The prioritised capabilities work roughly like this:
|
||||
- For a normal malloc (MALLOC_CAP_8BIT), give away the DRAM-only memory first, then pass off any dual-use IRAM regions,
|
||||
finally eat into the application memory.
|
||||
- For a malloc where 32-bit-aligned-only access is okay, first allocate IRAM, then DRAM, finally application IRAM.
|
||||
- Application mallocs (PIDx) will allocate IRAM first, if possible, then DRAM.
|
||||
- Most other malloc caps only fit in one region anyway.
|
||||
|
||||
These region descriptors are very ESP32 specific, because they describe the memory pools available there.
|
||||
*/
|
||||
const soc_memory_type_desc_t soc_memory_types[] = {
|
||||
//Type 0: Plain ole D-port RAM
|
||||
{ "DRAM", { MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT, 0 }, false, false},
|
||||
//Type 1: Plain ole D-port RAM which has an alias on the I-port
|
||||
//(This DRAM is also the region used by ROM during startup)
|
||||
{ "D/IRAM", { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC }, true, true},
|
||||
//Type 2: IRAM
|
||||
{ "IRAM", { MALLOC_CAP_EXEC|MALLOC_CAP_32BIT, 0, 0 }, false, false},
|
||||
//Type 3-8: PID 2-7 IRAM
|
||||
{ "PID2IRAM", { MALLOC_CAP_PID2, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID3IRAM", { MALLOC_CAP_PID3, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID4IRAM", { MALLOC_CAP_PID4, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID5IRAM", { MALLOC_CAP_PID5, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID6IRAM", { MALLOC_CAP_PID6, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID7IRAM", { MALLOC_CAP_PID7, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
|
||||
//Type 9-14: PID 2-7 DRAM
|
||||
{ "PID2DRAM", { MALLOC_CAP_PID2, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID3DRAM", { MALLOC_CAP_PID3, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID4DRAM", { MALLOC_CAP_PID4, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID5DRAM", { MALLOC_CAP_PID5, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID6DRAM", { MALLOC_CAP_PID6, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
{ "PID7DRAM", { MALLOC_CAP_PID7, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT }, false, false},
|
||||
//Type 15: SPI SRAM data
|
||||
{ "SPISRAM", { MALLOC_CAP_SPISRAM, 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false, false},
|
||||
};
|
||||
|
||||
Because of requirements in the coalescing code as well as the heap allocator itself, this list should always
|
||||
be sorted from low to high start address.
|
||||
const size_t soc_memory_type_count = sizeof(soc_memory_types)/sizeof(soc_memory_type_desc_t);
|
||||
|
||||
/*
|
||||
Region descriptors. These describe all regions of memory available, and map them to a type in the above type.
|
||||
|
||||
Because of requirements in the coalescing code which merges adjacent regions, this list should always be sorted
|
||||
from low to high start address.
|
||||
*/
|
||||
const soc_memory_region_t soc_memory_regions[] = {
|
||||
{ 0x3F800000, 0x20000, 15, 0}, //SPI SRAM, if available
|
||||
@@ -122,14 +122,18 @@ const soc_memory_region_t soc_memory_regions[] = {
|
||||
const size_t soc_memory_region_count = sizeof(soc_memory_regions)/sizeof(soc_memory_region_t);
|
||||
|
||||
|
||||
/* Reserved memory regions */
|
||||
/* Reserved memory regions
|
||||
|
||||
These are removed from the soc_memory_regions array when heaps are created.
|
||||
*/
|
||||
const soc_reserved_region_t soc_reserved_regions[] = {
|
||||
{ 0x40070000, 0x40078000 }, //CPU0 cache region
|
||||
{ 0x40078000, 0x40080000 }, //CPU1 cache region
|
||||
|
||||
/* Warning: The ROM stack is located in the 0x3ffe0000 area. We do not specifically disable that area here because
|
||||
after the scheduler has started, the ROM stack is not used anymore by anything. We handle it instead by not allowing
|
||||
any mallocs from tag 1 (the IRAM/DRAM region) until the scheduler has started.
|
||||
any mallocs memory regions with the startup_stack flag set (these are the IRAM/DRAM region) until the
|
||||
scheduler has started.
|
||||
|
||||
The 0x3ffe0000 region also contains static RAM for various ROM functions. The following lines
|
||||
reserve the regions for UART and ETSC, so these functions are usable. Libraries like xtos, which are
|
||||
@@ -138,8 +142,10 @@ const soc_reserved_region_t soc_reserved_regions[] = {
|
||||
|
||||
Enabling the heap allocator for this region but disabling allocation here until FreeRTOS is started up
|
||||
is a somewhat risky action in theory, because on initializing the allocator, the multi_heap implementation
|
||||
will go and write metadata at the start and end of all regions. For the ESP32, these linked
|
||||
list entries happen to end up in a region that is not touched by the stack; they can be placed safely there.*/
|
||||
will go and write metadata at the start and end of all regions. For the ESP32, these linked
|
||||
list entries happen to end up in a region that is not touched by the stack; they can be placed safely there.
|
||||
*/
|
||||
|
||||
{ 0x3ffe0000, 0x3ffe0440 }, //Reserve ROM PRO data region
|
||||
{ 0x3ffe4000, 0x3ffe4350 }, //Reserve ROM APP data region
|
||||
|
||||
|
@@ -18,20 +18,20 @@
|
||||
|
||||
#include "soc/soc.h"
|
||||
|
||||
#define SOC_HEAP_TAG_NO_PRIOS 3
|
||||
#define SOC_MEMORY_TYPE_NO_PRIOS 3
|
||||
|
||||
/* Tag descriptor holds a description for a particular 'tagged' type of memory on a particular SoC.
|
||||
/* Type descriptor holds a description for a particular type of memory on a particular SoC.
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name; ///< Name of this tag
|
||||
uint32_t caps[SOC_HEAP_TAG_NO_PRIOS]; ///< Capabilities for this tag (as a prioritised set)
|
||||
bool aliased_iram; ///< If true, this tag is also mapped in IRAM
|
||||
bool startup_stack; ///< If true, this tag is used for ROM stack during startup
|
||||
} soc_memory_tag_desc_t;
|
||||
const char *name; ///< Name of this memory type
|
||||
uint32_t caps[SOC_MEMORY_TYPE_NO_PRIOS]; ///< Capabilities for this memory type (as a prioritised set)
|
||||
bool aliased_iram; ///< If true, this is data memory that is is also mapped in IRAM
|
||||
bool startup_stack; ///< If true, memory of this type is used for ROM stack during startup
|
||||
} soc_memory_type_desc_t;
|
||||
|
||||
/* Constant table of tag descriptors for all this SoC's tags */
|
||||
extern const soc_memory_tag_desc_t soc_memory_tags[];
|
||||
extern const size_t soc_memory_tag_count;
|
||||
extern const soc_memory_type_desc_t soc_memory_types[];
|
||||
extern const size_t soc_memory_type_count;
|
||||
|
||||
/* Region descriptor holds a description for a particular region of memory on a particular SoC.
|
||||
*/
|
||||
@@ -39,7 +39,7 @@ typedef struct
|
||||
{
|
||||
intptr_t start; ///< Start address of the region
|
||||
size_t size; ///< Size of the region in bytes
|
||||
size_t tag; ///< Tag for the region (index into soc_memory_tag_descriptors)
|
||||
size_t type; ///< Type of the region (index into soc_memory_types array)
|
||||
intptr_t iram_address; ///< If non-zero, is equivalent address in IRAM
|
||||
} soc_memory_region_t;
|
||||
|
||||
|
Reference in New Issue
Block a user