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 __cplusplus
26 extern "C" {
27 #endif
28
esp_ptr_dma_capable(const void * p)29 inline static bool IRAM_ATTR esp_ptr_dma_capable(const void *p)
30 {
31 return (intptr_t)p >= SOC_DMA_LOW && (intptr_t)p < SOC_DMA_HIGH;
32 }
33
esp_ptr_dma_ext_capable(const void * p)34 inline static bool IRAM_ATTR esp_ptr_dma_ext_capable(const void *p)
35 {
36 #ifdef SOC_PSRAM_DMA_CAPABLE
37 return (intptr_t)p >= SOC_DMA_EXT_LOW && (intptr_t)p < SOC_DMA_EXT_HIGH;
38 #else
39 return false;
40 #endif
41 }
42
esp_ptr_word_aligned(const void * p)43 inline static bool IRAM_ATTR esp_ptr_word_aligned(const void *p)
44 {
45 return ((intptr_t)p) % 4 == 0;
46 }
47
esp_ptr_executable(const void * p)48 inline static bool IRAM_ATTR esp_ptr_executable(const void *p)
49 {
50 intptr_t ip = (intptr_t) p;
51 return (ip >= SOC_IROM_LOW && ip < SOC_IROM_HIGH)
52 || (ip >= SOC_IRAM_LOW && ip < SOC_IRAM_HIGH)
53 || (ip >= SOC_IROM_MASK_LOW && ip < SOC_IROM_MASK_HIGH)
54 #if defined(SOC_CACHE_APP_LOW) && defined(CONFIG_FREERTOS_UNICORE)
55 || (ip >= SOC_CACHE_APP_LOW && ip < SOC_CACHE_APP_HIGH)
56 #endif
57 || (ip >= SOC_RTC_IRAM_LOW && ip < SOC_RTC_IRAM_HIGH);
58 }
59
esp_ptr_byte_accessible(const void * p)60 inline static bool IRAM_ATTR esp_ptr_byte_accessible(const void *p)
61 {
62 intptr_t ip = (intptr_t) p;
63 bool r;
64 r = (ip >= SOC_BYTE_ACCESSIBLE_LOW && ip < SOC_BYTE_ACCESSIBLE_HIGH);
65 #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
66 /* For ESP32 case, RTC fast memory is accessible to PRO cpu only and hence
67 * for single core configuration (where it gets added to system heap) following
68 * additional check is required */
69 r |= (ip >= SOC_RTC_DRAM_LOW && ip < SOC_RTC_DRAM_HIGH);
70 #endif
71 #if CONFIG_SPIRAM
72 #if CONFIG_SPIRAM_SIZE != -1 // Fixed size, can be more accurate
73 r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE));
74 #else
75 r |= (ip >= SOC_EXTRAM_DATA_LOW && ip < (SOC_EXTRAM_DATA_HIGH));
76 #endif
77 #endif
78 return r;
79 }
80
esp_ptr_internal(const void * p)81 inline static bool IRAM_ATTR esp_ptr_internal(const void *p) {
82 bool r;
83 r = ((intptr_t)p >= SOC_MEM_INTERNAL_LOW && (intptr_t)p < SOC_MEM_INTERNAL_HIGH);
84 r |= ((intptr_t)p >= SOC_RTC_DATA_LOW && (intptr_t)p < SOC_RTC_DATA_HIGH);
85 #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
86 /* For ESP32 case, RTC fast memory is accessible to PRO cpu only and hence
87 * for single core configuration (where it gets added to system heap) following
88 * additional check is required */
89 r |= ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
90 #endif
91 return r;
92 }
93
94
esp_ptr_external_ram(const void * p)95 inline static bool IRAM_ATTR esp_ptr_external_ram(const void *p) {
96 #if SOC_SPIRAM_SUPPORTED
97 return ((intptr_t)p >= SOC_EXTRAM_DATA_LOW && (intptr_t)p < SOC_EXTRAM_DATA_HIGH);
98 #else
99 return false; // SoC has no external RAM
100 #endif
101 }
102
esp_ptr_in_iram(const void * p)103 inline static bool IRAM_ATTR esp_ptr_in_iram(const void *p) {
104 #if CONFIG_IDF_TARGET_ESP32 && CONFIG_FREERTOS_UNICORE
105 return ((intptr_t)p >= SOC_CACHE_APP_LOW && (intptr_t)p < SOC_IRAM_HIGH);
106 #else
107 return ((intptr_t)p >= SOC_IRAM_LOW && (intptr_t)p < SOC_IRAM_HIGH);
108 #endif
109 }
110
esp_ptr_in_drom(const void * p)111 inline static bool IRAM_ATTR esp_ptr_in_drom(const void *p) {
112 return ((intptr_t)p >= SOC_DROM_LOW && (intptr_t)p < SOC_DROM_HIGH);
113 }
114
esp_ptr_in_dram(const void * p)115 inline static bool IRAM_ATTR esp_ptr_in_dram(const void *p) {
116 return ((intptr_t)p >= SOC_DRAM_LOW && (intptr_t)p < SOC_DRAM_HIGH);
117 }
118
esp_ptr_in_diram_dram(const void * p)119 inline static bool IRAM_ATTR esp_ptr_in_diram_dram(const void *p) {
120 return ((intptr_t)p >= SOC_DIRAM_DRAM_LOW && (intptr_t)p < SOC_DIRAM_DRAM_HIGH);
121 }
122
esp_ptr_in_diram_iram(const void * p)123 inline static bool IRAM_ATTR esp_ptr_in_diram_iram(const void *p) {
124 return ((intptr_t)p >= SOC_DIRAM_IRAM_LOW && (intptr_t)p < SOC_DIRAM_IRAM_HIGH);
125 }
126
esp_ptr_in_rtc_iram_fast(const void * p)127 inline static bool IRAM_ATTR esp_ptr_in_rtc_iram_fast(const void *p) {
128 return ((intptr_t)p >= SOC_RTC_IRAM_LOW && (intptr_t)p < SOC_RTC_IRAM_HIGH);
129 }
130
esp_ptr_in_rtc_dram_fast(const void * p)131 inline static bool IRAM_ATTR esp_ptr_in_rtc_dram_fast(const void *p) {
132 return ((intptr_t)p >= SOC_RTC_DRAM_LOW && (intptr_t)p < SOC_RTC_DRAM_HIGH);
133 }
134
esp_ptr_in_rtc_slow(const void * p)135 inline static bool IRAM_ATTR esp_ptr_in_rtc_slow(const void *p) {
136 return ((intptr_t)p >= SOC_RTC_DATA_LOW && (intptr_t)p < SOC_RTC_DATA_HIGH);
137 }
138
139 /* Convert a D/IRAM DRAM pointer to equivalent word address in IRAM
140
141 - Address must be word aligned
142 - Address must pass esp_ptr_in_diram_dram() test, or result will be invalid pointer
143 */
esp_ptr_diram_dram_to_iram(const void * p)144 inline static void * IRAM_ATTR esp_ptr_diram_dram_to_iram(const void *p) {
145 #if SOC_DIRAM_INVERTED
146 return (void *) ( SOC_DIRAM_IRAM_LOW + (SOC_DIRAM_DRAM_HIGH - (intptr_t)p) - 4);
147 #else
148 return (void *) ( SOC_DIRAM_IRAM_LOW + ((intptr_t)p - SOC_DIRAM_DRAM_LOW) );
149 #endif
150 }
151
152 /* Convert a D/IRAM IRAM pointer to equivalent word address in DRAM
153
154 - Address must be word aligned
155 - Address must pass esp_ptr_in_diram_iram() test, or result will be invalid pointer
156 */
esp_ptr_diram_iram_to_dram(const void * p)157 inline static void * IRAM_ATTR esp_ptr_diram_iram_to_dram(const void *p) {
158 #if SOC_DIRAM_INVERTED
159 return (void *) ( SOC_DIRAM_DRAM_LOW + (SOC_DIRAM_IRAM_HIGH - (intptr_t)p) - 4);
160 #else
161 return (void *) ( SOC_DIRAM_DRAM_LOW + ((intptr_t)p - SOC_DIRAM_IRAM_LOW) );
162 #endif
163 }
164
esp_stack_ptr_in_dram(uint32_t sp)165 inline static bool IRAM_ATTR esp_stack_ptr_in_dram(uint32_t sp)
166 {
167 //Check if stack ptr is in between SOC_DRAM_LOW and SOC_DRAM_HIGH, and 16 byte aligned.
168 return !(sp < SOC_DRAM_LOW + 0x10 || sp > SOC_DRAM_HIGH - 0x10 || ((sp & 0xF) != 0));
169 }
170
171 #if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
esp_stack_ptr_in_extram(uint32_t sp)172 inline static bool IRAM_ATTR esp_stack_ptr_in_extram(uint32_t sp)
173 {
174 //Check if stack ptr is in between SOC_EXTRAM_DATA_LOW and SOC_EXTRAM_DATA_HIGH, and 16 byte aligned.
175 return !(sp < SOC_EXTRAM_DATA_LOW + 0x10 || sp > SOC_EXTRAM_DATA_HIGH - 0x10 || ((sp & 0xF) != 0));
176 }
177 #endif
178
esp_stack_ptr_is_sane(uint32_t sp)179 inline static bool IRAM_ATTR esp_stack_ptr_is_sane(uint32_t sp)
180 {
181 return esp_stack_ptr_in_dram(sp)
182 #if CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
183 || esp_stack_ptr_in_extram(sp)
184 #endif
185 #if CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
186 || esp_ptr_in_rtc_dram_fast((void*) sp)
187 #endif
188 ;
189 }
190
191 #ifdef __cplusplus
192 }
193 #endif
194