1/**
2\defgroup mpu8_functions  MPU Functions for Armv8-M
3\brief Functions that relate to the Memory Protection Unit.
4\details
5The following functions support the optional Memory Protection Unit (MPU) that is available on the Cortex-M23, M33, M35P processor.
6
7The MPU is used to prevent from illegal memory accesses that are typically caused by errors in an application software.
8
9<b>Example:</b>
10\code
11int main()
12{
13  // Set Region 0 using Attr 0
14  ARM_MPU_SetMemAttr(0UL, ARM_MPU_ATTR( /* Normal memory */
15    MPU_ATTR_NORMAL_OUTER_WT_TR_RA_WA,  /* Outer Write-Back transient with read and write allocate */
16    MPU_ATTR_NORMAL_INNER_WT_TR_RA_WA   /* Inner Write-Through transient with read and write allocate */
17  ));
18
19  ARM_MPU_SetRegion(0UL,
20    ARM_MPU_RBAR(0x08000000UL, ARM_MPU_SH_NON, ARM_MPU_AP_RW, ARM_MPU_AP_NP, ARM_MPU_XN),  /* Non-shareable, read/write, non-privileged, execute-never */
21    ARM_MPU_RLAR(0x080FFFFFUL, MAIR_ATTR(0))                        /* 1MB memory block using Attr 0 */
22  );
23
24  ARM_MPU_Enable(0);
25
26  // Execute application code that is access protected by the MPU
27
28  ARM_MPU_Disable();
29}
30\endcode
31
32@{
33*/
34
35/** \brief Attribute for device memory (outer only) */
36#define ARM_MPU_ATTR_DEVICE                           ( 0U )
37
38/** \brief Attribute for non-cacheable, normal memory */
39#define ARM_MPU_ATTR_NON_CACHEABLE                    ( 4U )
40
41/** \brief Attribute for Normal memory, Outer and Inner cacheability.
42* \param NT Non-Transient: Set to 1 for Non-transient data. Set to 0 for Transient data.
43* \param WB Write-Back: Set to 1 to use a Write-Back policy. Set to 0 to use a Write-Through policy.
44* \param RA Read Allocation: Set to 1 to enable cache allocation on read miss. Set to 0 to disable cache allocation on read miss.
45* \param WA Write Allocation: Set to 1 to enable cache allocation on write miss. Set to 0 to disable cache allocation on write miss.
46*/
47#define ARM_MPU_ATTR_MEMORY_(NT, WB, RA, WA)
48
49/** \brief Device memory type non Gathering, non Re-ordering, non Early Write Acknowledgement */
50#define ARM_MPU_ATTR_DEVICE_nGnRnE
51
52/** \brief Device memory type non Gathering, non Re-ordering, Early Write Acknowledgement */
53#define ARM_MPU_ATTR_DEVICE_nGnRE
54
55/** \brief Device memory type non Gathering, Re-ordering, Early Write Acknowledgement */
56#define ARM_MPU_ATTR_DEVICE_nGRE
57
58/** \brief Device memory type Gathering, Re-ordering, Early Write Acknowledgement */
59#define ARM_MPU_ATTR_DEVICE_GRE
60
61/** \brief Normal memory outer-cacheable and inner-cacheable attributes
62* WT = Write Through, WB = Write Back, TR = Transient, RA = Read-Allocate, WA = Write Allocate
63*/
64#define MPU_ATTR_NORMAL_OUTER_NON_CACHEABLE
65#define MPU_ATTR_NORMAL_OUTER_WT_TR_RA
66#define MPU_ATTR_NORMAL_OUTER_WT_TR_WA
67#define MPU_ATTR_NORMAL_OUTER_WT_TR_RA_WA
68#define MPU_ATTR_NORMAL_OUTER_WT_RA
69#define MPU_ATTR_NORMAL_OUTER_WT_WA
70#define MPU_ATTR_NORMAL_OUTER_WT_RA_WA
71#define MPU_ATTR_NORMAL_OUTER_WB_TR_RA
72#define MPU_ATTR_NORMAL_OUTER_WB_TR_WA
73#define MPU_ATTR_NORMAL_OUTER_WB_TR_RA_WA
74#define MPU_ATTR_NORMAL_OUTER_WB_RA
75#define MPU_ATTR_NORMAL_OUTER_WB_WA
76#define MPU_ATTR_NORMAL_OUTER_WB_RA_WA
77#define MPU_ATTR_NORMAL_INNER_NON_CACHEABLE
78#define MPU_ATTR_NORMAL_INNER_WT_TR_RA
79#define MPU_ATTR_NORMAL_INNER_WT_TR_WA
80#define MPU_ATTR_NORMAL_INNER_WT_TR_RA_WA
81#define MPU_ATTR_NORMAL_INNER_WT_RA
82#define MPU_ATTR_NORMAL_INNER_WT_WA
83#define MPU_ATTR_NORMAL_INNER_WT_RA_WA
84#define MPU_ATTR_NORMAL_INNER_WB_TR_RA
85#define MPU_ATTR_NORMAL_INNER_WB_TR_WA
86#define MPU_ATTR_NORMAL_INNER_WB_TR_RA_WA
87#define MPU_ATTR_NORMAL_INNER_WB_RA
88#define MPU_ATTR_NORMAL_INNER_WB_WA
89#define MPU_ATTR_NORMAL_INNER_WB_RA_WA
90
91/** \brief Memory Attribute
92* \param O Outer memory attributes
93* \param I O == ARM_MPU_ATTR_DEVICE: Device memory attributes, else: Inner memory attributes
94*/
95#define ARM_MPU_ATTR(O, I)
96
97/**
98 * Shareability
99 */
100/** \brief Normal memory non-shareable  */
101#define ARM_MPU_SH_NON
102
103/** \brief Normal memory outer shareable  */
104#define ARM_MPU_SH_OUTER
105
106/** \brief Normal memory inner shareable  */
107#define ARM_MPU_SH_INNER
108
109/**
110 * Access permissions
111 * AP = Access permission, RO = Read-only, RW = Read/Write, NP = Any privilege, PO = Privileged code only
112 */
113/** \brief Normal memory, read/write */
114#define ARM_MPU_AP_RW
115
116/** \brief Normal memory, read-only */
117#define ARM_MPU_AP_RO
118
119/** \brief Normal memory, any privilege level */
120#define ARM_MPU_AP_NP
121
122/** \brief Normal memory, privileged access only */
123#define ARM_MPU_AP_PO
124
125/*
126 * Execute-never
127 * XN = Execute-never, EX = Executable
128 */
129/** \brief Normal memory, Execution only permitted if read permitted */
130#define ARM_MPU_XN
131
132/** \brief Normal memory, Execution only permitted if read permitted */
133#define ARM_MPU_EX
134
135/** \brief Memory access permissions
136* \param RO Read-Only: Set to 1 for read-only memory.
137* \param NP Non-Privileged: Set to 1 for non-privileged memory.
138*/
139#define ARM_MPU_AP_(RO, NP)
140
141/** \brief Region Base Address Register value
142* \param BASE The base address bits [31:5] of a memory region. The value is zero extended. Effective address gets 32 byte aligned.
143* \param SH Defines the Shareability domain for this memory region.
144* \param RO Read-Only: Set to 1 for a read-only memory region. Set to 0 for a read/write memory region.
145* \param NP Non-Privileged: Set to 1 for a non-privileged memory region. Set to 0 for privileged memory region.
146* \param XN eXecute Never: Set to 1 for a non-executable memory region. Set to 0 for an executable memory region.
147*/
148#define ARM_MPU_RBAR(BASE, SH, RO, NP, XN)
149
150/** \brief Region Limit Address Register value
151* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
152* \param IDX The attribute index to be associated with this memory region.
153*/
154#define ARM_MPU_RLAR(LIMIT, IDX)
155
156/** \brief Region Limit Address Register with PXN value
157* \param LIMIT The limit address bits [31:5] for this memory region. The value is one extended.
158* \param PXN Privileged execute never. Defines whether code can be executed from this privileged region.
159* \param IDX The attribute index to be associated with this memory region.
160*/
161#define ARM_MPU_RLAR_PXN(LIMIT, PXN, IDX)
162
163/**
164* Struct for a single MPU Region
165*/
166typedef struct {
167  uint32_t RBAR;                   /*!< Region Base Address Register value */
168  uint32_t RLAR;                   /*!< Region Limit Address Register value */
169} ARM_MPU_Region_t;
170
171/**
172* \brief  Read MPU Type Register
173* \return Number of MPU regions
174*/
175__STATIC_INLINE uint32_t ARM_MPU_TYPE();
176
177/**
178* \brief Enable the MPU.
179* \param MPU_Control Default access permissions for unconfigured regions.
180*/
181__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control);
182
183/** Disable the MPU.
184*/
185__STATIC_INLINE void ARM_MPU_Disable(void);
186
187/** Enable the Non-secure MPU.
188* \param MPU_Control Default access permissions for unconfigured regions.
189*/
190__STATIC_INLINE ARM_MPU_Enable_NS(uint32_t MPU_Control);
191
192/** Disable the Non-secure MPU.
193*/
194__STATIC_INLINE void ARM_MPU_Disable_NS(void);
195
196/** Set the memory attribute encoding to the given MPU.
197* \param mpu Pointer to the MPU to be configured.
198* \param idx The attribute index to be set [0-7]
199* \param attr The attribute value to be set.
200*/
201__STATIC_INLINE void ARM_MPU_SetMemAttrEx(MPU_Type* mpu, uint8_t idx, uint8_t attr);
202
203/** Set the memory attribute encoding.
204* \param idx The attribute index to be set [0-7]
205* \param attr The attribute value to be set.
206*/
207__STATIC_INLINE void ARM_MPU_SetMemAttr(uint8_t idx, uint8_t attr);
208
209/** Set the memory attribute encoding to the Non-secure MPU.
210* \param idx The attribute index to be set [0-7]
211* \param attr The attribute value to be set.
212*/
213__STATIC_INLINE void ARM_MPU_SetMemAttr_NS(uint8_t idx, uint8_t attr);
214
215/** Clear and disable the given MPU region of the given MPU.
216* \param mpu Pointer to MPU to be used.
217* \param rnr Region number to be cleared.
218*/
219__STATIC_INLINE void ARM_MPU_ClrRegionEx(MPU_Type* mpu, uint32_t rnr);
220
221/** Clear and disable the given MPU region.
222* \param rnr Region number to be cleared.
223*/
224__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr);
225
226/** Clear and disable the given Non-secure MPU region.
227* \param rnr Region number to be cleared.
228*/
229__STATIC_INLINE void ARM_MPU_ClrRegion_NS(uint32_t rnr);
230
231/** Configure the given MPU region of the given MPU.
232* \param mpu Pointer to MPU to be used.
233* \param rnr Region number to be configured.
234* \param rbar Value for RBAR register.
235* \param rlar Value for RLAR register.
236*/
237__STATIC_INLINE void ARM_MPU_SetRegionEx(MPU_Type* mpu, uint32_t rnr, uint32_t rbar, uint32_t rlar);
238
239/** Configure the given MPU region.
240* \param rnr Region number to be configured.
241* \param rbar Value for RBAR register.
242* \param rlar Value for RLAR register.
243*/
244__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rnr, uint32_t rbar, uint32_t rlar);
245
246/** Configure the given Non-secure MPU region.
247* \param rnr Region number to be configured.
248* \param rbar Value for RBAR register.
249* \param rlar Value for RLAR register.
250*/
251__STATIC_INLINE void ARM_MPU_SetRegion_NS(uint32_t rnr, uint32_t rbar, uint32_t rlar);
252
253/** Memcpy with strictly ordered memory access, e.g. used by code in \ref ARM_MPU_LoadEx.
254* \param dst Destination data is copied to.
255* \param src Source data is copied from.
256* \param len Amount of data words to be copied.
257*/
258__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len);
259
260/** Load the given number of MPU regions from a table to the given MPU.
261* \param mpu Pointer to the MPU registers to be used.
262* \param rnr First region number to be configured.
263* \param table Pointer to the MPU configuration table.
264* \param cnt Amount of regions to be configured.
265*/
266__STATIC_INLINE void ARM_MPU_LoadEx(MPU_Type* mpu, uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt);
267
268/** Load the given number of MPU regions from a table.
269* \param rnr First region number to be configured.
270* \param table Pointer to the MPU configuration table.
271* \param cnt Amount of regions to be configured.
272*
273* <b>Example:</b>
274* \code
275* const ARM_MPU_Region_t mpuTable[1][4] = {
276*   {
277*     //                     BASE          SH              RO             NP             XN                                LIMIT         ATTR
278*     { .RBAR = ARM_MPU_RBAR(0x08000000UL, ARM_MPU_SH_NON, ARM_MPU_AP_RO, ARM_MPU_AP_NP, ARM_MPU_XN), .RLAR = ARM_MPU_RLAR(0x080FFFFFUL, MAIR_ATTR(0)) },
279*     { .RBAR = ARM_MPU_RBAR(0x20000000UL, ARM_MPU_SH_NON, ARM_MPU_AP_RO, ARM_MPU_AP_NP, ARM_MPU_XN), .RLAR = ARM_MPU_RLAR(0x20007FFFUL, MAIR_ATTR(0)) },
280*     { .RBAR = ARM_MPU_RBAR(0x40020000UL, ARM_MPU_SH_NON, ARM_MPU_AP_RO, ARM_MPU_AP_NP, ARM_MPU_XN), .RLAR = ARM_MPU_RLAR(0x40021FFFUL, MAIR_ATTR(1)) },
281*     { .RBAR = ARM_MPU_RBAR(0x40022000UL, ARM_MPU_SH_NON, ARM_MPU_AP_RO, ARM_MPU_AP_NP, ARM_MPU_XN), .RLAR = ARM_MPU_RLAR(0x40022FFFUL, MAIR_ATTR(1)) }
282*   }
283* };
284*
285* void UpdateMpu(uint32_t idx)
286* {
287*    ARM_MPU_Load(0, mpuTable[idx], 4);
288* }
289* \endcode
290*/
291__STATIC_INLINE void ARM_MPU_Load(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt);
292
293/** Load the given number of MPU regions from a table to the Non-secure MPU.
294* \param rnr First region number to be configured.
295* \param table Pointer to the MPU configuration table.
296* \param cnt Amount of regions to be configured.
297*/
298__STATIC_INLINE void ARM_MPU_Load_NS(uint32_t rnr, ARM_MPU_Region_t const* table, uint32_t cnt);
299
300/** @} */
301
302