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 | |
| parent | 4b2fdd450e70270f346f302829fa493a67fe3ce1 (diff) | |
Remove free() from PeripheralMutex and all nrf drivers.
| -rw-r--r-- | embassy-extras/src/peripheral.rs | 77 | ||||
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 29 | ||||
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 5 | ||||
| -rw-r--r-- | embassy-nrf/src/spim.rs | 5 |
4 files changed, 23 insertions, 93 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 | } |
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index b1366cd9e..9b4ec6061 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs | |||
| @@ -201,29 +201,6 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 201 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<'a, U, T, P1, P2>>> { | 201 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<'a, U, T, P1, P2>>> { |
| 202 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | 202 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } |
| 203 | } | 203 | } |
| 204 | |||
| 205 | pub fn free(self: Pin<&mut Self>) -> (U, T, P1, P2, U::Interrupt) { | ||
| 206 | let (mut state, irq) = self.inner().free(); | ||
| 207 | state.stop(); | ||
| 208 | ( | ||
| 209 | state.uarte, | ||
| 210 | state.timer, | ||
| 211 | state.ppi_channel_1, | ||
| 212 | state.ppi_channel_2, | ||
| 213 | irq, | ||
| 214 | ) | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> Drop | ||
| 219 | for BufferedUarte<'a, U, T, P1, P2> | ||
| 220 | { | ||
| 221 | fn drop(&mut self) { | ||
| 222 | let inner = unsafe { Pin::new_unchecked(&mut self.inner) }; | ||
| 223 | if let Some((mut state, _irq)) = inner.try_free() { | ||
| 224 | state.stop(); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | } | 204 | } |
| 228 | 205 | ||
| 229 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> AsyncBufRead | 206 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> AsyncBufRead |
| @@ -293,10 +270,10 @@ impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi | |||
| 293 | } | 270 | } |
| 294 | } | 271 | } |
| 295 | 272 | ||
| 296 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> | 273 | impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> Drop |
| 297 | State<'a, U, T, P1, P2> | 274 | for State<'a, U, T, P1, P2> |
| 298 | { | 275 | { |
| 299 | fn stop(&mut self) { | 276 | fn drop(&mut self) { |
| 300 | self.timer.tasks_stop.write(|w| unsafe { w.bits(1) }); | 277 | self.timer.tasks_stop.write(|w| unsafe { w.bits(1) }); |
| 301 | if let RxState::Receiving = self.rx_state { | 278 | if let RxState::Receiving = self.rx_state { |
| 302 | self.uarte.tasks_stoprx.write(|w| unsafe { w.bits(1) }); | 279 | self.uarte.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index f6e8175fa..026660cba 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -238,11 +238,6 @@ impl Qspi { | |||
| 238 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | 238 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | pub fn free(self: Pin<&mut Self>) -> (QSPI, interrupt::QSPI) { | ||
| 242 | let (state, irq) = self.inner().free(); | ||
| 243 | (state.inner, irq) | ||
| 244 | } | ||
| 245 | |||
| 246 | fn wait_ready<'a>(mut self: Pin<&'a mut Self>) -> impl Future<Output = ()> + 'a { | 241 | fn wait_ready<'a>(mut self: Pin<&'a mut Self>) -> impl Future<Output = ()> + 'a { |
| 247 | poll_fn(move |cx| { | 242 | poll_fn(move |cx| { |
| 248 | self.as_mut().inner().with(|s, _irq| { | 243 | self.as_mut().inner().with(|s, _irq| { |
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 61d415e02..4a3adeb3d 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs | |||
| @@ -120,11 +120,6 @@ impl<T: Instance> Spim<T> { | |||
| 120 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<T>>> { | 120 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State<T>>> { |
| 121 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | 121 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } |
| 122 | } | 122 | } |
| 123 | |||
| 124 | pub fn free(self: Pin<&mut Self>) -> (T, T::Interrupt) { | ||
| 125 | let (state, irq) = self.inner().free(); | ||
| 126 | (state.spim, irq) | ||
| 127 | } | ||
| 128 | } | 123 | } |
| 129 | 124 | ||
| 130 | impl<T: Instance> FullDuplex<u8> for Spim<T> { | 125 | impl<T: Instance> FullDuplex<u8> for Spim<T> { |
