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