1 // Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #pragma once
16 #include <stdlib.h>
17 #include <stdint.h>
18 #include <stdbool.h>
19
20 #include "soc/soc.h"
21 #include "soc/soc_caps.h"
22 #include "sdkconfig.h"
23 #include "esp_attr.h"
24
25 #ifdef CONFIG_BT_ENABLED
26
27 #define SOC_MEM_BT_DATA_START 0x3ffae6e0
28 #define SOC_MEM_BT_DATA_END 0x3ffaff10
29 #define SOC_MEM_BT_EM_START 0x3ffb0000
30 #define SOC_MEM_BT_EM_END 0x3ffb7cd8
31 #define SOC_MEM_BT_EM_BTDM0_START 0x3ffb0000
32 #define SOC_MEM_BT_EM_BTDM0_END 0x3ffb09a8
33 #define SOC_MEM_BT_EM_BLE_START 0x3ffb09a8
34 #define SOC_MEM_BT_EM_BLE_END 0x3ffb1ddc
35 #define SOC_MEM_BT_EM_BTDM1_START 0x3ffb1ddc
36 #define SOC_MEM_BT_EM_BTDM1_END 0x3ffb2730
37 #define SOC_MEM_BT_EM_BREDR_START 0x3ffb2730
38 #define SOC_MEM_BT_EM_BREDR_NO_SYNC_END 0x3ffb6388 //Not calculate with synchronize connection support
39 #define SOC_MEM_BT_EM_BREDR_END 0x3ffb7cd8 //Calculate with synchronize connection support
40 #define SOC_MEM_BT_EM_SYNC0_START 0x3ffb6388
41 #define SOC_MEM_BT_EM_SYNC0_END 0x3ffb6bf8
42 #define SOC_MEM_BT_EM_SYNC1_START 0x3ffb6bf8
43 #define SOC_MEM_BT_EM_SYNC1_END 0x3ffb7468
44 #define SOC_MEM_BT_EM_SYNC2_START 0x3ffb7468
45 #define SOC_MEM_BT_EM_SYNC2_END 0x3ffb7cd8
46 #define SOC_MEM_BT_BSS_START 0x3ffb8000
47 #define SOC_MEM_BT_BSS_END 0x3ffb9a20
48 #define SOC_MEM_BT_MISC_START 0x3ffbdb28
49 #define SOC_MEM_BT_MISC_END 0x3ffbdb5c
50
51 #define SOC_MEM_BT_EM_PER_SYNC_SIZE 0x870
52
53 #define SOC_MEM_BT_EM_BREDR_REAL_END (SOC_MEM_BT_EM_BREDR_NO_SYNC_END + CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF * SOC_MEM_BT_EM_PER_SYNC_SIZE)
54
55 #endif //CONFIG_BT_ENABLED
56
57 #define SOC_MEMORY_TYPE_NO_PRIOS 3
58
59 /* Type descriptor holds a description for a particular type of memory on a particular SoC.
60 */
61 typedef struct {
62 const char *name; ///< Name of this memory type
63 uint32_t caps[SOC_MEMORY_TYPE_NO_PRIOS]; ///< Capabilities for this memory type (as a prioritised set)
64 bool aliased_iram; ///< If true, this is data memory that is is also mapped in IRAM
65 bool startup_stack; ///< If true, memory of this type is used for ROM stack during startup
66 } soc_memory_type_desc_t;
67
68 /* Constant table of tag descriptors for all this SoC's tags */
69 extern const soc_memory_type_desc_t soc_memory_types[];
70 extern const size_t soc_memory_type_count;
71
72 /* Region descriptor holds a description for a particular region of memory on a particular SoC.
73 */
74 typedef struct
75 {
76 intptr_t start; ///< Start address of the region
77 size_t size; ///< Size of the region in bytes
78 size_t type; ///< Type of the region (index into soc_memory_types array)
79 intptr_t iram_address; ///< If non-zero, is equivalent address in IRAM
80 } soc_memory_region_t;
81
82 extern const soc_memory_region_t soc_memory_regions[];
83 extern const size_t soc_memory_region_count;
84
85 /* Region descriptor holds a description for a particular region of
86 memory reserved on this SoC for a particular use (ie not available
87 for stack/heap usage.) */
88 typedef struct
89 {
90 intptr_t start;
91 intptr_t end;
92 } soc_reserved_region_t;
93
94 /* Use this macro to reserved a fixed region of RAM (hardcoded addresses)
95 * for a particular purpose.
96 *
97 * Usually used to mark out memory addresses needed for hardware or ROM code
98 * purposes.
99 *
100 * Don't call this macro from user code which can use normal C static allocation
101 * instead.
102 *
103 * @param START Start address to be reserved.
104 * @param END One after the address of the last byte to be reserved. (ie length of
105 * the reserved region is (END - START) in bytes.
106 * @param NAME Name for the reserved region. Must be a valid variable name,
107 * unique to this source file.
108 */
109 #define SOC_RESERVE_MEMORY_REGION(START, END, NAME) \
110 __attribute__((section(".reserved_memory_address"))) __attribute__((used)) \
111 static soc_reserved_region_t reserved_region_##NAME = { START, END };
112
113 /* Return available memory regions for this SoC. Each available memory
114 * region is a contiguous piece of memory which is not being used by
115 * static data, used by ROM code, or reserved by a component using
116 * the SOC_RESERVE_MEMORY_REGION() macro.
117 *
118 * This result is soc_memory_regions[] minus all regions reserved
119 * via the SOC_RESERVE_MEMORY_REGION() macro (which may also split
120 * some regions up.)
121 *
122 * At startup, all available memory returned by this function is
123 * registered as heap space.
124 *
125 * @note OS-level startup function only, not recommended to call from
126 * app code.
127 *
128 * @param regions Pointer to an array for reading available regions into.
129 * Size of the array should be at least the result of
130 * soc_get_available_memory_region_max_count(). Entries in the array
131 * will be ordered by memory address.
132 *
133 * @return Number of entries copied to 'regions'. Will be no greater than
134 * the result of soc_get_available_memory_region_max_count().
135 */
136 size_t soc_get_available_memory_regions(soc_memory_region_t *regions);
137
138 /* Return the maximum number of available memory regions which could be
139 * returned by soc_get_available_memory_regions(). Used to size the
140 * array passed to that function.
141 */
142 size_t soc_get_available_memory_region_max_count(void);
143
esp_ptr_dma_capable(const void * p)144 inline static bool IRAM_ATTR esp_ptr_dma_capable(const void *p)
145 {
146 return (intptr_t)p >= SOC_DMA_LOW && (intptr_t)p < SOC_DMA_HIGH;
147 }
148
esp_ptr_dma_ext_capable(const void * p)149 inline static bool IRAM_ATTR esp_ptr_dma_ext_capable(const void *p)
150 {
151 #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
152 return (intptr_t)p >= SOC_DMA_EXT_LOW && (intptr_t)p < SOC_DMA_EXT_HIGH;
153 #else
154 return false;
155 #endif
156 }
157
esp_ptr_word_aligned(const void * p)158 inline static bool IRAM_ATTR esp_ptr_word_aligned(const void *p)
159 {
160 return ((intptr_t)p) % 4 == 0;
161 }
162
esp_ptr_executable(const void * p)163 inline static bool IRAM_ATTR esp_ptr_executable(const void *p)
164 {
165 intptr_t ip = (intptr_t) p;
166 return (ip >= SOC_IROM_LOW && ip < SOC_IROM_HIGH)
167 || (ip >= SOC_IRAM_LOW && ip < SOC_IRAM_HIGH)
168 || (ip >= SOC_IROM_MASK_LOW && ip < SOC_IROM_MASK_HIGH)
169 #if defined(SOC_CACHE_APP_LOW) && defined(CONFIG_FREERTOS_UNICORE)
170 || (ip >= SOC_CACHE_APP_LOW && ip < SOC_CACHE_APP_HIGH)
171 #endif
172 || (ip >= SOC_RTC_IRAM_LOW && ip < SOC_RTC_IRAM_HIGH);
173 }
174
esp_ptr_byte_accessible(const void * p)175 inline static bool IRAM_ATTR esp_ptr_byte_accessible(const void *p)
176 {
177 intptr_t ip = (intptr_t) p;
178 bool r;
179 r = (ip >= SOC_BYTE_ACCESSIBLE_LOW && ip < SOC_BYTE_ACCESSIBLE_HIGH);
180 #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
181 /* For ESP32 case, RTC fast memory is accessible to PRO cpu only and hence
182 * for single core configuration (where it gets added to system heap) following
183 * additional check is required */
184 r |= (ip >= SOC_RTC_DRAM_LOW && ip < SOC_RTC_DRAM_HIGH);
185 #endif
186 #if CONFIG_SPIRAM
187 #if CONFIG_SPIRAM_SIZE != -1 // Fixed size, can be more accurate
188 r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE));
189 #else
190 r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_HIGH));
191 #endif
192 #endif
193 return r;
194 }
195
esp_ptr_internal(const void * p)196 inline static bool IRAM_ATTR esp_ptr_internal(const void *p) {
197 bool r;
198 r = ((intptr_t)p >= SOC_MEM_INTERNAL_LOW && (intptr_t)p < SOC_MEM_INTERNAL_HIGH);
199 r |= ((intptr_t)p >= SOC_RTC_DATA_LOW && (intptr_t)p < SOC_RTC_DATA_HIGH);
200 #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
201 /* For ESP32 case, RTC fast memory is accessible to PRO cpu only and hence
202 * for single core configuration (where it gets added to system heap) following
203 * additional check is required */
204 r |= ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
205 #endif
206 return r;
207 }
208
209
esp_ptr_external_ram(const void * p)210 inline static bool IRAM_ATTR esp_ptr_external_ram(const void *p) {
211 #if SOC_SPIRAM_SUPPORTED
212 return ((intptr_t)p >= SOC_EXTRAM_DATA_LOW && (intptr_t)p < SOC_EXTRAM_DATA_HIGH);
213 #else
214 return false; // SoC has no external RAM
215 #endif
216 }
217
esp_ptr_in_iram(const void * p)218 inline static bool IRAM_ATTR esp_ptr_in_iram(const void *p) {
219 #if CONFIG_IDF_TARGET_ESP32 && CONFIG_FREERTOS_UNICORE
220 return ((intptr_t)p >= SOC_CACHE_APP_LOW && (intptr_t)p < SOC_IRAM_HIGH);
221 #else
222 return ((intptr_t)p >= SOC_IRAM_LOW && (intptr_t)p < SOC_IRAM_HIGH);
223 #endif
224 }
225
esp_ptr_in_drom(const void * p)226 inline static bool IRAM_ATTR esp_ptr_in_drom(const void *p) {
227 return ((intptr_t)p >= SOC_DROM_LOW && (intptr_t)p < SOC_DROM_HIGH);
228 }
229
esp_ptr_in_dram(const void * p)230 inline static bool IRAM_ATTR esp_ptr_in_dram(const void *p) {
231 return ((intptr_t)p >= SOC_DRAM_LOW && (intptr_t)p < SOC_DRAM_HIGH);
232 }
233
esp_ptr_in_diram_dram(const void * p)234 inline static bool IRAM_ATTR esp_ptr_in_diram_dram(const void *p) {
235 return ((intptr_t)p >= SOC_DIRAM_DRAM_LOW && (intptr_t)p < SOC_DIRAM_DRAM_HIGH);
236 }
237
esp_ptr_in_diram_iram(const void * p)238 inline static bool IRAM_ATTR esp_ptr_in_diram_iram(const void *p) {
239 return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH);
240 }
241
esp_ptr_in_rtc_iram_fast(const void * p)242 inline static bool IRAM_ATTR esp_ptr_in_rtc_iram_fast(const void *p) {
243 return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH);
244 }
245
esp_ptr_in_rtc_dram_fast(const void * p)246 inline static bool IRAM_ATTR esp_ptr_in_rtc_dram_fast(const void *p) {
247 return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
248 }
249
esp_ptr_in_rtc_slow(const void * p)250 inline static bool IRAM_ATTR esp_ptr_in_rtc_slow(const void *p) {
251 return ((intptr_t)p >= SOC_RTC_DATA_LOW && (intptr_t)p < SOC_RTC_DATA_HIGH);
252 }
253
254 /* Convert a D/IRAM DRAM pointer to equivalent word address in IRAM
255
256 - Address must be word aligned
257 - Address must pass esp_ptr_in_diram_dram() test, or result will be invalid pointer
258 */
esp_ptr_diram_dram_to_iram(const void * p)259 inline static void * IRAM_ATTR esp_ptr_diram_dram_to_iram(const void *p) {
260 #if SOC_DIRAM_INVERTED
261 return (void *) ( SOC_DIRAM_IRAM_LOW + (SOC_DIRAM_DRAM_HIGH - (intptr_t)p) - 4);
262 #else
263 return (void *) ( SOC_DIRAM_IRAM_LOW + ((intptr_t)p - SOC_DIRAM_DRAM_LOW) );
264 #endif
265 }
266
267 /* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM
268
269 - Address must be word aligned
270 - Address must pass esp_ptr_in_diram_iram() test, or result will be invalid pointer
271 */
esp_ptr_diram_iram_to_dram(const void * p)272 inline static void * IRAM_ATTR esp_ptr_diram_iram_to_dram(const void *p) {
273 #if SOC_DIRAM_INVERTED
274 return (void *) ( SOC_DIRAM_DRAM_LOW + (SOC_DIRAM_IRAM_HIGH - (intptr_t)p) - 4);
275 #else
276 return (void *) ( SOC_DIRAM_DRAM_LOW + ((intptr_t)p - SOC_DIRAM_IRAM_LOW) );
277 #endif
278 }
279
esp_stack_ptr_in_dram(uint32_t sp)280 inline static bool IRAM_ATTR esp_stack_ptr_in_dram(uint32_t sp)
281 {
282 //Check if stack ptr is in between SOC_DRAM_LOW and SOC_DRAM_HIGH, and 16 byte aligned.
283 return !(sp < SOC_DRAM_LOW + 0x10 || sp > SOC_DRAM_HIGH - 0x10 || ((sp & 0xF) != 0));
284 }
285
286 #if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
esp_stack_ptr_in_extram(uint32_t sp)287 inline static bool IRAM_ATTR esp_stack_ptr_in_extram(uint32_t sp)
288 {
289 //Check if stack ptr is in between SOC_EXTRAM_DATA_LOW and SOC_EXTRAM_DATA_HIGH, and 16 byte aligned.
290 return !(sp < SOC_EXTRAM_DATA_LOW + 0x10 || sp > SOC_EXTRAM_DATA_HIGH - 0x10 || ((sp & 0xF) != 0));
291 }
292 #endif
293
esp_stack_ptr_is_sane(uint32_t sp)294 inline static bool IRAM_ATTR esp_stack_ptr_is_sane(uint32_t sp)
295 {
296 #if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
297 return (esp_stack_ptr_in_dram(sp) || esp_stack_ptr_in_extram(sp));
298 #else
299 return esp_stack_ptr_in_dram(sp);
300 #endif
301 }
302