|
1 |
| -use msp430_atomic::AtomicOperations; |
| 1 | +mod atomic { |
| 2 | + use portable_atomic::{AtomicU16, AtomicU8, Ordering}; |
2 | 3 |
|
3 |
| -impl<REG: Writable> Reg<REG> |
| 4 | + pub trait AtomicOperations { |
| 5 | + unsafe fn atomic_or(ptr: *mut Self, val: Self); |
| 6 | + unsafe fn atomic_and(ptr: *mut Self, val: Self); |
| 7 | + unsafe fn atomic_xor(ptr: *mut Self, val: Self); |
| 8 | + } |
| 9 | + |
| 10 | + macro_rules! impl_atomics { |
| 11 | + ($U:ty, $Atomic:ty) => { |
| 12 | + impl AtomicOperations for $U { |
| 13 | + unsafe fn atomic_or(ptr: *mut Self, val: Self) { |
| 14 | + (*(ptr as *const $Atomic)).fetch_or(val, Ordering::SeqCst); |
| 15 | + } |
| 16 | + |
| 17 | + unsafe fn atomic_and(ptr: *mut Self, val: Self) { |
| 18 | + (*(ptr as *const $Atomic)).fetch_and(val, Ordering::SeqCst); |
| 19 | + } |
| 20 | + |
| 21 | + unsafe fn atomic_xor(ptr: *mut Self, val: Self) { |
| 22 | + (*(ptr as *const $Atomic)).fetch_xor(val, Ordering::SeqCst); |
| 23 | + } |
| 24 | + } |
| 25 | + }; |
| 26 | + } |
| 27 | + impl_atomics!(u8, AtomicU8); |
| 28 | + impl_atomics!(u16, AtomicU16); |
| 29 | +} |
| 30 | +use atomic::AtomicOperations; |
| 31 | + |
| 32 | +impl<REG: Readable + Writable> Reg<REG> |
4 | 33 | where
|
5 |
| - Self: Readable + Writable, |
6 | 34 | REG::Ux: AtomicOperations + Default + core::ops::Not<Output = REG::Ux>,
|
7 | 35 | {
|
8 | 36 | /// Set high every bit in the register that was set in the write proxy. Leave other bits
|
9 | 37 | /// untouched. The write is done in a single atomic instruction.
|
| 38 | + /// |
| 39 | + /// # Safety |
| 40 | + /// |
| 41 | + /// The resultant bit pattern may not be valid for the register. |
10 | 42 | #[inline(always)]
|
11 | 43 | pub unsafe fn set_bits<F>(&self, f: F)
|
12 | 44 | where
|
13 |
| - F: FnOnce(&mut W<REG>) -> &mut W<REG>, |
| 45 | + F: FnOnce(&mut REG::Writer) -> &mut W<REG>, |
14 | 46 | {
|
15 |
| - let bits = f(&mut W { |
| 47 | + let bits = f(&mut REG::Writer::from(W { |
16 | 48 | bits: Default::default(),
|
17 | 49 | _reg: marker::PhantomData,
|
18 |
| - }) |
| 50 | + })) |
19 | 51 | .bits;
|
20 | 52 | REG::Ux::atomic_or(self.register.as_ptr(), bits);
|
21 | 53 | }
|
22 | 54 |
|
23 | 55 | /// Clear every bit in the register that was cleared in the write proxy. Leave other bits
|
24 | 56 | /// untouched. The write is done in a single atomic instruction.
|
| 57 | + /// |
| 58 | + /// # Safety |
| 59 | + /// |
| 60 | + /// The resultant bit pattern may not be valid for the register. |
25 | 61 | #[inline(always)]
|
26 | 62 | pub unsafe fn clear_bits<F>(&self, f: F)
|
27 | 63 | where
|
28 |
| - F: FnOnce(&mut W<REG>) -> &mut W<REG>, |
| 64 | + F: FnOnce(&mut REG::Writer) -> &mut W<REG>, |
29 | 65 | {
|
30 |
| - let bits = f(&mut W { |
| 66 | + let bits = f(&mut REG::Writer::from(W { |
31 | 67 | bits: !REG::Ux::default(),
|
32 | 68 | _reg: marker::PhantomData,
|
33 |
| - }) |
| 69 | + })) |
34 | 70 | .bits;
|
35 | 71 | REG::Ux::atomic_and(self.register.as_ptr(), bits);
|
36 | 72 | }
|
37 | 73 |
|
38 | 74 | /// Toggle every bit in the register that was set in the write proxy. Leave other bits
|
39 | 75 | /// untouched. The write is done in a single atomic instruction.
|
| 76 | + /// |
| 77 | + /// # Safety |
| 78 | + /// |
| 79 | + /// The resultant bit pattern may not be valid for the register. |
40 | 80 | #[inline(always)]
|
41 | 81 | pub unsafe fn toggle_bits<F>(&self, f: F)
|
42 | 82 | where
|
43 |
| - F: FnOnce(&mut W<REG>) -> &mut W<REG>, |
| 83 | + F: FnOnce(&mut REG::Writer) -> &mut W<REG>, |
44 | 84 | {
|
45 |
| - let bits = f(&mut W { |
| 85 | + let bits = f(&mut REG::Writer::from(W { |
46 | 86 | bits: Default::default(),
|
47 | 87 | _reg: marker::PhantomData,
|
48 |
| - }) |
| 88 | + })) |
49 | 89 | .bits;
|
50 | 90 | REG::Ux::atomic_xor(self.register.as_ptr(), bits);
|
51 | 91 | }
|
|
0 commit comments