Commit | Line | Data |
---|---|---|
65eee97a AG |
1 | /* Copyright 2011 Adam Green (http://mbed.org/users/AdamGreen/) |
2 | ||
3 | Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | you may not use this file except in compliance with the License. | |
5 | You may obtain a copy of the License at | |
6 | ||
7 | http://www.apache.org/licenses/LICENSE-2.0 | |
8 | ||
9 | Unless required by applicable law or agreed to in writing, software | |
10 | distributed under the License is distributed on an "AS IS" BASIS, | |
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | See the License for the specific language governing permissions and | |
13 | limitations under the License. | |
14 | */ | |
15 | #ifndef _MPU_H_ | |
16 | #define _MPU_H_ | |
17 | ||
18 | #include <cmsis.h> | |
19 | ||
20 | /* Memory Protection Unit Type Register Bits. */ | |
21 | /* Number of instruction regions supported by MPU. 0 for Cortex-M3 */ | |
22 | #define MPU_TYPE_IREGION_SHIFT 16 | |
23 | #define MPU_TYPE_IREGION_MASK (0xFF << MPU_TYPE_IREGION_SHIFT) | |
24 | /* Number of data regions supported by MPU. */ | |
25 | #define MPU_TYPE_DREGION_SHIFT 8 | |
26 | #define MPU_TYPE_DREGION_MASK (0xFF << MPU_TYPE_DREGION_SHIFT) | |
27 | /* Are instruction and data regions configured separately? 1 for yes and 0 otherwise. */ | |
28 | #define MPU_TYPE_SEPARATE 0x1 | |
29 | ||
30 | /* Memory Protection Unit Control Register Bits. */ | |
31 | /* Default memory map as background region for privileged access. 1 enables. */ | |
32 | #define MPU_CTRL_PRIVDEFENA (1 << 2) | |
33 | /* Hard fault and NMI exceptions to use MPU. 0 disables MPU for these handlers. */ | |
34 | #define MPU_CTRL_HFNMIENA (1 << 1) | |
35 | /* MPU Enable. 1 enables and disabled otherwise. */ | |
36 | #define MPU_CTRL_ENABLE 1 | |
37 | ||
38 | /* Memory Protection Unit Region Region Number Register Bits. */ | |
39 | #define MPU_RNR_REGION_MASK 0xFF | |
40 | ||
41 | /* Memory Protection Unit Region Base Address Register Bits. */ | |
42 | /* Base address of this region. */ | |
43 | #define MPU_RBAR_ADDR_SHIFT 5 | |
44 | #define MPU_RBAR_ADDR_MASK (0x7FFFFFF << MPU_RBAR_ADDR_SHIFT) | |
45 | /* Are the region bits in this register valid or should RNR be used instead. */ | |
46 | #define MPU_RBAR_VALID (1 << 4) | |
47 | /* The region number. Only used when MPU_RBAR_VALID is one. */ | |
48 | #define MPU_RBAR_REGION_MASK 0xF | |
49 | ||
50 | /* Memory Protection Unit Region Attribute and Size Register Bits. */ | |
51 | /* eXecute Never bit. 1 means code can't execute from this region. */ | |
52 | #define MPU_RASR_XN (1 << 28) | |
53 | /* Access permission bits. */ | |
54 | #define MPU_RASR_AP_SHIFT 24 | |
55 | #define MPU_RASR_AP_MASK (0x7 << MPU_RASR_AP_SHIFT) | |
56 | /* TEX, C, and B bits together determine memory type. */ | |
57 | #define MPU_RASR_TEX_SHIFT 19 | |
58 | #define MPU_RASR_TEX_MASK (0x7 << MPU_RASR_TEX_SHIFT) | |
59 | #define MPU_RASR_S (1 << 18) | |
60 | #define MPU_RASR_C (1 << 17) | |
61 | #define MPU_RASR_B (1 << 16) | |
62 | /* Sub-region disable bits. */ | |
63 | #define MPU_RASR_SRD_SHIFT 8 | |
64 | #define MPU_RASR_SRD_MASK (0xff << MPU_RASR_SRD_SHIFT) | |
65 | /* Region size in 2^(value + 1) */ | |
66 | #define MPU_RASR_SIZE_SHIFT 1 | |
67 | #define MPU_RASR_SIZE_MASK (0x1F << MPU_RASR_SIZE_SHIFT) | |
68 | /* Region enable. 1 enables. */ | |
69 | #define MPU_RASR_ENABLE 1 | |
70 | ||
71 | ||
72 | /* MPU - Memory Protection Unit Routines. */ | |
73 | static __INLINE uint32_t getMPUDataRegionCount(void) | |
74 | { | |
75 | return (MPU->TYPE & MPU_TYPE_DREGION_MASK) >> MPU_TYPE_DREGION_SHIFT; | |
76 | } | |
77 | ||
78 | static __INLINE uint32_t getHighestMPUDataRegionIndex(void) | |
79 | { | |
80 | return getMPUDataRegionCount() - 1; | |
81 | } | |
82 | ||
83 | static __INLINE int isMPURegionNumberValid(uint32_t regionNumber) | |
84 | { | |
85 | return regionNumber < getMPUDataRegionCount(); | |
86 | } | |
87 | ||
88 | static __INLINE int isMPUNotPresent(void) | |
89 | { | |
90 | return getMPUDataRegionCount() == 0; | |
91 | } | |
92 | ||
93 | static __INLINE uint32_t getMPUControlValue(void) | |
94 | { | |
95 | if (isMPUNotPresent()) | |
96 | return ~0U; | |
97 | ||
98 | return (MPU->CTRL); | |
99 | ||
100 | } | |
101 | ||
102 | static __INLINE void setMPUControlValue(uint32_t newControlValue) | |
103 | { | |
104 | if (isMPUNotPresent()) | |
105 | return; | |
106 | ||
107 | MPU->CTRL = newControlValue; | |
108 | __DSB(); | |
109 | __ISB(); | |
110 | } | |
111 | ||
112 | static __INLINE void disableMPU(void) | |
113 | { | |
114 | if (isMPUNotPresent()) | |
115 | return; | |
116 | ||
117 | MPU->CTRL &= ~MPU_CTRL_ENABLE; | |
118 | __DSB(); | |
119 | __ISB(); | |
120 | } | |
121 | ||
122 | static __INLINE void enableMPU(void) | |
123 | { | |
124 | if (isMPUNotPresent()) | |
125 | return; | |
126 | ||
ddf5038e | 127 | MPU->CTRL = MPU_CTRL_ENABLE; |
65eee97a AG |
128 | __DSB(); |
129 | __ISB(); | |
130 | } | |
131 | ||
132 | static __INLINE void enableMPUWithHardAndNMIFaults(void) | |
133 | { | |
134 | if (isMPUNotPresent()) | |
135 | return; | |
136 | ||
ddf5038e AG |
137 | MPU->CTRL = MPU_CTRL_ENABLE | MPU_CTRL_HFNMIENA; |
138 | __DSB(); | |
139 | __ISB(); | |
140 | } | |
141 | ||
142 | static __INLINE void enableMPUWithDefaultMemoryMap(void) | |
143 | { | |
144 | if (isMPUNotPresent()) | |
145 | return; | |
146 | ||
147 | MPU->CTRL = MPU_CTRL_ENABLE | MPU_CTRL_PRIVDEFENA; | |
65eee97a AG |
148 | __DSB(); |
149 | __ISB(); | |
150 | } | |
151 | ||
152 | static __INLINE int prepareToAccessMPURegion(uint32_t regionNumber) | |
153 | { | |
154 | if (!isMPURegionNumberValid(regionNumber)) | |
155 | return 0; | |
156 | ||
157 | MPU->RNR = regionNumber; | |
158 | return 1; | |
159 | } | |
160 | ||
161 | static __INLINE uint32_t getCurrentMPURegionNumber(void) | |
162 | { | |
163 | return MPU->RNR; | |
164 | } | |
165 | ||
166 | static __INLINE void setMPURegionAddress(uint32_t address) | |
167 | { | |
168 | if (isMPUNotPresent()) | |
169 | return; | |
170 | ||
ddf5038e | 171 | MPU->RBAR = address & MPU_RBAR_ADDR_MASK; |
65eee97a AG |
172 | } |
173 | ||
174 | static __INLINE uint32_t getMPURegionAddress(void) | |
175 | { | |
176 | if (isMPUNotPresent()) | |
177 | return 0; | |
178 | ||
ddf5038e | 179 | return MPU->RBAR & MPU_RBAR_ADDR_MASK; |
65eee97a AG |
180 | } |
181 | ||
182 | static __INLINE void setMPURegionAttributeAndSize(uint32_t attributeAndSize) | |
183 | { | |
184 | if (isMPUNotPresent()) | |
185 | return; | |
186 | ||
187 | MPU->RASR = attributeAndSize; | |
188 | } | |
189 | ||
190 | static __INLINE uint32_t getMPURegionAttributeAndSize(void) | |
191 | { | |
192 | if (isMPUNotPresent()) | |
193 | return 0; | |
194 | ||
195 | return MPU->RASR; | |
196 | } | |
197 | ||
198 | #endif /* _MPU_H_ */ |