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