diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-03-18 02:01:29 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-03-18 18:49:10 +0100 |
| commit | 0cd19a58c3dcaa689ba57da80c02af75866f7e09 (patch) | |
| tree | fc27bb5c7dad30e401aa0ef9df28be9e3aacc1f5 /embassy-extras | |
| parent | 4b2fdd450e70270f346f302829fa493a67fe3ce1 (diff) | |
Remove free() from PeripheralMutex and all nrf drivers.
Diffstat (limited to 'embassy-extras')
| -rw-r--r-- | embassy-extras/src/peripheral.rs | 77 |
1 files changed, 20 insertions, 57 deletions
diff --git a/embassy-extras/src/peripheral.rs b/embassy-extras/src/peripheral.rs index e9357969d..aa23bc978 100644 --- a/embassy-extras/src/peripheral.rs +++ b/embassy-extras/src/peripheral.rs | |||
| @@ -1,30 +1,20 @@ | |||
| 1 | use core::cell::UnsafeCell; | 1 | use core::cell::UnsafeCell; |
| 2 | use core::marker::{PhantomData, PhantomPinned}; | 2 | use core::marker::{PhantomData, PhantomPinned}; |
| 3 | use core::mem::MaybeUninit; | ||
| 4 | use core::pin::Pin; | 3 | use core::pin::Pin; |
| 5 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 6 | 5 | ||
| 7 | use embassy::interrupt::{Interrupt, InterruptExt}; | 6 | use embassy::interrupt::{Interrupt, InterruptExt}; |
| 8 | 7 | ||
| 9 | use crate::fmt::assert; | ||
| 10 | |||
| 11 | pub trait PeripheralState { | 8 | pub trait PeripheralState { |
| 12 | type Interrupt: Interrupt; | 9 | type Interrupt: Interrupt; |
| 13 | fn on_interrupt(&mut self); | 10 | fn on_interrupt(&mut self); |
| 14 | } | 11 | } |
| 15 | 12 | ||
| 16 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | ||
| 17 | enum Life { | ||
| 18 | Ready, | ||
| 19 | Created, | ||
| 20 | Freed, | ||
| 21 | } | ||
| 22 | |||
| 23 | pub struct PeripheralMutex<S: PeripheralState> { | 13 | pub struct PeripheralMutex<S: PeripheralState> { |
| 24 | life: Life, | 14 | state: UnsafeCell<S>, |
| 25 | 15 | ||
| 26 | state: MaybeUninit<UnsafeCell<S>>, // Init if life != Freed | 16 | irq_setup_done: bool, |
| 27 | irq: MaybeUninit<S::Interrupt>, // Init if life != Freed | 17 | irq: S::Interrupt, |
| 28 | 18 | ||
| 29 | _not_send: PhantomData<*mut ()>, | 19 | _not_send: PhantomData<*mut ()>, |
| 30 | _pinned: PhantomPinned, | 20 | _pinned: PhantomPinned, |
| @@ -33,9 +23,10 @@ pub struct PeripheralMutex<S: PeripheralState> { | |||
| 33 | impl<S: PeripheralState> PeripheralMutex<S> { | 23 | impl<S: PeripheralState> PeripheralMutex<S> { |
| 34 | pub fn new(state: S, irq: S::Interrupt) -> Self { | 24 | pub fn new(state: S, irq: S::Interrupt) -> Self { |
| 35 | Self { | 25 | Self { |
| 36 | life: Life::Created, | 26 | irq, |
| 37 | state: MaybeUninit::new(UnsafeCell::new(state)), | 27 | irq_setup_done: false, |
| 38 | irq: MaybeUninit::new(irq), | 28 | |
| 29 | state: UnsafeCell::new(state), | ||
| 39 | _not_send: PhantomData, | 30 | _not_send: PhantomData, |
| 40 | _pinned: PhantomPinned, | 31 | _pinned: PhantomPinned, |
| 41 | } | 32 | } |
| @@ -43,77 +34,49 @@ impl<S: PeripheralState> PeripheralMutex<S> { | |||
| 43 | 34 | ||
| 44 | /// safety: self must be pinned. | 35 | /// safety: self must be pinned. |
| 45 | unsafe fn setup(&mut self) { | 36 | unsafe fn setup(&mut self) { |
| 46 | assert!(self.life == Life::Created); | 37 | self.irq.disable(); |
| 47 | |||
| 48 | let irq = &mut *self.irq.as_mut_ptr(); | ||
| 49 | irq.disable(); | ||
| 50 | compiler_fence(Ordering::SeqCst); | 38 | compiler_fence(Ordering::SeqCst); |
| 51 | 39 | ||
| 52 | irq.set_handler(|p| { | 40 | self.irq.set_handler(|p| { |
| 53 | // Safety: it's OK to get a &mut to the state, since | 41 | // Safety: it's OK to get a &mut to the state, since |
| 54 | // - We're in the IRQ, no one else can't preempt us | 42 | // - We're in the IRQ, no one else can't preempt us |
| 55 | // - We can't have preempted a with() call because the irq is disabled during it. | 43 | // - We can't have preempted a with() call because the irq is disabled during it. |
| 56 | let state = &mut *(p as *mut S); | 44 | let state = &mut *(p as *mut S); |
| 57 | state.on_interrupt(); | 45 | state.on_interrupt(); |
| 58 | }); | 46 | }); |
| 59 | irq.set_handler_context(self.state.as_mut_ptr() as *mut ()); | 47 | self.irq |
| 48 | .set_handler_context((&mut self.state) as *mut _ as *mut ()); | ||
| 60 | 49 | ||
| 61 | compiler_fence(Ordering::SeqCst); | 50 | compiler_fence(Ordering::SeqCst); |
| 62 | irq.enable(); | 51 | self.irq.enable(); |
| 63 | 52 | ||
| 64 | self.life = Life::Ready; | 53 | self.irq_setup_done = true; |
| 65 | } | 54 | } |
| 66 | 55 | ||
| 67 | pub fn with<R>(self: Pin<&mut Self>, f: impl FnOnce(&mut S, &mut S::Interrupt) -> R) -> R { | 56 | pub fn with<R>(self: Pin<&mut Self>, f: impl FnOnce(&mut S, &mut S::Interrupt) -> R) -> R { |
| 68 | let this = unsafe { self.get_unchecked_mut() }; | 57 | let this = unsafe { self.get_unchecked_mut() }; |
| 69 | if this.life != Life::Ready { | 58 | if !this.irq_setup_done { |
| 70 | unsafe { this.setup() } | 59 | unsafe { this.setup() } |
| 71 | } | 60 | } |
| 72 | 61 | ||
| 73 | let irq = unsafe { &mut *this.irq.as_mut_ptr() }; | 62 | this.irq.disable(); |
| 74 | |||
| 75 | irq.disable(); | ||
| 76 | compiler_fence(Ordering::SeqCst); | 63 | compiler_fence(Ordering::SeqCst); |
| 77 | 64 | ||
| 78 | // Safety: it's OK to get a &mut to the state, since the irq is disabled. | 65 | // Safety: it's OK to get a &mut to the state, since the irq is disabled. |
| 79 | let state = unsafe { &mut *(*this.state.as_ptr()).get() }; | 66 | let state = unsafe { &mut *this.state.get() }; |
| 80 | 67 | ||
| 81 | let r = f(state, irq); | 68 | let r = f(state, &mut this.irq); |
| 82 | 69 | ||
| 83 | compiler_fence(Ordering::SeqCst); | 70 | compiler_fence(Ordering::SeqCst); |
| 84 | irq.enable(); | 71 | this.irq.enable(); |
| 85 | 72 | ||
| 86 | r | 73 | r |
| 87 | } | 74 | } |
| 88 | |||
| 89 | pub fn try_free(self: Pin<&mut Self>) -> Option<(S, S::Interrupt)> { | ||
| 90 | let this = unsafe { self.get_unchecked_mut() }; | ||
| 91 | |||
| 92 | if this.life != Life::Freed { | ||
| 93 | return None; | ||
| 94 | } | ||
| 95 | |||
| 96 | unsafe { &mut *this.irq.as_mut_ptr() }.disable(); | ||
| 97 | compiler_fence(Ordering::SeqCst); | ||
| 98 | |||
| 99 | this.life = Life::Freed; | ||
| 100 | |||
| 101 | let state = unsafe { this.state.as_ptr().read().into_inner() }; | ||
| 102 | let irq = unsafe { this.irq.as_ptr().read() }; | ||
| 103 | Some((state, irq)) | ||
| 104 | } | ||
| 105 | |||
| 106 | pub fn free(self: Pin<&mut Self>) -> (S, S::Interrupt) { | ||
| 107 | unwrap!(self.try_free()) | ||
| 108 | } | ||
| 109 | } | 75 | } |
| 110 | 76 | ||
| 111 | impl<S: PeripheralState> Drop for PeripheralMutex<S> { | 77 | impl<S: PeripheralState> Drop for PeripheralMutex<S> { |
| 112 | fn drop(&mut self) { | 78 | fn drop(&mut self) { |
| 113 | if self.life != Life::Freed { | 79 | self.irq.disable(); |
| 114 | let irq = unsafe { &mut *self.irq.as_mut_ptr() }; | 80 | self.irq.remove_handler(); |
| 115 | irq.disable(); | ||
| 116 | irq.remove_handler(); | ||
| 117 | } | ||
| 118 | } | 81 | } |
| 119 | } | 82 | } |
