cortex_m/peripheral/
sau.rs1use crate::interrupt;
11use crate::peripheral::SAU;
12use bitfield::bitfield;
13use volatile_register::{RO, RW};
14
15#[repr(C)]
17pub struct RegisterBlock {
18 pub ctrl: RW<Ctrl>,
20 pub _type: RO<Type>,
22 pub rnr: RW<Rnr>,
24 pub rbar: RW<Rbar>,
26 pub rlar: RW<Rlar>,
28 pub sfsr: RO<Sfsr>,
30 pub sfar: RO<Sfar>,
32}
33
34bitfield! {
35 #[repr(C)]
37 #[derive(Copy, Clone)]
38 pub struct Ctrl(u32);
39 get_enable, set_enable: 0;
40 get_allns, set_allns: 1;
41}
42
43bitfield! {
44 #[repr(C)]
46 #[derive(Copy, Clone)]
47 pub struct Type(u32);
48 u8;
49 sregion, _: 7, 0;
50}
51
52bitfield! {
53 #[repr(C)]
55 #[derive(Copy, Clone)]
56 pub struct Rnr(u32);
57 u8;
58 get_region, set_region: 7, 0;
59}
60
61bitfield! {
62 #[repr(C)]
64 #[derive(Copy, Clone)]
65 pub struct Rbar(u32);
66 u32;
67 get_baddr, set_baddr: 31, 5;
68}
69
70bitfield! {
71 #[repr(C)]
73 #[derive(Copy, Clone)]
74 pub struct Rlar(u32);
75 u32;
76 get_laddr, set_laddr: 31, 5;
77 get_nsc, set_nsc: 1;
78 get_enable, set_enable: 0;
79}
80
81bitfield! {
82 #[repr(C)]
84 #[derive(Copy, Clone)]
85 pub struct Sfsr(u32);
86 invep, _: 0;
87 invis, _: 1;
88 inver, _: 2;
89 auviol, _: 3;
90 invtran, _: 4;
91 lsperr, _: 5;
92 sfarvalid, _: 6;
93 lserr, _: 7;
94}
95
96bitfield! {
97 #[repr(C)]
99 #[derive(Copy, Clone)]
100 pub struct Sfar(u32);
101 u32;
102 address, _: 31, 0;
103}
104
105#[derive(Debug)]
107pub enum SauRegionAttribute {
108 Secure,
110 NonSecureCallable,
112 NonSecure,
114}
115
116#[derive(Debug)]
118pub struct SauRegion {
119 pub base_address: u32,
121 pub limit_address: u32,
123 pub attribute: SauRegionAttribute,
125}
126
127#[derive(Debug)]
129pub enum SauError {
130 RegionNumberTooBig,
133 WrongBaseAddress,
135 WrongLimitAddress,
137}
138
139impl SAU {
140 #[inline]
142 pub fn region_numbers(&self) -> u8 {
143 self._type.read().sregion()
144 }
145
146 #[inline]
148 pub fn enable(&mut self) {
149 unsafe {
150 self.ctrl.modify(|mut ctrl| {
151 ctrl.set_enable(true);
152 ctrl
153 });
154 }
155 }
156
157 #[inline]
164 pub fn set_region(&mut self, region_number: u8, region: SauRegion) -> Result<(), SauError> {
165 interrupt::free(|_| {
166 let base_address = region.base_address;
167 let limit_address = region.limit_address;
168 let attribute = region.attribute;
169
170 if region_number >= self.region_numbers() {
171 Err(SauError::RegionNumberTooBig)
172 } else if base_address & 0x1F != 0 {
173 Err(SauError::WrongBaseAddress)
174 } else if limit_address & 0x1F != 0x1F {
175 Err(SauError::WrongLimitAddress)
176 } else {
177 let mut rnr = Rnr(0);
180 let mut rbar = Rbar(0);
181 let mut rlar = Rlar(0);
182
183 rnr.set_region(region_number);
184 rbar.set_baddr(base_address >> 5);
185 rlar.set_laddr(limit_address >> 5);
186
187 match attribute {
188 SauRegionAttribute::Secure => {
189 rlar.set_nsc(false);
190 rlar.set_enable(false);
191 }
192 SauRegionAttribute::NonSecureCallable => {
193 rlar.set_nsc(true);
194 rlar.set_enable(true);
195 }
196 SauRegionAttribute::NonSecure => {
197 rlar.set_nsc(false);
198 rlar.set_enable(true);
199 }
200 }
201
202 unsafe {
203 self.rnr.write(rnr);
204 self.rbar.write(rbar);
205 self.rlar.write(rlar);
206 }
207
208 Ok(())
209 }
210 })
211 }
212
213 #[inline]
217 pub fn get_region(&mut self, region_number: u8) -> Result<SauRegion, SauError> {
218 interrupt::free(|_| {
219 if region_number >= self.region_numbers() {
220 Err(SauError::RegionNumberTooBig)
221 } else {
222 unsafe {
223 self.rnr.write(Rnr(region_number.into()));
224 }
225
226 let rbar = self.rbar.read();
227 let rlar = self.rlar.read();
228
229 let attribute = match (rlar.get_enable(), rlar.get_nsc()) {
230 (false, _) => SauRegionAttribute::Secure,
231 (true, false) => SauRegionAttribute::NonSecure,
232 (true, true) => SauRegionAttribute::NonSecureCallable,
233 };
234
235 Ok(SauRegion {
236 base_address: rbar.get_baddr() << 5,
237 limit_address: (rlar.get_laddr() << 5) | 0x1F,
238 attribute,
239 })
240 }
241 })
242 }
243}