bern_arch/cortex_m/
memory_protection.rs1use crate::arch::mpu::{self, Attributes, CachePolicy, Mpu, Permission, RegionNumber, Subregions};
4pub use crate::arch::mpu::{MemoryRegion, Size};
5use crate::arch::Arch;
6use crate::memory_protection::{Config, IMemoryProtection, Type};
7
8use bern_units::memory_size::{Byte, ExtByte};
9use cortex_m::asm;
10use cortex_m_rt::exception;
11
12impl IMemoryProtection for Arch {
13 type MemoryRegion = MemoryRegion;
14
15 fn enable_memory_protection() {
16 let mut mpu = unsafe { Mpu::take() };
17 mpu.enable();
18 }
19
20 fn disable_memory_protection() {
21 let mut mpu = unsafe { Mpu::take() };
22 mpu.disable();
23 }
24
25 fn enable_memory_region(region: u8, config: Config) {
26 let mut mpu = unsafe { Mpu::take() };
27
28 let memory_region = Self::prepare_memory_region(region, config);
29 mpu.set_region(&memory_region);
30 }
31
32 fn disable_memory_region(region: u8) {
33 let mut mpu = unsafe { Mpu::take() };
34 mpu.disable_region(region);
35 }
36
37 fn prepare_memory_region(region: u8, config: Config) -> Self::MemoryRegion {
38 let region_base_address =
39 Mpu::prepare_region_base_address(config.addr as u32, RegionNumber::Use(region));
40
41 let attributes = match config.memory {
42 Type::SramInternal => Attributes::Normal {
43 shareable: false,
44 cache_policy: (
45 CachePolicy::WriteBack { wa: true },
46 CachePolicy::WriteBack { wa: true },
47 ),
48 },
49 Type::SramExternal => Attributes::Normal {
50 shareable: false,
51 cache_policy: (
52 CachePolicy::WriteBack { wa: true },
53 CachePolicy::WriteBack { wa: true },
54 ),
55 },
56 Type::Flash => Attributes::Normal {
57 shareable: false,
58 cache_policy: (CachePolicy::WriteThrough, CachePolicy::WriteThrough),
59 },
60 Type::Peripheral => Attributes::Device { shareable: true },
61 };
62
63 let region_attributes = Mpu::prepare_region_attributes(
64 config.executable,
65 (
66 Permission::from(config.access.system),
67 Permission::from(config.access.user),
68 ),
69 attributes,
70 Subregions::ALL,
71 config.size.into(),
72 );
73
74 MemoryRegion {
75 region_base_address_reg: region_base_address,
76 region_attribute_size_reg: region_attributes,
77 }
78 }
79
80 fn prepare_unused_region(region: u8) -> Self::MemoryRegion {
81 MemoryRegion {
82 region_base_address_reg: mpu::MPU_REGION_VALID | region as u32,
83 region_attribute_size_reg: 0, }
85 }
86
87 fn apply_regions(memory_regions: &[MemoryRegion; 3]) {
88 let mut mpu = unsafe { Mpu::take() };
89
90 mpu.set_regions(memory_regions);
91 }
92
93 fn min_region_size() -> Byte {
94 32.B()
95 }
96
97 fn n_memory_regions() -> u8 {
99 8
100 }
101}
102
103extern "Rust" {
104 pub fn memory_protection_exception();
108}
109
110#[allow(non_snake_case)]
111#[no_mangle]
112pub unsafe extern "C" fn MemoryManagement() -> () {
113 unsafe {
114 memory_protection_exception();
115 }
116}
117
118#[repr(align(32))]
121pub struct A32;
122
123#[repr(align(64))]
124pub struct A64;
125
126#[repr(align(128))]
127pub struct A128;
128
129#[repr(align(256))]
130pub struct A256;
131
132#[repr(align(512))]
133pub struct A512;
134
135#[repr(align(1_024))]
136pub struct A1K;
137
138#[repr(align(2_048))]
139pub struct A2K;
140
141#[repr(align(4_096))]
142pub struct A4K;
143
144#[repr(align(8_192))]
145pub struct A8K;
146
147#[repr(align(16_384))]
148pub struct A16K;
149
150#[repr(align(32_768))]
151pub struct A32K;
152
153#[repr(align(65_536))]
154pub struct A64K;
155
156#[repr(align(131_072))]
157pub struct A128K;
158
159#[repr(align(262_144))]
160pub struct A256K;
161
162#[repr(align(524_288))]
163pub struct A512K;
164
165#[repr(align(1_048_576))]
166pub struct A1M;
167
168#[repr(align(2_097_152))]
169pub struct A2M;
170
171#[repr(align(4_194_304))]
172pub struct A4M;
173
174#[repr(align(8_388_608))]
175pub struct A8M;
176
177#[repr(align(16_777_216))]
178pub struct A16M;
179
180#[repr(align(33_554_432))]
181pub struct A32M;
182
183#[repr(align(67_108_864))]
184pub struct A64M;
185
186#[repr(align(134_217_728))]
187pub struct A128M;
188
189#[repr(align(268_435_456))]
190pub struct A256M;
191
192#[repr(align(536_870_912))]
193pub struct A512M;
194
195#[macro_export]
197macro_rules! alignment_from_size {
198 (32) => {
199 $crate::arch::memory_protection::A32
200 };
201 (64) => {
202 $crate::arch::memory_protection::A64
203 };
204 (128) => {
205 $crate::arch::memory_protection::A128
206 };
207 (256) => {
208 $crate::arch::memory_protection::A256
209 };
210 (512) => {
211 $crate::arch::memory_protection::A512
212 };
213 (1_024) => {
214 $crate::arch::memory_protection::A1K
215 };
216 (1024) => {
217 $crate::arch::memory_protection::A1K
218 };
219 (2_048) => {
220 $crate::arch::memory_protection::A2K
221 };
222 (2048) => {
223 $crate::arch::memory_protection::A2K
224 };
225 (4_096) => {
226 $crate::arch::memory_protection::A4K
227 };
228 (4096) => {
229 $crate::arch::memory_protection::A4K
230 };
231 (8_192) => {
232 $crate::arch::memory_protection::A8K
233 };
234 (8192) => {
235 $crate::arch::memory_protection::A8K
236 };
237 (16_384) => {
238 $crate::arch::memory_protection::A16K
239 };
240 (16384) => {
241 $crate::arch::memory_protection::A16K
242 };
243 (32_768) => {
244 $crate::arch::memory_protection::A32K
245 };
246 (32768) => {
247 $crate::arch::memory_protection::A32K
248 };
249 (65_536) => {
250 $crate::arch::memory_protection::A64K
251 };
252 (65536) => {
253 $crate::arch::memory_protection::A64K
254 };
255 (131_072) => {
256 $crate::arch::memory_protection::A128K
257 };
258 (131072) => {
259 $crate::arch::memory_protection::A128K
260 };
261 (262_144) => {
262 $crate::arch::memory_protection::A256K
263 };
264 (262144) => {
265 $crate::arch::memory_protection::A256K
266 };
267 (524_288) => {
268 $crate::arch::memory_protection::A512K
269 };
270 (524288) => {
271 $crate::arch::memory_protection::A512K
272 };
273 (1_048_576) => {
274 $crate::arch::memory_protection::A1M
275 };
276 (1048576) => {
277 $crate::arch::memory_protection::A1M
278 };
279 ($x:expr) => {
280 compile_error!(
281 "Size does not meet alignment requirements from the MPU. \
282 Compatible sizes are: 32B, 64B, 128B, 256B, 512B, 1KB, 2KB, 4KB, 16KB, \
283 32KB, 64KB, 128KB, 256KB, 512KB, 1M"
284 );
285 };
286}
287
288#[macro_export]
290macro_rules! size_from_raw {
291 (32) => {
292 $crate::arch::memory_protection::Size::S32
293 };
294 (64) => {
295 $crate::arch::memory_protection::Size::S64
296 };
297 (128) => {
298 $crate::arch::memory_protection::Size::S128
299 };
300 (256) => {
301 $crate::arch::memory_protection::Size::S256
302 };
303 (512) => {
304 $crate::arch::memory_protection::Size::S512
305 };
306 (1_024) => {
307 $crate::arch::memory_protection::Size::S1K
308 };
309 (1024) => {
310 $crate::arch::memory_protection::Size::S1K
311 };
312 (2_048) => {
313 $crate::arch::memory_protection::Size::S2K
314 };
315 (2048) => {
316 $crate::arch::memory_protection::Size::S2K
317 };
318 (4_096) => {
319 $crate::arch::memory_protection::Size::S4K
320 };
321 (4096) => {
322 $crate::arch::memory_protection::Size::S4K
323 };
324 (8_192) => {
325 $crate::arch::memory_protection::Size::S8K
326 };
327 (8192) => {
328 $crate::arch::memory_protection::Size::S8K
329 };
330 (16_384) => {
331 $crate::arch::memory_protection::Size::S16K
332 };
333 (16384) => {
334 $crate::arch::memory_protection::Size::S16K
335 };
336 (32_768) => {
337 $crate::arch::memory_protection::Size::S32K
338 };
339 (32768) => {
340 $crate::arch::memory_protection::Size::S32K
341 };
342 (65_536) => {
343 $crate::arch::memory_protection::Size::S64K
344 };
345 (65536) => {
346 $crate::arch::memory_protection::Size::S64K
347 };
348 (131_072) => {
349 $crate::arch::memory_protection::Size::S128K
350 };
351 (131072) => {
352 $crate::arch::memory_protection::Size::S128K
353 };
354 (262_144) => {
355 $crate::arch::memory_protection::Size::S256K
356 };
357 (262144) => {
358 $crate::arch::memory_protection::Size::S256K
359 };
360 (524_288) => {
361 $crate::arch::memory_protection::Size::S512K
362 };
363 (524288) => {
364 $crate::arch::memory_protection::Size::S512K
365 };
366 (1_048_576) => {
367 $crate::arch::memory_protection::Size::S1M
368 };
369 (1048576) => {
370 $crate::arch::memory_protection::Size::S1M
371 };
372 ($x:expr) => {
373 compile_error!(
374 "Size cannot be protected by MPU. \
375 Compatible sizes are: 32B, 64B, 128B, 256B, 512B, 1KB, 2KB, 4KB, 16KB, \
376 32KB, 64KB, 128KB, 256KB, 512KB, 1M"
377 );
378 };
379}