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