1 /****************************************************************************** 2 * @file mpu_armv7.h 3 * @brief CMSIS MPU API for Armv7-M MPU 4 * @version V5.1.1 5 * @date 10. February 2020 6 ******************************************************************************/ 7 8 /* 9 * Copyright (c) 2017-2020 Arm Limited. All rights reserved. 10 * 11 * SPDX-License-Identifier: Apache-2.0 12 * 13 * Licensed under the Apache License, Version 2.0 (the License); you may 14 * not use this file except in compliance with the License. 15 * You may obtain a copy of the License at 16 * 17 * www.apache.org/licenses/LICENSE-2.0 18 * 19 * Unless required by applicable law or agreed to in writing, software 20 * distributed under the License is distributed on an AS IS BASIS, WITHOUT 21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 * See the License for the specific language governing permissions and 23 * limitations under the License. 24 */ 25 26 #if defined( __ICCARM__ ) 27 #pragma system_include /* treat file as system include file for MISRA check */ 28 #elif defined( __clang__ ) 29 #pragma clang system_header /* treat file as system include file */ 30 #endif 31 32 #ifndef ARM_MPU_ARMV7_H 33 #define ARM_MPU_ARMV7_H 34 35 #define ARM_MPU_REGION_SIZE_32B ( ( uint8_t ) 0x04U ) /*/!< MPU Region Size 32 Bytes */ 36 #define ARM_MPU_REGION_SIZE_64B ( ( uint8_t ) 0x05U ) /*/!< MPU Region Size 64 Bytes */ 37 #define ARM_MPU_REGION_SIZE_128B ( ( uint8_t ) 0x06U ) /*/!< MPU Region Size 128 Bytes */ 38 #define ARM_MPU_REGION_SIZE_256B ( ( uint8_t ) 0x07U ) /*/!< MPU Region Size 256 Bytes */ 39 #define ARM_MPU_REGION_SIZE_512B ( ( uint8_t ) 0x08U ) /*/!< MPU Region Size 512 Bytes */ 40 #define ARM_MPU_REGION_SIZE_1KB ( ( uint8_t ) 0x09U ) /*/!< MPU Region Size 1 KByte */ 41 #define ARM_MPU_REGION_SIZE_2KB ( ( uint8_t ) 0x0AU ) /*/!< MPU Region Size 2 KBytes */ 42 #define ARM_MPU_REGION_SIZE_4KB ( ( uint8_t ) 0x0BU ) /*/!< MPU Region Size 4 KBytes */ 43 #define ARM_MPU_REGION_SIZE_8KB ( ( uint8_t ) 0x0CU ) /*/!< MPU Region Size 8 KBytes */ 44 #define ARM_MPU_REGION_SIZE_16KB ( ( uint8_t ) 0x0DU ) /*/!< MPU Region Size 16 KBytes */ 45 #define ARM_MPU_REGION_SIZE_32KB ( ( uint8_t ) 0x0EU ) /*/!< MPU Region Size 32 KBytes */ 46 #define ARM_MPU_REGION_SIZE_64KB ( ( uint8_t ) 0x0FU ) /*/!< MPU Region Size 64 KBytes */ 47 #define ARM_MPU_REGION_SIZE_128KB ( ( uint8_t ) 0x10U ) /*/!< MPU Region Size 128 KBytes */ 48 #define ARM_MPU_REGION_SIZE_256KB ( ( uint8_t ) 0x11U ) /*/!< MPU Region Size 256 KBytes */ 49 #define ARM_MPU_REGION_SIZE_512KB ( ( uint8_t ) 0x12U ) /*/!< MPU Region Size 512 KBytes */ 50 #define ARM_MPU_REGION_SIZE_1MB ( ( uint8_t ) 0x13U ) /*/!< MPU Region Size 1 MByte */ 51 #define ARM_MPU_REGION_SIZE_2MB ( ( uint8_t ) 0x14U ) /*/!< MPU Region Size 2 MBytes */ 52 #define ARM_MPU_REGION_SIZE_4MB ( ( uint8_t ) 0x15U ) /*/!< MPU Region Size 4 MBytes */ 53 #define ARM_MPU_REGION_SIZE_8MB ( ( uint8_t ) 0x16U ) /*/!< MPU Region Size 8 MBytes */ 54 #define ARM_MPU_REGION_SIZE_16MB ( ( uint8_t ) 0x17U ) /*/!< MPU Region Size 16 MBytes */ 55 #define ARM_MPU_REGION_SIZE_32MB ( ( uint8_t ) 0x18U ) /*/!< MPU Region Size 32 MBytes */ 56 #define ARM_MPU_REGION_SIZE_64MB ( ( uint8_t ) 0x19U ) /*/!< MPU Region Size 64 MBytes */ 57 #define ARM_MPU_REGION_SIZE_128MB ( ( uint8_t ) 0x1AU ) /*/!< MPU Region Size 128 MBytes */ 58 #define ARM_MPU_REGION_SIZE_256MB ( ( uint8_t ) 0x1BU ) /*/!< MPU Region Size 256 MBytes */ 59 #define ARM_MPU_REGION_SIZE_512MB ( ( uint8_t ) 0x1CU ) /*/!< MPU Region Size 512 MBytes */ 60 #define ARM_MPU_REGION_SIZE_1GB ( ( uint8_t ) 0x1DU ) /*/!< MPU Region Size 1 GByte */ 61 #define ARM_MPU_REGION_SIZE_2GB ( ( uint8_t ) 0x1EU ) /*/!< MPU Region Size 2 GBytes */ 62 #define ARM_MPU_REGION_SIZE_4GB ( ( uint8_t ) 0x1FU ) /*/!< MPU Region Size 4 GBytes */ 63 64 #define ARM_MPU_AP_NONE 0U /*/!< MPU Access Permission no access */ 65 #define ARM_MPU_AP_PRIV 1U /*/!< MPU Access Permission privileged access only */ 66 #define ARM_MPU_AP_URO 2U /*/!< MPU Access Permission unprivileged access read-only */ 67 #define ARM_MPU_AP_FULL 3U /*/!< MPU Access Permission full access */ 68 #define ARM_MPU_AP_PRO 5U /*/!< MPU Access Permission privileged access read-only */ 69 #define ARM_MPU_AP_RO 6U /*/!< MPU Access Permission read-only access */ 70 71 /** MPU Region Base Address Register Value 72 * 73 * \param Region The region to be configured, number 0 to 15. 74 * \param BaseAddress The base address for the region. 75 */ 76 #define ARM_MPU_RBAR( Region, BaseAddress ) \ 77 ( ( ( BaseAddress ) & MPU_RBAR_ADDR_Msk ) | \ 78 ( ( Region ) & MPU_RBAR_REGION_Msk ) | \ 79 ( MPU_RBAR_VALID_Msk ) ) 80 81 /** 82 * MPU Memory Access Attributes 83 * 84 * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. 85 * \param IsShareable Region is shareable between multiple bus masters. 86 * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. 87 * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. 88 */ 89 #define ARM_MPU_ACCESS_( TypeExtField, IsShareable, IsCacheable, IsBufferable ) \ 90 ( ( ( ( TypeExtField ) << MPU_RASR_TEX_Pos ) & MPU_RASR_TEX_Msk ) | \ 91 ( ( ( IsShareable ) << MPU_RASR_S_Pos ) & MPU_RASR_S_Msk ) | \ 92 ( ( ( IsCacheable ) << MPU_RASR_C_Pos ) & MPU_RASR_C_Msk ) | \ 93 ( ( ( IsBufferable ) << MPU_RASR_B_Pos ) & MPU_RASR_B_Msk ) ) 94 95 /** 96 * MPU Region Attribute and Size Register Value 97 * 98 * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. 99 * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. 100 * \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_. 101 * \param SubRegionDisable Sub-region disable field. 102 * \param Size Region size of the region to be configured, for example 4K, 8K. 103 */ 104 #define ARM_MPU_RASR_EX( DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size ) \ 105 ( ( ( ( DisableExec ) << MPU_RASR_XN_Pos ) & MPU_RASR_XN_Msk ) | \ 106 ( ( ( AccessPermission ) << MPU_RASR_AP_Pos ) & MPU_RASR_AP_Msk ) | \ 107 ( ( ( AccessAttributes ) & ( MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk ) ) ) | \ 108 ( ( ( SubRegionDisable ) << MPU_RASR_SRD_Pos ) & MPU_RASR_SRD_Msk ) | \ 109 ( ( ( Size ) << MPU_RASR_SIZE_Pos ) & MPU_RASR_SIZE_Msk ) | \ 110 ( ( ( MPU_RASR_ENABLE_Msk ) ) ) ) 111 112 /** 113 * MPU Region Attribute and Size Register Value 114 * 115 * \param DisableExec Instruction access disable bit, 1= disable instruction fetches. 116 * \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode. 117 * \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral. 118 * \param IsShareable Region is shareable between multiple bus masters. 119 * \param IsCacheable Region is cacheable, i.e. its value may be kept in cache. 120 * \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy. 121 * \param SubRegionDisable Sub-region disable field. 122 * \param Size Region size of the region to be configured, for example 4K, 8K. 123 */ 124 #define ARM_MPU_RASR( DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size ) \ 125 ARM_MPU_RASR_EX( DisableExec, AccessPermission, ARM_MPU_ACCESS_( TypeExtField, IsShareable, IsCacheable, IsBufferable ), SubRegionDisable, Size ) 126 127 /** 128 * MPU Memory Access Attribute for strongly ordered memory. 129 * - TEX: 000b 130 * - Shareable 131 * - Non-cacheable 132 * - Non-bufferable 133 */ 134 #define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_( 0U, 1U, 0U, 0U ) 135 136 /** 137 * MPU Memory Access Attribute for device memory. 138 * - TEX: 000b (if shareable) or 010b (if non-shareable) 139 * - Shareable or non-shareable 140 * - Non-cacheable 141 * - Bufferable (if shareable) or non-bufferable (if non-shareable) 142 * 143 * \param IsShareable Configures the device memory as shareable or non-shareable. 144 */ 145 #define ARM_MPU_ACCESS_DEVICE( IsShareable ) ( ( IsShareable ) ? ARM_MPU_ACCESS_( 0U, 1U, 0U, 1U ) : ARM_MPU_ACCESS_( 2U, 0U, 0U, 0U ) ) 146 147 /** 148 * MPU Memory Access Attribute for normal memory. 149 * - TEX: 1BBb (reflecting outer cacheability rules) 150 * - Shareable or non-shareable 151 * - Cacheable or non-cacheable (reflecting inner cacheability rules) 152 * - Bufferable or non-bufferable (reflecting inner cacheability rules) 153 * 154 * \param OuterCp Configures the outer cache policy. 155 * \param InnerCp Configures the inner cache policy. 156 * \param IsShareable Configures the memory as shareable or non-shareable. 157 */ 158 #define ARM_MPU_ACCESS_NORMAL( OuterCp, InnerCp, IsShareable ) ARM_MPU_ACCESS_( ( 4U | ( OuterCp ) ), IsShareable, ( ( InnerCp ) >> 1U ), ( ( InnerCp ) & 1U ) ) 159 160 /** 161 * MPU Memory Access Attribute non-cacheable policy. 162 */ 163 #define ARM_MPU_CACHEP_NOCACHE 0U 164 165 /** 166 * MPU Memory Access Attribute write-back, write and read allocate policy. 167 */ 168 #define ARM_MPU_CACHEP_WB_WRA 1U 169 170 /** 171 * MPU Memory Access Attribute write-through, no write allocate policy. 172 */ 173 #define ARM_MPU_CACHEP_WT_NWA 2U 174 175 /** 176 * MPU Memory Access Attribute write-back, no write allocate policy. 177 */ 178 #define ARM_MPU_CACHEP_WB_NWA 3U 179 180 181 /** 182 * Struct for a single MPU Region 183 */ 184 typedef struct 185 { 186 uint32_t RBAR; /*!< The region base address register value (RBAR) */ 187 uint32_t RASR; /*!< The region attribute and size register value (RASR) \ref MPU_RASR */ 188 } ARM_MPU_Region_t; 189 190 /** Enable the MPU. 191 * \param MPU_Control Default access permissions for unconfigured regions. 192 */ ARM_MPU_Enable(uint32_t MPU_Control)193 __STATIC_INLINE void ARM_MPU_Enable( uint32_t MPU_Control ) 194 { 195 __DMB(); 196 MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk; 197 #ifdef SCB_SHCSR_MEMFAULTENA_Msk 198 SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; 199 #endif 200 __DSB(); 201 __ISB(); 202 } 203 204 /** Disable the MPU. 205 */ ARM_MPU_Disable(void)206 __STATIC_INLINE void ARM_MPU_Disable( void ) 207 { 208 __DMB(); 209 #ifdef SCB_SHCSR_MEMFAULTENA_Msk 210 SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; 211 #endif 212 MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; 213 __DSB(); 214 __ISB(); 215 } 216 217 /** Clear and disable the given MPU region. 218 * \param rnr Region number to be cleared. 219 */ ARM_MPU_ClrRegion(uint32_t rnr)220 __STATIC_INLINE void ARM_MPU_ClrRegion( uint32_t rnr ) 221 { 222 MPU->RNR = rnr; 223 MPU->RASR = 0U; 224 } 225 226 /** Configure an MPU region. 227 * \param rbar Value for RBAR register. 228 * \param rsar Value for RSAR register. 229 */ ARM_MPU_SetRegion(uint32_t rbar,uint32_t rasr)230 __STATIC_INLINE void ARM_MPU_SetRegion( uint32_t rbar, 231 uint32_t rasr ) 232 { 233 MPU->RBAR = rbar; 234 MPU->RASR = rasr; 235 } 236 237 /** Configure the given MPU region. 238 * \param rnr Region number to be configured. 239 * \param rbar Value for RBAR register. 240 * \param rsar Value for RSAR register. 241 */ ARM_MPU_SetRegionEx(uint32_t rnr,uint32_t rbar,uint32_t rasr)242 __STATIC_INLINE void ARM_MPU_SetRegionEx( uint32_t rnr, 243 uint32_t rbar, 244 uint32_t rasr ) 245 { 246 MPU->RNR = rnr; 247 MPU->RBAR = rbar; 248 MPU->RASR = rasr; 249 } 250 251 /** Memcopy with strictly ordered memory access, e.g. for register targets. 252 * \param dst Destination data is copied to. 253 * \param src Source data is copied from. 254 * \param len Amount of data words to be copied. 255 */ ARM_MPU_OrderedMemcpy(volatile uint32_t * dst,const uint32_t * __RESTRICT src,uint32_t len)256 __STATIC_INLINE void ARM_MPU_OrderedMemcpy( volatile uint32_t * dst, 257 const uint32_t * __RESTRICT src, 258 uint32_t len ) 259 { 260 uint32_t i; 261 262 for( i = 0U; i < len; ++i ) 263 { 264 dst[ i ] = src[ i ]; 265 } 266 } 267 268 /** Load the given number of MPU regions from a table. 269 * \param table Pointer to the MPU configuration table. 270 * \param cnt Amount of regions to be configured. 271 */ ARM_MPU_Load(ARM_MPU_Region_t const * table,uint32_t cnt)272 __STATIC_INLINE void ARM_MPU_Load( ARM_MPU_Region_t const * table, 273 uint32_t cnt ) 274 { 275 const uint32_t rowWordSize = sizeof( ARM_MPU_Region_t ) / 4U; 276 277 while( cnt > MPU_TYPE_RALIASES ) 278 { 279 ARM_MPU_OrderedMemcpy( &( MPU->RBAR ), &( table->RBAR ), MPU_TYPE_RALIASES * rowWordSize ); 280 table += MPU_TYPE_RALIASES; 281 cnt -= MPU_TYPE_RALIASES; 282 } 283 284 ARM_MPU_OrderedMemcpy( &( MPU->RBAR ), &( table->RBAR ), cnt * rowWordSize ); 285 } 286 287 #endif /* ifndef ARM_MPU_ARMV7_H */ 288