Branch data Line data Source code
1 : : /******************************************************************************
2 : : * @file mpu_armv8.h
3 : : * @brief CMSIS MPU API for Armv8-M and Armv8.1-M MPU
4 : : * @version V5.1.3
5 : : * @date 03. February 2021
6 : : ******************************************************************************/
7 : : /*
8 : : * Copyright (c) 2017-2021 Arm Limited. All rights reserved.
9 : : *
10 : : * SPDX-License-Identifier: Apache-2.0
11 : : *
12 : : * Licensed under the Apache License, Version 2.0 (the License); you may
13 : : * not use this file except in compliance with the License.
14 : : * You may obtain a copy of the License at
15 : : *
16 : : * www.apache.org/licenses/LICENSE-2.0
17 : : *
18 : : * Unless required by applicable law or agreed to in writing, software
19 : : * distributed under the License is distributed on an AS IS BASIS, WITHOUT
20 : : * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 : : * See the License for the specific language governing permissions and
22 : : * limitations under the License.
23 : : */
24 : :
25 : : #if defined ( __ICCARM__ )
26 : : #pragma system_include /* treat file as system include file for MISRA check */
27 : : #elif defined (__clang__)
28 : : #pragma clang system_header /* treat file as system include file */
29 : : #endif
30 : :
31 : : #ifndef ARM_MPU_ARMV8_H
32 : : #define ARM_MPU_ARMV8_H
33 : :
34 : : /** \brief Attribute for device memory (outer only) */
35 : : #define ARM_MPU_ATTR_DEVICE ( 0U )
36 : :
37 : : /** \brief Attribute for non-cacheable, normal memory */
38 : : #define ARM_MPU_ATTR_NON_CACHEABLE ( 4U )
39 : :
40 : : /** \brief Attribute for normal memory (outer and inner)
41 : : * \param NT Non-Transient: Set to 1 for non-transient data.
42 : : * \param WB Write-Back: Set to 1 to use write-back update policy.
43 : : * \param RA Read Allocation: Set to 1 to use cache allocation on read miss.
44 : : * \param WA Write Allocation: Set to 1 to use cache allocation on write miss.
45 : : */
46 : : #define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA) \
47 : : ((((NT) & 1U) << 3U) | (((WB) & 1U) << 2U) | (((RA) & 1U) << 1U) | ((WA) & 1U))
48 : :
49 : : /** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */
50 : : #define ARM_MPU_ATTR_DEVICE_nGnRnE (0U)
51 : :
52 : : /** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */
53 : : #define ARM_MPU_ATTR_DEVICE_nGnRE (1U)
54 : :
55 : : /** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */
56 : : #define ARM_MPU_ATTR_DEVICE_nGRE (2U)
57 : :
58 : : /** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */
59 : : #define ARM_MPU_ATTR_DEVICE_GRE (3U)
60 : :
61 : : /** \brief Memory Attribute
62 : : * \param O Outer memory attributes
63 : : * \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes
64 : : */
65 : : #define ARM_MPU_ATTR(O, I) ((((O) & 0xFU) << 4U) | ((((O) & 0xFU) != 0U) ? ((I) & 0xFU) : (((I) & 0x3U) << 2U)))
66 : :
67 : : /** \brief Normal memory non-shareable */
68 : : #define ARM_MPU_SH_NON (0U)
69 : :
70 : : /** \brief Normal memory outer shareable */
71 : : #define ARM_MPU_SH_OUTER (2U)
72 : :
73 : : /** \brief Normal memory inner shareable */
74 : : #define ARM_MPU_SH_INNER (3U)
75 : :
76 : : /** \brief Memory access permissions
77 : : * \param RO Read-Only: Set to 1 for read-only memory.
78 : : * \param NP Non-Privileged: Set to 1 for non-privileged memory.
79 : : */
80 : : #define ARM_MPU_AP_(RO, NP) ((((RO) & 1U) << 1U) | ((NP) & 1U))
81 : :
82 : : /** \brief Region Base Address Register value
83 : : * \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned.
84 : : * \param SH Defines the Shareability domain for this memory region.
85 : : * \param RO Read-Only: Set to 1 for a read-only memory region.
86 : : * \param NP Non-Privileged: Set to 1 for a non-privileged memory region.
87 : : * \oaram XN eXecute Never: Set to 1 for a non-executable memory region.
88 : : */
89 : : #define ARM_MPU_RBAR(BASE, SH, RO, NP, XN) \
90 : : (((BASE) & MPU_RBAR_BASE_Msk) | \
91 : : (((SH) << MPU_RBAR_SH_Pos) & MPU_RBAR_SH_Msk) | \
92 : : ((ARM_MPU_AP_(RO, NP) << MPU_RBAR_AP_Pos) & MPU_RBAR_AP_Msk) | \
93 : : (((XN) << MPU_RBAR_XN_Pos) & MPU_RBAR_XN_Msk))
94 : :
95 : : /** \brief Region Limit Address Register value
96 : : * \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
97 : : * \param IDX The attribute index to be associated with this memory region.
98 : : */
99 : : #define ARM_MPU_RLAR(LIMIT, IDX) \
100 : : (((LIMIT) & MPU_RLAR_LIMIT_Msk) | \
101 : : (((IDX) << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \
102 : : (MPU_RLAR_EN_Msk))
103 : :
104 : : #if defined(MPU_RLAR_PXN_Pos)
105 : :
106 : : /** \brief Region Limit Address Register with PXN value
107 : : * \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
108 : : * \param PXN Privileged execute never. Defines whether code can be executed from this privileged region.
109 : : * \param IDX The attribute index to be associated with this memory region.
110 : : */
111 : : #define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX) \
112 : : (((LIMIT) & MPU_RLAR_LIMIT_Msk) | \
113 : : (((PXN) << MPU_RLAR_PXN_Pos) & MPU_RLAR_PXN_Msk) | \
114 : : (((IDX) << MPU_RLAR_AttrIndx_Pos) & MPU_RLAR_AttrIndx_Msk) | \
115 : : (MPU_RLAR_EN_Msk))
116 : :
117 : : #endif
118 : :
119 : : /**
120 : : * Struct for a single MPU Region
121 : : */
122 : : typedef struct {
123 : : uint32_t RBAR; /*!< Region Base Address Register value */
124 : : uint32_t RLAR; /*!< Region Limit Address Register value */
125 : : } ARM_MPU_Region_t;
126 : :
127 : : /** Enable the MPU.
128 : : * \param MPU_Control Default access permissions for unconfigured regions.
129 : : */
130 : : __STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
131 : : {
132 : : __DMB();
133 : : MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
134 : : #ifdef SCB_SHCSR_MEMFAULTENA_Msk
135 : : SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
136 : : #endif
137 : : __DSB();
138 : : __ISB();
139 : : }
140 : :
141 : : /** Disable the MPU.
142 : : */
143 : : __STATIC_INLINE void ARM_MPU_Disable(void)
144 : : {
145 : : __DMB();
146 : : #ifdef SCB_SHCSR_MEMFAULTENA_Msk
147 : : SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
148 : : #endif
149 : : MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
150 : : __DSB();
151 : : __ISB();
152 : : }
153 : :
154 : : #ifdef MPU_NS
155 : : /** Enable the Non-secure MPU.
156 : : * \param MPU_Control Default access permissions for unconfigured regions.
157 : : */
158 : : __STATIC_INLINE void ARM_MPU_Enable_NS(uint32_t MPU_Control)
159 : : {
160 : : __DMB();
161 : : MPU_NS->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
162 : : #ifdef SCB_SHCSR_MEMFAULTENA_Msk
163 : : SCB_NS->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
164 : : #endif
165 : : __DSB();
166 : : __ISB();
167 : : }
168 : :
169 : : /** Disable the Non-secure MPU.
170 : : */
171 : : __STATIC_INLINE void ARM_MPU_Disable_NS(void)
172 : : {
173 : : __DMB();
174 : : #ifdef SCB_SHCSR_MEMFAULTENA_Msk
175 : : SCB_NS->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
176 : : #endif
177 : : MPU_NS->CTRL &= ~MPU_CTRL_ENABLE_Msk;
178 : : __DSB();
179 : : __ISB();
180 : : }
181 : : #endif
182 : :
183 : : /** Set the memory attribute encoding to the given MPU.
184 : : * \param mpu Pointer to the MPU to be configured.
185 : : * \param idx The attribute index to be set [0-7]
186 : : * \param attr The attribute value to be set.
187 : : */
188 : : __STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr)
189 : : {
190 : : const uint8_t reg = idx / 4U;
191 : : const uint32_t pos = ((idx % 4U) * 8U);
192 : : const uint32_t mask = 0xFFU << pos;
193 : :
194 : : if (reg >= (sizeof(mpu->MAIR) / sizeof(mpu->MAIR[0]))) {
195 : : return; // invalid index
196 : : }
197 : :
198 : : mpu->MAIR[reg] = ((mpu->MAIR[reg] & ~mask) | ((attr << pos) & mask));
199 : : }
200 : :
201 : : /** Set the memory attribute encoding.
202 : : * \param idx The attribute index to be set [0-7]
203 : : * \param attr The attribute value to be set.
204 : : */
205 : : __STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr)
206 : : {
207 : : ARM_MPU_SetMemAttrEx(MPU, idx, attr);
208 : : }
209 : :
210 : : #ifdef MPU_NS
211 : : /** Set the memory attribute encoding to the Non-secure MPU.
212 : : * \param idx The attribute index to be set [0-7]
213 : : * \param attr The attribute value to be set.
214 : : */
215 : : __STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr)
216 : : {
217 : : ARM_MPU_SetMemAttrEx(MPU_NS, idx, attr);
218 : : }
219 : : #endif
220 : :
221 : : /** Clear and disable the given MPU region of the given MPU.
222 : : * \param mpu Pointer to MPU to be used.
223 : : * \param rnr Region number to be cleared.
224 : : */
225 : 0 : __STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr)
226 : : {
227 : 0 : mpu->RNR = rnr;
228 : 0 : mpu->RLAR = 0U;
229 : 0 : }
230 : :
231 : : /** Clear and disable the given MPU region.
232 : : * \param rnr Region number to be cleared.
233 : : */
234 : 0 : __STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
235 : : {
236 : 0 : ARM_MPU_ClrRegionEx(MPU, rnr);
237 : 0 : }
238 : :
239 : : #ifdef MPU_NS
240 : : /** Clear and disable the given Non-secure MPU region.
241 : : * \param rnr Region number to be cleared.
242 : : */
243 : : __STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr)
244 : : {
245 : : ARM_MPU_ClrRegionEx(MPU_NS, rnr);
246 : : }
247 : : #endif
248 : :
249 : : /** Configure the given MPU region of the given MPU.
250 : : * \param mpu Pointer to MPU to be used.
251 : : * \param rnr Region number to be configured.
252 : : * \param rbar Value for RBAR register.
253 : : * \param rlar Value for RLAR register.
254 : : */
255 : 2 : __STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar)
256 : : {
257 : 2 : mpu->RNR = rnr;
258 : 2 : mpu->RBAR = rbar;
259 : 2 : mpu->RLAR = rlar;
260 : 2 : }
261 : :
262 : : /** Configure the given MPU region.
263 : : * \param rnr Region number to be configured.
264 : : * \param rbar Value for RBAR register.
265 : : * \param rlar Value for RLAR register.
266 : : */
267 : 2 : __STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar)
268 : : {
269 : 2 : ARM_MPU_SetRegionEx(MPU, rnr, rbar, rlar);
270 : 2 : }
271 : :
272 : : #ifdef MPU_NS
273 : : /** Configure the given Non-secure MPU region.
274 : : * \param rnr Region number to be configured.
275 : : * \param rbar Value for RBAR register.
276 : : * \param rlar Value for RLAR register.
277 : : */
278 : : __STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar)
279 : : {
280 : : ARM_MPU_SetRegionEx(MPU_NS, rnr, rbar, rlar);
281 : : }
282 : : #endif
283 : :
284 : : /** Memcpy with strictly ordered memory access, e.g. used by code in ARM_MPU_LoadEx()
285 : : * \param dst Destination data is copied to.
286 : : * \param src Source data is copied from.
287 : : * \param len Amount of data words to be copied.
288 : : */
289 : : __STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
290 : : {
291 : : uint32_t i;
292 : : for (i = 0U; i < len; ++i)
293 : : {
294 : : dst[i] = src[i];
295 : : }
296 : : }
297 : :
298 : : /** Load the given number of MPU regions from a table to the given MPU.
299 : : * \param mpu Pointer to the MPU registers to be used.
300 : : * \param rnr First region number to be configured.
301 : : * \param table Pointer to the MPU configuration table.
302 : : * \param cnt Amount of regions to be configured.
303 : : */
304 : : __STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
305 : : {
306 : : const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
307 : : if (cnt == 1U) {
308 : : mpu->RNR = rnr;
309 : : ARM_MPU_OrderedMemcpy(&(mpu->RBAR), &(table->RBAR), rowWordSize);
310 : : } else {
311 : : uint32_t rnrBase = rnr & ~(MPU_TYPE_RALIASES-1U);
312 : : uint32_t rnrOffset = rnr % MPU_TYPE_RALIASES;
313 : :
314 : : mpu->RNR = rnrBase;
315 : : while ((rnrOffset + cnt) > MPU_TYPE_RALIASES) {
316 : : uint32_t c = MPU_TYPE_RALIASES - rnrOffset;
317 : : ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), c*rowWordSize);
318 : : table += c;
319 : : cnt -= c;
320 : : rnrOffset = 0U;
321 : : rnrBase += MPU_TYPE_RALIASES;
322 : : mpu->RNR = rnrBase;
323 : : }
324 : :
325 : : ARM_MPU_OrderedMemcpy(&(mpu->RBAR)+(rnrOffset*2U), &(table->RBAR), cnt*rowWordSize);
326 : : }
327 : : }
328 : :
329 : : /** Load the given number of MPU regions from a table.
330 : : * \param rnr First region number to be configured.
331 : : * \param table Pointer to the MPU configuration table.
332 : : * \param cnt Amount of regions to be configured.
333 : : */
334 : : __STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
335 : : {
336 : : ARM_MPU_LoadEx(MPU, rnr, table, cnt);
337 : : }
338 : :
339 : : #ifdef MPU_NS
340 : : /** Load the given number of MPU regions from a table to the Non-secure MPU.
341 : : * \param rnr First region number to be configured.
342 : : * \param table Pointer to the MPU configuration table.
343 : : * \param cnt Amount of regions to be configured.
344 : : */
345 : : __STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt)
346 : : {
347 : : ARM_MPU_LoadEx(MPU_NS, rnr, table, cnt);
348 : : }
349 : : #endif
350 : :
351 : : #endif
352 : :
|