aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-18 02:01:29 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-18 18:49:10 +0100
commit0cd19a58c3dcaa689ba57da80c02af75866f7e09 (patch)
treefc27bb5c7dad30e401aa0ef9df28be9e3aacc1f5
parent4b2fdd450e70270f346f302829fa493a67fe3ce1 (diff)
Remove free() from PeripheralMutex and all nrf drivers.
-rw-r--r--embassy-extras/src/peripheral.rs77
-rw-r--r--embassy-nrf/src/buffered_uarte.rs29
-rw-r--r--embassy-nrf/src/qspi.rs5
-rw-r--r--embassy-nrf/src/spim.rs5
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 @@
1use core::cell::UnsafeCell; 1use core::cell::UnsafeCell;
2use core::marker::{PhantomData, PhantomPinned}; 2use core::marker::{PhantomData, PhantomPinned};
3use core::mem::MaybeUninit;
4use core::pin::Pin; 3use core::pin::Pin;
5use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
6 5
7use embassy::interrupt::{Interrupt, InterruptExt}; 6use embassy::interrupt::{Interrupt, InterruptExt};
8 7
9use crate::fmt::assert;
10
11pub trait PeripheralState { 8pub 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)]
17enum Life {
18 Ready,
19 Created,
20 Freed,
21}
22
23pub struct PeripheralMutex<S: PeripheralState> { 13pub 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> {
33impl<S: PeripheralState> PeripheralMutex<S> { 23impl<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
111impl<S: PeripheralState> Drop for PeripheralMutex<S> { 77impl<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
218impl<'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
229impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> AsyncBufRead 206impl<'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
296impl<'a, U: Instance, T: TimerInstance, P1: ConfigurablePpi, P2: ConfigurablePpi> 273impl<'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
130impl<T: Instance> FullDuplex<u8> for Spim<T> { 125impl<T: Instance> FullDuplex<u8> for Spim<T> {