mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 20:54:32 +02:00
Merge branch 'feature/component_memory_reservation' into 'master'
soc: Allow components to reserve fixed memory ranges that they need See merge request idf/esp-idf!2596
This commit is contained in:
@@ -149,6 +149,11 @@ static btdm_dram_available_region_t btdm_dram_available_region[] = {
|
||||
{ESP_BT_MODE_BTDM, 0x3ffbdb28, 0x3ffc0000},
|
||||
};
|
||||
|
||||
/* Reserve the full memory region used by Bluetooth Controller,
|
||||
some may be released later at runtime. */
|
||||
SOC_RESERVE_MEMORY_REGION(0x3ffb0000, 0x3ffc0000, bt_hardware_shared_mem);
|
||||
SOC_RESERVE_MEMORY_REGION(0x3ffae6e0, 0x3ffaff10, rom_bt_data);
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
typedef struct {
|
||||
QueueHandle_t handle;
|
||||
|
@@ -52,6 +52,7 @@ SECTIONS
|
||||
/* Send .iram0 code to iram */
|
||||
.iram0.vectors :
|
||||
{
|
||||
_iram_start = ABSOLUTE(.);
|
||||
/* Vectors go to IRAM */
|
||||
_init_start = ABSOLUTE(.);
|
||||
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
|
||||
@@ -85,11 +86,7 @@ SECTIONS
|
||||
*(.init.literal)
|
||||
*(.init)
|
||||
_init_end = ABSOLUTE(.);
|
||||
|
||||
/* This goes here, not at top of linker script, so addr2line finds it last,
|
||||
and uses it in preference to the first symbol in IRAM */
|
||||
_iram_start = ABSOLUTE(0);
|
||||
} > iram0_0_seg
|
||||
} > iram0_0_seg
|
||||
|
||||
.iram0.text :
|
||||
{
|
||||
@@ -104,15 +101,17 @@ SECTIONS
|
||||
*libapp_trace.a:(.literal .text .literal.* .text.*)
|
||||
*libxtensa-debug-module.a:eri.o(.literal .text .literal.* .text.*)
|
||||
*librtc.a:(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_*.o(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:cpu_util.o(.literal .text .literal.* .text.*)
|
||||
*libhal.a:(.literal .text .literal.* .text.*)
|
||||
*libgcc.a:lib2funcs.o(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:spi_flash_rom_patch.o(.literal .text .literal.* .text.*)
|
||||
*libgcov.a:(.literal .text .literal.* .text.*)
|
||||
INCLUDE esp32.spiram.rom-functions-iram.ld
|
||||
_iram_text_end = ABSOLUTE(.);
|
||||
_iram_end = ABSOLUTE(.);
|
||||
} > iram0_0_seg
|
||||
|
||||
|
||||
.dram0.data :
|
||||
{
|
||||
_data_start = ABSOLUTE(.);
|
||||
@@ -231,6 +230,11 @@ SECTIONS
|
||||
*(.xt_except_desc_end)
|
||||
*(.dynamic)
|
||||
*(.gnu.version_d)
|
||||
/* Addresses of memory regions reserved via
|
||||
SOC_RESERVE_MEMORY_REGION() */
|
||||
soc_reserved_memory_region_start = ABSOLUTE(.);
|
||||
KEEP (*(.reserved_memory_address))
|
||||
soc_reserved_memory_region_end = ABSOLUTE(.);
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
/* Literals are also RO data. */
|
||||
_lit4_start = ABSOLUTE(.);
|
||||
|
@@ -52,74 +52,21 @@ void heap_caps_enable_nonos_stack_heaps()
|
||||
}
|
||||
}
|
||||
|
||||
//Modify regions array to disable the given range of memory.
|
||||
static void disable_mem_region(soc_memory_region_t *regions, intptr_t from, intptr_t to)
|
||||
{
|
||||
//Align from and to on word boundaries
|
||||
from = from & ~3;
|
||||
to = (to + 3) & ~3;
|
||||
|
||||
for (int i = 0; i < soc_memory_region_count; i++) {
|
||||
soc_memory_region_t *region = ®ions[i];
|
||||
|
||||
intptr_t regStart = region->start;
|
||||
intptr_t regEnd = region->start + region->size;
|
||||
if (regStart >= from && regEnd <= to) {
|
||||
//Entire region falls in the range. Disable entirely.
|
||||
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;
|
||||
region->start += overlap;
|
||||
region->size -= overlap;
|
||||
if (region->iram_address) {
|
||||
region->iram_address += overlap;
|
||||
}
|
||||
} else if (regStart < from && regEnd > from && regEnd <= to) {
|
||||
//End of the region falls in the range. Modify length.
|
||||
region->size -= regEnd - from;
|
||||
} 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->type = -1; //Just disable memory region. That'll teach them!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Warning: These variables are assumed to have the start and end of the data and iram
|
||||
area used statically by the program, respectively. These variables are defined in the ld
|
||||
file.
|
||||
*/
|
||||
extern int _data_start, _heap_start, _init_start, _iram_text_end;
|
||||
|
||||
/*
|
||||
Initialize the heap allocator. We pass it a bunch of region descriptors, but we need to modify those first to accommodate for
|
||||
the data as loaded by the bootloader.
|
||||
ToDo: The regions are different when stuff like trace memory, BT, ... is used. Modify the regions struct on the fly for this.
|
||||
Same with loading of apps. Same with using SPI RAM.
|
||||
*/
|
||||
/* Initialize the heap allocator to use all of the memory not
|
||||
used by static data or reserved for other purposes
|
||||
*/
|
||||
void heap_caps_init()
|
||||
{
|
||||
/* Copy the soc_memory_regions data to the stack, so we can
|
||||
manipulate it. */
|
||||
soc_memory_region_t regions[soc_memory_region_count];
|
||||
memcpy(regions, soc_memory_regions, sizeof(soc_memory_region_t)*soc_memory_region_count);
|
||||
|
||||
//Disable the bits of memory where this code is loaded.
|
||||
disable_mem_region(regions, (intptr_t)&_data_start, (intptr_t)&_heap_start); //DRAM used by bss/data static variables
|
||||
disable_mem_region(regions, (intptr_t)&_init_start, (intptr_t)&_iram_text_end); //IRAM used by code
|
||||
|
||||
// Disable all regions reserved on this SoC
|
||||
for (int i = 0; i < soc_reserved_region_count; i++) {
|
||||
disable_mem_region(regions, soc_reserved_regions[i].start,
|
||||
soc_reserved_regions[i].end);
|
||||
}
|
||||
/* Get the array of regions that we can use for heaps
|
||||
(with reserved memory removed already.)
|
||||
*/
|
||||
size_t num_regions = soc_get_available_memory_region_max_count();
|
||||
soc_memory_region_t regions[num_regions];
|
||||
num_regions = soc_get_available_memory_regions(regions);
|
||||
|
||||
//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 type.
|
||||
|
||||
for (int i = 1; i < soc_memory_region_count; i++) {
|
||||
for (int i = 1; i < num_regions; i++) {
|
||||
soc_memory_region_t *a = ®ions[i - 1];
|
||||
soc_memory_region_t *b = ®ions[i];
|
||||
if (b->start == a->start + a->size && b->type == a->type ) {
|
||||
@@ -131,7 +78,7 @@ void heap_caps_init()
|
||||
|
||||
/* Count the heaps left after merging */
|
||||
size_t num_heaps = 0;
|
||||
for (int i = 0; i < soc_memory_region_count; i++) {
|
||||
for (int i = 0; i < num_regions; i++) {
|
||||
if (regions[i].type != -1) {
|
||||
num_heaps++;
|
||||
}
|
||||
@@ -145,7 +92,7 @@ void heap_caps_init()
|
||||
size_t heap_idx = 0;
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Initializing. RAM available for dynamic allocation:");
|
||||
for (int i = 0; i < soc_memory_region_count; i++) {
|
||||
for (int i = 0; i < num_regions; i++) {
|
||||
soc_memory_region_t *region = ®ions[i];
|
||||
const soc_memory_type_desc_t *type = &soc_memory_types[region->type];
|
||||
heap_t *heap = &temp_heaps[heap_idx];
|
||||
|
@@ -1,5 +1,6 @@
|
||||
# currently the only SoC supported; to be moved into Kconfig
|
||||
SOC_NAME := esp32
|
||||
|
||||
COMPONENT_SRCDIRS := $(SOC_NAME)
|
||||
COMPONENT_SRCDIRS := $(SOC_NAME) src/
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := $(SOC_NAME)/include include
|
||||
|
@@ -60,8 +60,10 @@ const soc_memory_type_desc_t soc_memory_types[] = {
|
||||
{ "PID5DRAM", { MALLOC_CAP_PID5|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
|
||||
{ "PID6DRAM", { MALLOC_CAP_PID6|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
|
||||
{ "PID7DRAM", { MALLOC_CAP_PID7|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
|
||||
#ifdef CONFIG_SPIRAM_SUPPORT
|
||||
//Type 15: SPI SRAM data
|
||||
{ "SPIRAM", { MALLOC_CAP_SPIRAM|MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false, false},
|
||||
#endif
|
||||
};
|
||||
|
||||
const size_t soc_memory_type_count = sizeof(soc_memory_types)/sizeof(soc_memory_type_desc_t);
|
||||
@@ -73,7 +75,9 @@ Because of requirements in the coalescing code which merges adjacent regions, th
|
||||
from low to high start address.
|
||||
*/
|
||||
const soc_memory_region_t soc_memory_regions[] = {
|
||||
#ifdef CONFIG_SPIRAM_SUPPORT
|
||||
{ 0x3F800000, 0x400000, 15, 0}, //SPI SRAM, if available
|
||||
#endif
|
||||
{ 0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code
|
||||
{ 0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory
|
||||
{ 0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions.
|
||||
@@ -126,9 +130,8 @@ const size_t soc_memory_region_count = sizeof(soc_memory_regions)/sizeof(soc_mem
|
||||
|
||||
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
|
||||
SOC_RESERVE_MEMORY_REGION(0x40070000, 0x40078000, cpu0_cache);
|
||||
SOC_RESERVE_MEMORY_REGION(0x40078000, 0x40080000, cpu1_cache);
|
||||
|
||||
/* 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
|
||||
@@ -146,27 +149,21 @@ const soc_reserved_region_t soc_reserved_regions[] = {
|
||||
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
|
||||
SOC_RESERVE_MEMORY_REGION(0x3ffe0000, 0x3ffe0440, rom_pro_data); //Reserve ROM PRO data region
|
||||
SOC_RESERVE_MEMORY_REGION(0x3ffe4000, 0x3ffe4350, rom_app_data); //Reserve ROM APP data region
|
||||
|
||||
#if CONFIG_BT_ENABLED
|
||||
{ 0x3ffb0000, 0x3ffc0000 }, //Reserve BT hardware shared memory & BT data region
|
||||
{ 0x3ffae000, 0x3ffaff10 }, //Reserve ROM data region, inc region needed for BT ROM routines
|
||||
#else
|
||||
{ 0x3ffae000, 0x3ffae6e0 }, //Reserve ROM data region
|
||||
#endif
|
||||
SOC_RESERVE_MEMORY_REGION(0x3ffae000, 0x3ffae6e0, rom_data);
|
||||
|
||||
#if CONFIG_MEMMAP_TRACEMEM
|
||||
#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
|
||||
{ 0x3fff8000, 0x40000000 }, //Reserve trace mem region
|
||||
SOC_RESERVE_MEMORY_REGION(0x3fff8000, 0x40000000, trace_mem); //Reserve trace mem region
|
||||
#else
|
||||
{ 0x3fff8000, 0x3fffc000 }, //Reserve trace mem region
|
||||
SOC_RESERVE_MEMORY_REGION(0x3fff8000, 0x3fffc000, trace_mem); //Reserve trace mem region
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{ 0x3f800000, 0x3fC00000 }, //SPI RAM gets added later if needed, in spiram.c; reserve it for now
|
||||
};
|
||||
|
||||
const size_t soc_reserved_region_count = sizeof(soc_reserved_regions)/sizeof(soc_reserved_region_t);
|
||||
|
||||
#ifdef CONFIG_SPIRAM_SUPPORT
|
||||
SOC_RESERVE_MEMORY_REGION(0x3f800000, 0x3fC00000, spi_ram); //SPI RAM gets added later if needed, in spiram.c; reserve it for now
|
||||
#endif
|
||||
|
||||
#endif /* BOOTLOADER_BUILD */
|
||||
|
@@ -57,8 +57,55 @@ typedef struct
|
||||
intptr_t end;
|
||||
} soc_reserved_region_t;
|
||||
|
||||
extern const soc_reserved_region_t soc_reserved_regions[];
|
||||
extern const size_t soc_reserved_region_count;
|
||||
/* Use this macro to reserved a fixed region of RAM (hardcoded addresses)
|
||||
* for a particular purpose.
|
||||
*
|
||||
* Usually used to mark out memory addresses needed for hardware or ROM code
|
||||
* purposes.
|
||||
*
|
||||
* Don't call this macro from user code which can use normal C static allocation
|
||||
* instead.
|
||||
*
|
||||
* @param START Start address to be reserved.
|
||||
* @param END One after the address of the last byte to be reserved. (ie length of
|
||||
* the reserved region is (END - START) in bytes.
|
||||
* @param NAME Name for the reserved region. Must be a valid variable name,
|
||||
* unique to this source file.
|
||||
*/
|
||||
#define SOC_RESERVE_MEMORY_REGION(START, END, NAME) \
|
||||
__attribute__((section(".reserved_memory_address"))) __attribute__((used)) \
|
||||
static soc_reserved_region_t reserved_region_##NAME = { START, END };
|
||||
|
||||
/* Return available memory regions for this SoC. Each available memory
|
||||
* region is a contiguous piece of memory which is not being used by
|
||||
* static data, used by ROM code, or reserved by a component using
|
||||
* the SOC_RESERVE_MEMORY_REGION() macro.
|
||||
*
|
||||
* This result is soc_memory_regions[] minus all regions reserved
|
||||
* via the SOC_RESERVE_MEMORY_REGION() macro (which may also split
|
||||
* some regions up.)
|
||||
*
|
||||
* At startup, all available memory returned by this function is
|
||||
* registered as heap space.
|
||||
*
|
||||
* @note OS-level startup function only, not recommended to call from
|
||||
* app code.
|
||||
*
|
||||
* @param regions Pointer to an array for reading available regions into.
|
||||
* Size of the array should be at least the result of
|
||||
* soc_get_available_memory_region_max_count(). Entries in the array
|
||||
* will be ordered by memory address.
|
||||
*
|
||||
* @return Number of entries copied to 'regions'. Will be no greater than
|
||||
* the result of soc_get_available_memory_region_max_count().
|
||||
*/
|
||||
size_t soc_get_available_memory_regions(soc_memory_region_t *regions);
|
||||
|
||||
/* Return the maximum number of available memory regions which could be
|
||||
* returned by soc_get_available_memory_regions(). Used to size the
|
||||
* array passed to that function.
|
||||
*/
|
||||
size_t soc_get_available_memory_region_max_count();
|
||||
|
||||
inline static bool IRAM_ATTR esp_ptr_dma_capable(const void *p)
|
||||
{
|
||||
|
191
components/soc/src/memory_layout_utils.c
Normal file
191
components/soc/src/memory_layout_utils.c
Normal file
@@ -0,0 +1,191 @@
|
||||
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
|
||||
static const char *TAG = "memory_layout";
|
||||
|
||||
/* These variables come from the linker script,
|
||||
delimit the start and end of entries created via
|
||||
SOC_RESERVE_MEMORY_REGION() macro.
|
||||
*/
|
||||
extern soc_reserved_region_t soc_reserved_memory_region_start;
|
||||
extern soc_reserved_region_t soc_reserved_memory_region_end;
|
||||
|
||||
/*
|
||||
These variables have the start and end of the data and static IRAM
|
||||
area used by the program. Defined in the linker script.
|
||||
*/
|
||||
extern int _data_start, _bss_end, _iram_start, _iram_end;
|
||||
|
||||
/* static DRAM & IRAM chunks */
|
||||
static const size_t EXTRA_RESERVED_REGIONS = 2;
|
||||
|
||||
static size_t s_get_num_reserved_regions()
|
||||
{
|
||||
return ( ( &soc_reserved_memory_region_end
|
||||
- &soc_reserved_memory_region_start ) +
|
||||
EXTRA_RESERVED_REGIONS );
|
||||
}
|
||||
|
||||
size_t soc_get_available_memory_region_max_count()
|
||||
{
|
||||
/* Worst-case: each reserved memory region splits an available
|
||||
region in two, so the maximum possible number of regions
|
||||
is the number of regions of memory plus the number of reservations */
|
||||
return soc_memory_region_count + s_get_num_reserved_regions();
|
||||
}
|
||||
|
||||
static int s_compare_reserved_regions(const void *a, const void *b)
|
||||
{
|
||||
const soc_reserved_region_t *r_a = (soc_reserved_region_t *)a;
|
||||
const soc_reserved_region_t *r_b = (soc_reserved_region_t *)b;
|
||||
return (int)r_a->start - (int)r_b->start;
|
||||
}
|
||||
|
||||
/* Initialize a mutable array of reserved regions in 'reserved',
|
||||
then sort it by start address and check for overlapping
|
||||
reserved regions (illegal).
|
||||
*/
|
||||
static void s_prepare_reserved_regions(soc_reserved_region_t *reserved, size_t count)
|
||||
{
|
||||
memcpy(reserved + EXTRA_RESERVED_REGIONS,
|
||||
&soc_reserved_memory_region_start,
|
||||
(count - EXTRA_RESERVED_REGIONS) * sizeof(soc_reserved_region_t));
|
||||
|
||||
/* Add the EXTRA_RESERVED_REGIONS at the beginning */
|
||||
reserved[0].start = (intptr_t)&_data_start; /* DRAM used by data+bss */
|
||||
reserved[0].end = (intptr_t)&_bss_end;
|
||||
reserved[1].start = (intptr_t)&_iram_start; /* IRAM used by code */
|
||||
reserved[1].end = (intptr_t)&_iram_end;
|
||||
|
||||
/* Sort by starting address */
|
||||
qsort(reserved, count, sizeof(soc_reserved_region_t), s_compare_reserved_regions);
|
||||
|
||||
/* Validity checks */
|
||||
ESP_EARLY_LOGV(TAG, "reserved range is %p - %p",
|
||||
&soc_reserved_memory_region_start,
|
||||
&soc_reserved_memory_region_end);
|
||||
ESP_EARLY_LOGD(TAG, "Checking %d reserved memory ranges:", count);
|
||||
for (size_t i = 0; i < count; i++)
|
||||
{
|
||||
ESP_EARLY_LOGD(TAG, "Reserved memory range 0x%08x - 0x%08x",
|
||||
reserved[i].start, reserved[i].end);
|
||||
reserved[i].start = reserved[i].start & ~3; /* expand all reserved areas to word boundaries */
|
||||
reserved[i].end = (reserved[i].end + 3) & ~3;
|
||||
assert(reserved[i].start < reserved[i].end);
|
||||
if (i < count - 1) {
|
||||
assert(reserved[i+1].start > reserved[i].start);
|
||||
if (reserved[i].end > reserved[i+1].start) {
|
||||
ESP_EARLY_LOGE(TAG, "SOC_RESERVE_MEMORY_REGION region range " \
|
||||
"0x%08x - 0x%08x overlaps with 0x%08x - 0x%08x",
|
||||
reserved[i].start, reserved[i].end, reserved[i+1].start,
|
||||
reserved[i+1].end);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t soc_get_available_memory_regions(soc_memory_region_t *regions)
|
||||
{
|
||||
soc_memory_region_t *out_region = regions;
|
||||
/* make a local copy of the "input" regions so we can modify them */
|
||||
soc_memory_region_t in_regions[soc_memory_region_count];
|
||||
memcpy(in_regions, soc_memory_regions, sizeof(in_regions));
|
||||
soc_memory_region_t *in_region = in_regions;
|
||||
|
||||
size_t num_reserved = s_get_num_reserved_regions();
|
||||
soc_reserved_region_t reserved[num_reserved];
|
||||
|
||||
s_prepare_reserved_regions(reserved, num_reserved);
|
||||
|
||||
/* Go through the "in" regions (full regions, with no reserved
|
||||
sections removed from them) one at a time, trim off each reserved
|
||||
region, and then copy them to an out_region once trimmed
|
||||
*/
|
||||
ESP_EARLY_LOGD(TAG, "Building list of available memory regions:");
|
||||
while(in_region != in_regions + soc_memory_region_count) {
|
||||
soc_memory_region_t in = *in_region;
|
||||
ESP_EARLY_LOGV(TAG, "Examining memory region 0x%08x - 0x%08x", in.start, in.start + in.size);
|
||||
intptr_t in_start = in.start;
|
||||
intptr_t in_end = in_start + in.size;
|
||||
bool copy_in_to_out = true;
|
||||
bool move_to_next = true;
|
||||
|
||||
for (size_t i = 0; i < num_reserved; i++) {
|
||||
if (reserved[i].end <= in_start) {
|
||||
/* reserved region ends before 'in' starts */
|
||||
continue;
|
||||
}
|
||||
else if (reserved[i].start >= in_end) {
|
||||
/* reserved region starts after 'in' ends */
|
||||
break;
|
||||
}
|
||||
else if (reserved[i].start <= in_start &&
|
||||
reserved[i].end >= in_end) { /* reserved covers all of 'in' */
|
||||
ESP_EARLY_LOGV(TAG, "Region 0x%08x - 0x%08x inside of reserved 0x%08x - 0x%08x",
|
||||
in_start, in_end, reserved[i].start, reserved[i].end);
|
||||
/* skip 'in' entirely */
|
||||
copy_in_to_out = false;
|
||||
break;
|
||||
}
|
||||
else if (in_start < reserved[i].start &&
|
||||
in_end > reserved[i].end) { /* reserved contained inside 'in', need to "hole punch" */
|
||||
ESP_EARLY_LOGV(TAG, "Region 0x%08x - 0x%08x contains reserved 0x%08x - 0x%08x",
|
||||
in_start, in_end, reserved[i].start, reserved[i].end);
|
||||
assert(in_start < reserved[i].start);
|
||||
assert(in_end > reserved[i].end);
|
||||
|
||||
/* shrink this region to end where the reserved section starts */
|
||||
in_end = reserved[i].start;
|
||||
in.size = in_end - in_start;
|
||||
|
||||
/* update in_region so the 'next' iteration uses the region
|
||||
after the reserved section */
|
||||
in_region->size -= (reserved[i].end - in_region->start);
|
||||
in_region->start = reserved[i].end;
|
||||
|
||||
/* add first region, then re-run while loop with the updated in_region */
|
||||
move_to_next = false;
|
||||
break;
|
||||
}
|
||||
else if (reserved[i].start <= in_start) { /* reserved overlaps start of 'in' */
|
||||
ESP_EARLY_LOGV(TAG, "Start of region 0x%08x - 0x%08x overlaps reserved 0x%08x - 0x%08x",
|
||||
in_start, in_end, reserved[i].start, reserved[i].end);
|
||||
in.start = reserved[i].end;
|
||||
in_start = in.start;
|
||||
in.size = in_end - in_start;
|
||||
}
|
||||
else { /* reserved overlaps end of 'in' */
|
||||
ESP_EARLY_LOGV(TAG, "End of region 0x%08x - 0x%08x overlaps reserved 0x%08x - 0x%08x",
|
||||
in_start, in_end, reserved[i].start, reserved[i].end);
|
||||
in_end = reserved[i].start;
|
||||
in.size = in_end - in_start;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_in_to_out) {
|
||||
ESP_EARLY_LOGD(TAG, "Available memory region 0x%08x - 0x%08x", in.start, in.start + in.size);
|
||||
*out_region++ = in;
|
||||
}
|
||||
if (move_to_next) {
|
||||
in_region++;
|
||||
}
|
||||
}
|
||||
|
||||
return (out_region - regions); /* return number of regions */
|
||||
}
|
Reference in New Issue
Block a user