sam3_hal/write_protect.rs
1#[allow(clippy::wildcard_imports)]
2use crate::{pac::generic::FieldSpec, structure::*};
3
4pub trait WriteProtectKey {
5 /// `const` value to insert into the `WPKEY` field of the write protection register of a
6 /// peripheral with write protection capability.
7 const WPKEY: u32;
8}
9
10pub trait WpmrWpsrRegs {
11 type Wpmr: WpmrModify;
12 fn _wpmr(&self) -> &Self::Wpmr;
13 type Wpsr: WpsrRead;
14 fn _wpsr(&self) -> &Self::Wpsr;
15}
16
17pub trait WriteProtect: WriteProtectKey + WpmrWpsrRegs {
18 fn enable_writeprotect(&mut self) {
19 self._wpmr()
20 .write(|w| unsafe { w.wpkey().bits(Self::WPKEY).wpen().set_bit() })
21 }
22
23 fn disable_writeprotect(&mut self) {
24 self._wpmr()
25 .write(|w| unsafe { w.wpkey().bits(Self::WPKEY).wpen().clear_bit() });
26 }
27
28 fn writeprotect_enabled(&self) -> bool {
29 self._wpmr().read().wpen().bit()
30 }
31
32 /// Check if a peripheral with write protection capability is indicating a write protection
33 /// error.
34 fn writeprotect_error(&self) -> bool {
35 self._wpsr().read().wpvs().bit()
36 }
37
38 /// Check if the write protect status register of a peripheral with write protection capability
39 /// is indicating that a write protection error has occurred, and if it has, return the address
40 /// of the register write request that generated the error. Otherwise, `None` is returned.
41 fn writeprotect_error_addr(
42 &self,
43 ) -> Option<<<Self::Wpsr as WpsrRead>::R as WpsrReadFields>::Addr> {
44 if self.writeprotect_error() {
45 unsafe { Some(self.writeprotect_error_addr_unchecked()) }
46 } else {
47 None
48 }
49 }
50
51 /// Read the value from the `WPROTADDR` field of the write protection status register of a
52 /// peripheral with write protection capability without checking the `WPROTERR` flag.
53 ///
54 /// # Safety
55 ///
56 /// The value held in this register may be nonsensical if the `WPROTERR` flag is not indicating
57 /// that a write protection error has occured, thus it is recommended to use the
58 /// [`writeprotect_error_addr`](crate::write_protect::WriteProtect::writeprotect_error_addr)
59 /// method instead.
60 unsafe fn writeprotect_error_addr_unchecked(
61 &self,
62 ) -> <<Self::Wpsr as WpsrRead>::R as WpsrReadFields>::Addr {
63 self._wpsr().read().wpvsrc().bits()
64 }
65}
66
67pub trait WpmrRead {
68 type R: WpmrReadFields;
69 /// See [`Reg::read`](crate::pac::generic::Reg::read)
70 fn read(&self) -> Self::R;
71}
72
73pub trait WpmrReadFields {
74 type Wpen: BRead;
75 fn wpen(&self) -> Self::Wpen;
76 type Wpkey: FRead<u32>;
77 fn wpkey(&self) -> Self::Wpkey;
78}
79
80pub trait WpmrWrite {
81 /// See [`Reg::reset`](crate::pac::generic::Reg::reset).
82 fn reset(&self);
83 type W: WpmrWriteFields;
84 /// See [`Reg::write`](crate::pac::generic::Reg::write).
85 fn write<F>(&self, f: F)
86 where
87 F: FnOnce(&mut Self::W) -> &mut Self::W;
88}
89
90pub trait WpmrWriteWithZero {
91 type W: WpmrWriteFields;
92 #[allow(clippy::missing_safety_doc)]
93 /// See [`Reg::write_with_zero`](crate::pac::generic::Reg::write_with_zero).
94 unsafe fn write_with_zero<F>(&self, f: F)
95 where
96 F: FnOnce(&mut Self::W) -> &mut Self::W;
97}
98
99pub trait WpmrWriteFields: Sized {
100 type Wpen<'a>: BWrite<'a, Self>
101 where
102 Self: 'a + Sized;
103 fn wpen(&mut self) -> Self::Wpen<'_>;
104 type Wpkey<'a>: FWrite<'a, 24, u32, Self>
105 where
106 Self: 'a + Sized;
107 fn wpkey(&mut self) -> Self::Wpkey<'_>;
108}
109
110pub trait WpmrModify: WpmrRead + WpmrWrite + WpmrWriteWithZero {
111 /// See [`Reg::modify`](crate::pac::generic::Reg::modify).
112 fn modify<F>(&self, f: F)
113 where
114 for<'w> F: FnOnce(
115 &<Self as WpmrRead>::R,
116 &'w mut <Self as WpmrWrite>::W,
117 ) -> &'w mut <Self as WpmrWrite>::W;
118}
119
120pub trait WpsrRead {
121 type R: WpsrReadFields;
122 /// See [`Reg::read`](crate::pac::generic::Reg::read).
123 fn read(&self) -> Self::R;
124}
125
126pub trait WpsrReadFields {
127 type Wpvs: BRead;
128 fn wpvs(&self) -> Self::Wpvs;
129 type Addr: FieldSpec<Ux = Self::Addr>;
130 type Wpvsrc: FRead<Self::Addr>;
131 fn wpvsrc(&self) -> Self::Wpvsrc;
132}
133
134macro_rules! wpmr_wpsr_impl {
135 (
136 $ty:ty: {
137 key: $key:literal,
138 addr: $addr:ty,
139 wpvs: $wpvs:ident,
140 wpvsrc: $wpvsrc:ident,
141 }
142 ) => {
143 paste::paste! {
144 const _: () = {
145 use crate::{
146 pac::[<$ty:lower>]::{
147 wpmr::{self, WpenR, WpenW, WpkeyR, WpkeyW, WpmrSpec},
148 wpsr,
149 Wpmr,
150 Wpsr,
151 },
152 structure::FWrite,
153 write_protect::{
154 WriteProtectKey,
155 WpmrModify,
156 WpmrRead,
157 WpmrReadFields,
158 WpmrWpsrRegs,
159 WpmrWrite,
160 WpmrWriteFields,
161 WpmrWriteWithZero,
162 WpsrRead,
163 WpsrReadFields,
164 },
165 };
166
167 impl WriteProtectKey for $ty {
168 const WPKEY: u32 = $key;
169 }
170
171 impl WpmrWpsrRegs for $ty {
172 type Wpmr = Wpmr;
173 fn _wpmr(&self) -> &Self::Wpmr {
174 self.wpmr()
175 }
176 type Wpsr = Wpsr;
177 fn _wpsr(&self) -> &Self::Wpsr {
178 self.wpsr()
179 }
180 }
181
182 impl WpmrRead for Wpmr {
183 type R = wpmr::R;
184 fn read(&self) -> Self::R {
185 self.read()
186 }
187 }
188
189 impl WpmrReadFields for wpmr::R {
190 type Wpen = WpenR;
191 fn wpen(&self) -> Self::Wpen {
192 self.wpen()
193 }
194 type Wpkey = WpkeyR;
195 fn wpkey(&self) -> Self::Wpkey {
196 self.wpkey()
197 }
198 }
199
200 impl WpmrWrite for Wpmr {
201 fn reset(&self) {
202 self.reset()
203 }
204 type W = wpmr::W;
205 fn write<F>(&self, f: F)
206 where
207 F: FnOnce(&mut Self::W) -> &mut Self::W
208 {
209 self.write(f)
210 }
211 }
212
213 impl WpmrWriteWithZero for Wpmr {
214 type W = wpmr::W;
215 unsafe fn write_with_zero<F>(&self, f: F)
216 where
217 F: FnOnce(&mut Self::W) -> &mut Self::W,
218 {
219 self.write_with_zero(f)
220 }
221 }
222
223 impl WpmrWriteFields for wpmr::W {
224 type Wpen<'a> = WpenW<'a, WpmrSpec>;
225 fn wpen(&mut self) -> Self::Wpen<'_> {
226 self.wpen()
227 }
228 type Wpkey<'a> = WpkeyW<'a, WpmrSpec>;
229 fn wpkey(&mut self) -> Self::Wpkey<'_> {
230 self.wpkey()
231 }
232 }
233
234 crate::structure::bwrite_impl! {
235 ty: $ty,
236 reg: Wpmr,
237 }
238
239 impl<'a> FWrite<'a, 24, u32, wpmr::W> for WpkeyW<'a, WpmrSpec> {
240 const WIDTH: u8 = Self::WIDTH;
241 fn width(&self) -> u8 {
242 self.width()
243 }
244 fn offset(&self) -> u8 {
245 self.offset()
246 }
247 unsafe fn bits(self, value: u32) -> &'a mut wpmr::W {
248 self.bits(value)
249 }
250 }
251
252 impl WpmrModify for Wpmr {
253 fn modify<F>(&self, f: F)
254 where
255 for<'w> F: FnOnce(
256 &<Self as WpmrRead>::R,
257 &'w mut <Self as WpmrWrite>::W,
258 ) -> &'w mut <Self as WpmrWrite>::W,
259 {
260 self.modify(f)
261 }
262 }
263
264 impl WpsrRead for Wpsr {
265 type R = wpsr::R;
266 fn read(&self) -> Self::R {
267 self.read()
268 }
269 }
270
271 impl WpsrReadFields for wpsr::R {
272 type Wpvs = wpsr::[<$wpvs R>];
273 fn wpvs(&self) -> Self::Wpvs {
274 self.[<$wpvs:lower>]()
275 }
276 type Addr = $addr;
277 type Wpvsrc = wpsr::[<$wpvsrc R>];
278 fn wpvsrc(&self) -> Self::Wpvsrc {
279 self.[<$wpvsrc:lower>]()
280 }
281 }
282 };
283 }
284 };
285}
286
287pub(crate) use wpmr_wpsr_impl;
288
289// macro_rules! wp_impl {
290// ($(
291// $(#[$fields:meta])+
292// $type:ty => $field:ident($err:ident, $addr:ident<$addrty:ty>): $key:literal
293// ),+$(,)?) => {$(
294// paste::paste! {
295// #[doc = "`" $type "` has write protection for the following registers:"]
296// #[doc = ""]
297// $(#[$fields])+
298// impl crate::write_protect::WriteProtect for $type {
299// const WPKEY: u32 = {
300// let [b0, b1, b2] = *$key;
301// u32::from_be_bytes([0, b0, b1, b2])
302// };
303//
304// type AddrType = $addrty;
305//
306// #[rustfmt::skip]
307// fn enable_writeprotect(&mut self) {
308// self.$field.wpmr().write(|wpmr| unsafe {
309// wpmr
310// .wpkey().bits(Self::WPKEY)
311// .wpen().set_bit()
312// });
313// }
314//
315// #[rustfmt::skip]
316// fn disable_writeprotect(&mut self) {
317// self.$field.wpmr().write(|wpmr| unsafe {
318// wpmr
319// .wpkey().bits(Self::WPKEY)
320// .wpen().clear_bit()
321// });
322// }
323//
324// fn writeprotect_enabled(&self) -> bool {
325// self.$field.wpmr().read().wpen().bit()
326// }
327//
328// fn writeprotect_error(&self) -> bool {
329// self.$field.wpsr().read().$err().bit()
330// }
331//
332// /// Read the value from the `WPROTADDR` field of the write protection status register of a
333// /// peripheral with write protection capability without checking the `WPROTERR` flag.
334// ///
335// /// # Safety
336// ///
337// /// The value held in this register may be nonsensical if the `WPROTERR` flag is not indicating
338// /// that a write protection error has occured, thus it is recommended to use the
339// /// [`writeprotect_error_addr`](crate::write_protect::WriteProtect::writeprotect_error_addr)
340// /// method instead.
341// unsafe fn writeprotect_error_addr_unchecked(&self) -> $addrty {
342// self.$field.wpsr().read().$addr().bits()
343// }
344// }
345// }
346// )+};
347// }
348//
349// pub(crate) use wp_impl;