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;