1 /*
2  * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdlib.h>
8 #include <stdint.h>
9 
10 #include "soc/soc.h"
11 #include "heap_memory_layout.h"
12 #include "esp_heap_caps.h"
13 #include "sdkconfig.h"
14 
15 #ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
16 #define MALLOC_IRAM_CAP MALLOC_CAP_EXEC|MALLOC_CAP_32BIT|MALLOC_CAP_IRAM_8BIT
17 #else
18 #define MALLOC_IRAM_CAP MALLOC_CAP_EXEC|MALLOC_CAP_32BIT
19 #endif
20 
21 /* Memory layout for ESP32 SoC */
22 
23 /*
24 Memory type descriptors. These describe the capabilities of a type of memory in the SoC. Each type of memory
25 map consist of one or more regions in the address space.
26 
27 Each type contains an array of prioritised capabilities; types with later entries are only taken if earlier
28 ones can't fulfill the memory request.
29 
30 The prioritised capabilities work roughly like this:
31 - For a normal malloc (MALLOC_CAP_DEFAULT), give away the DRAM-only memory first, then pass off any dual-use IRAM regions,
32   finally eat into the application memory.
33 - For a malloc where 32-bit-aligned-only access is okay, first allocate IRAM, then DRAM, finally application IRAM.
34 - Application mallocs (PIDx) will allocate IRAM first, if possible, then DRAM.
35 - Most other malloc caps only fit in one region anyway.
36 
37 */
38 const soc_memory_type_desc_t soc_memory_types[] = {
39     //Type 0: Plain ole D-port RAM
40     { "DRAM", { MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_DMA|MALLOC_CAP_32BIT, 0 }, false, false},
41     //Type 1: Plain ole D-port RAM which has an alias on the I-port
42     //(This DRAM is also the region used by ROM during startup)
43     { "D/IRAM", { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL|MALLOC_CAP_DEFAULT, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC }, true, true},
44     //Type 2: IRAM
45     { "IRAM", { MALLOC_CAP_INTERNAL|MALLOC_IRAM_CAP, 0, 0 }, false, false},
46     //Type 3-8: PID 2-7 IRAM
47     { "PID2IRAM", { MALLOC_CAP_PID2|MALLOC_CAP_INTERNAL, 0, MALLOC_IRAM_CAP }, false, false},
48     { "PID3IRAM", { MALLOC_CAP_PID3|MALLOC_CAP_INTERNAL, 0, MALLOC_IRAM_CAP }, false, false},
49     { "PID4IRAM", { MALLOC_CAP_PID4|MALLOC_CAP_INTERNAL, 0, MALLOC_IRAM_CAP }, false, false},
50     { "PID5IRAM", { MALLOC_CAP_PID5|MALLOC_CAP_INTERNAL, 0, MALLOC_IRAM_CAP }, false, false},
51     { "PID6IRAM", { MALLOC_CAP_PID6|MALLOC_CAP_INTERNAL, 0, MALLOC_IRAM_CAP }, false, false},
52     { "PID7IRAM", { MALLOC_CAP_PID7|MALLOC_CAP_INTERNAL, 0, MALLOC_IRAM_CAP }, false, false},
53     //Type 9-14: PID 2-7 DRAM
54     { "PID2DRAM", { MALLOC_CAP_PID2|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
55     { "PID3DRAM", { MALLOC_CAP_PID3|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
56     { "PID4DRAM", { MALLOC_CAP_PID4|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
57     { "PID5DRAM", { MALLOC_CAP_PID5|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
58     { "PID6DRAM", { MALLOC_CAP_PID6|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
59     { "PID7DRAM", { MALLOC_CAP_PID7|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
60     //Type 15: SPI SRAM data
61     { "SPIRAM", { MALLOC_CAP_SPIRAM|MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false, false},
62     //Type 16: RTC Fast RAM
63     { "RTCRAM", { MALLOC_CAP_RTCRAM, MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_32BIT }, false, false},
64 };
65 
66 const size_t soc_memory_type_count = sizeof(soc_memory_types)/sizeof(soc_memory_type_desc_t);
67 
68 /*
69 Region descriptors. These describe all regions of memory available, and map them to a type in the above type.
70 
71 Because of requirements in the coalescing code which merges adjacent regions, this list should always be sorted
72 from low to high start address.
73 */
74 const soc_memory_region_t soc_memory_regions[] = {
75 #ifdef CONFIG_SPIRAM
76     { SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_SIZE, 15, 0}, //SPI SRAM, if available
77 #endif
78     { 0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code
79     { 0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory
80     { 0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions.
81     { 0x3FFC0000, 0x2000, 0, 0}, //pool 10-13, mmu page 0
82     { 0x3FFC2000, 0x2000, 0, 0}, //pool 10-13, mmu page 1
83     { 0x3FFC4000, 0x2000, 0, 0}, //pool 10-13, mmu page 2
84     { 0x3FFC6000, 0x2000, 0, 0}, //pool 10-13, mmu page 3
85     { 0x3FFC8000, 0x2000, 0, 0}, //pool 10-13, mmu page 4
86     { 0x3FFCA000, 0x2000, 0, 0}, //pool 10-13, mmu page 5
87     { 0x3FFCC000, 0x2000, 0, 0}, //pool 10-13, mmu page 6
88     { 0x3FFCE000, 0x2000, 0, 0}, //pool 10-13, mmu page 7
89     { 0x3FFD0000, 0x2000, 0, 0}, //pool 10-13, mmu page 8
90     { 0x3FFD2000, 0x2000, 0, 0}, //pool 10-13, mmu page 9
91     { 0x3FFD4000, 0x2000, 0, 0}, //pool 10-13, mmu page 10
92     { 0x3FFD6000, 0x2000, 0, 0}, //pool 10-13, mmu page 11
93     { 0x3FFD8000, 0x2000, 0, 0}, //pool 10-13, mmu page 12
94     { 0x3FFDA000, 0x2000, 0, 0}, //pool 10-13, mmu page 13
95     { 0x3FFDC000, 0x2000, 0, 0}, //pool 10-13, mmu page 14
96     { 0x3FFDE000, 0x2000, 0, 0}, //pool 10-13, mmu page 15
97     { 0x3FFE0000, 0x4000, 1, 0x400BC000}, //pool 9 blk 1
98     { 0x3FFE4000, 0x4000, 1, 0x400B8000}, //pool 9 blk 0
99     { 0x3FFE8000, 0x8000, 1, 0x400B0000}, //pool 8 <- can be remapped to ROM, used for MAC dump
100     { 0x3FFF0000, 0x8000, 1, 0x400A8000}, //pool 7 <- can be used for MAC dump
101     { 0x3FFF8000, 0x4000, 1, 0x400A4000}, //pool 6 blk 1 <- can be used as trace memory
102     { 0x3FFFC000, 0x4000, 1, 0x400A0000}, //pool 6 blk 0 <- can be used as trace memory
103     { 0x40070000, 0x8000, 2, 0}, //pool 0
104     { 0x40078000, 0x8000, 2, 0}, //pool 1
105     { 0x40080000, 0x2000, 2, 0}, //pool 2-5, mmu page 0
106     { 0x40082000, 0x2000, 2, 0}, //pool 2-5, mmu page 1
107     { 0x40084000, 0x2000, 2, 0}, //pool 2-5, mmu page 2
108     { 0x40086000, 0x2000, 2, 0}, //pool 2-5, mmu page 3
109     { 0x40088000, 0x2000, 2, 0}, //pool 2-5, mmu page 4
110     { 0x4008A000, 0x2000, 2, 0}, //pool 2-5, mmu page 5
111     { 0x4008C000, 0x2000, 2, 0}, //pool 2-5, mmu page 6
112     { 0x4008E000, 0x2000, 2, 0}, //pool 2-5, mmu page 7
113     { 0x40090000, 0x2000, 2, 0}, //pool 2-5, mmu page 8
114     { 0x40092000, 0x2000, 2, 0}, //pool 2-5, mmu page 9
115     { 0x40094000, 0x2000, 2, 0}, //pool 2-5, mmu page 10
116     { 0x40096000, 0x2000, 2, 0}, //pool 2-5, mmu page 11
117     { 0x40098000, 0x2000, 2, 0}, //pool 2-5, mmu page 12
118     { 0x4009A000, 0x2000, 2, 0}, //pool 2-5, mmu page 13
119     { 0x4009C000, 0x2000, 2, 0}, //pool 2-5, mmu page 14
120     { 0x4009E000, 0x2000, 2, 0}, //pool 2-5, mmu page 15
121 #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
122     { SOC_RTC_DRAM_LOW, 0x2000, 16, 0}, //RTC Fast Memory
123 #endif
124 };
125 
126 const size_t soc_memory_region_count = sizeof(soc_memory_regions)/sizeof(soc_memory_region_t);
127 
128 
129 /* Reserved memory regions
130 
131    These are removed from the soc_memory_regions array when heaps are created.
132  */
133 SOC_RESERVE_MEMORY_REGION(SOC_CACHE_PRO_LOW, SOC_CACHE_PRO_HIGH, cpu0_cache);
134 #ifndef CONFIG_FREERTOS_UNICORE
135 SOC_RESERVE_MEMORY_REGION(SOC_CACHE_APP_LOW, SOC_CACHE_APP_HIGH, cpu1_cache);
136 #endif
137 
138     /* Warning: The ROM stack is located in the 0x3ffe0000 area. We do not specifically disable that area here because
139        after the scheduler has started, the ROM stack is not used anymore by anything. We handle it instead by not allowing
140        any mallocs memory regions with the startup_stack flag set (these are the IRAM/DRAM region) until the
141        scheduler has started.
142 
143        The 0x3ffe0000 region also contains static RAM for various ROM functions. The following lines
144        reserve the regions for UART and ETSC, so these functions are usable. Libraries like xtos, which are
145        not usable in FreeRTOS anyway, are commented out in the linker script so they cannot be used; we
146        do not disable their memory regions here and they will be used as general purpose heap memory.
147 
148        Enabling the heap allocator for this region but disabling allocation here until FreeRTOS is started up
149        is a somewhat risky action in theory, because on initializing the allocator, the multi_heap implementation
150        will go and write metadata at the start and end of all regions. For the ESP32, these linked
151        list entries happen to end up in a region that is not touched by the stack; they can be placed safely there.
152     */
153 
154 SOC_RESERVE_MEMORY_REGION(0x3ffe0000, 0x3ffe0440, rom_pro_data); //Reserve ROM PRO data region
155 #ifndef CONFIG_FREERTOS_UNICORE
156 SOC_RESERVE_MEMORY_REGION(0x3ffe3f20, 0x3ffe4350, rom_app_data); //Reserve ROM APP data region
157 #endif
158 
159 SOC_RESERVE_MEMORY_REGION(0x3ffae000, 0x3ffae6e0, rom_data);
160 
161 #if CONFIG_ESP32_MEMMAP_TRACEMEM
162 #if CONFIG_ESP32_MEMMAP_TRACEMEM_TWOBANKS
163 SOC_RESERVE_MEMORY_REGION(0x3fff8000, 0x40000000, trace_mem); //Reserve trace mem region, 32K for both cpu
164 #else
165 SOC_RESERVE_MEMORY_REGION(0x3fffc000, 0x40000000, trace_mem); //Reserve trace mem region, 16K (upper-half) for pro cpu
166 #endif
167 #endif
168 
169 #ifdef CONFIG_SPIRAM
170 /* Reserve the whole possible SPIRAM region here, spiram.c will add some or all of this
171  * memory to heap depending on the actual SPIRAM chip size. */
172 SOC_RESERVE_MEMORY_REGION(SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH, spi_ram);
173 #endif
174 
175 extern int _data_start, _heap_start, _heap_end, _iram_start, _iram_end, _rtc_force_fast_end, _rtc_noinit_end;
176 extern int _rtc_fast_reserved_start, _rtc_fast_reserved_end;
177 extern int _rtc_slow_reserved_start, _rtc_slow_reserved_end;
178 
179 // Static data region. DRAM used by data+bss and possibly rodata
180 SOC_RESERVE_MEMORY_REGION((intptr_t)&_data_start, (intptr_t)&_heap_start, dram_data);
181 
182 // IRAM code region
183 // ESP32 has an IRAM-only region 0x4008_0000 - 0x4009_FFFF, reserve the used part
184 SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start, (intptr_t)&_iram_end, iram_code);
185 
186 // If IRAM spans into SRAM1 due to CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM, reserve the corresponding part of DRAM
187 #ifdef CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM
188 SOC_RESERVE_MEMORY_REGION((intptr_t) &_heap_end, 0x40000000, sram1_iram);
189 #endif
190 
191 // RTC Fast RAM region
192 #ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
193 #ifdef CONFIG_ESP32_RTCDATA_IN_FAST_MEM
194 SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_noinit_end, rtcram_data);
195 #else
196 SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_fast_end, rtcram_data);
197 #endif
198 #endif
199 
200 SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_fast_reserved_start, (intptr_t)&_rtc_fast_reserved_end, rtc_fast_reserved_data);
201 SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_slow_reserved_start, (intptr_t)&_rtc_slow_reserved_end, rtc_reserved_data);
202