aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/buffered_uarte.rs42
-rw-r--r--embassy-nrf/src/util/peripheral.rs118
2 files changed, 52 insertions, 108 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index c67b6f166..dbdb6f514 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -5,7 +5,6 @@
5//! - nrf52832: Section 35 5//! - nrf52832: Section 35
6//! - nrf52840: Section 6.34 6//! - nrf52840: Section 6.34
7use core::cmp::min; 7use core::cmp::min;
8use core::marker::PhantomData;
9use core::mem; 8use core::mem;
10use core::ops::Deref; 9use core::ops::Deref;
11use core::pin::Pin; 10use core::pin::Pin;
@@ -20,7 +19,7 @@ use crate::hal::gpio::Port as GpioPort;
20use crate::interrupt::{self, OwnedInterrupt}; 19use crate::interrupt::{self, OwnedInterrupt};
21use crate::pac; 20use crate::pac;
22use crate::pac::uarte0; 21use crate::pac::uarte0;
23use crate::util::peripheral; 22use crate::util::peripheral::{PeripheralMutex, PeripheralState};
24use crate::util::ring_buffer::RingBuffer; 23use crate::util::ring_buffer::RingBuffer;
25 24
26// Re-export SVD variants to allow user to directly set values 25// Re-export SVD variants to allow user to directly set values
@@ -49,8 +48,7 @@ enum TxState {
49/// - nrf52832: Section 15.2 48/// - nrf52832: Section 15.2
50/// - nrf52840: Section 6.1.2 49/// - nrf52840: Section 6.1.2
51pub struct BufferedUarte<'a, T: Instance> { 50pub struct BufferedUarte<'a, T: Instance> {
52 reg: peripheral::Registration<State<'a, T>>, 51 inner: PeripheralMutex<T::Interrupt, State<'a, T>>,
53 wtf: PhantomData<&'a ()>,
54} 52}
55 53
56impl<'a, T: Instance> Unpin for BufferedUarte<'a, T> {} 54impl<'a, T: Instance> Unpin for BufferedUarte<'a, T> {}
@@ -126,10 +124,12 @@ impl<'a, T: Instance> BufferedUarte<'a, T> {
126 // Configure frequency 124 // Configure frequency
127 uarte.baudrate.write(|w| w.baudrate().variant(baudrate)); 125 uarte.baudrate.write(|w| w.baudrate().variant(baudrate));
128 126
127 // Disable the irq, let the Registration enable it when everything is set up.
128 irq.disable();
129 irq.pend(); 129 irq.pend();
130 130
131 BufferedUarte { 131 BufferedUarte {
132 reg: peripheral::Registration::new( 132 inner: PeripheralMutex::new(
133 irq, 133 irq,
134 State { 134 State {
135 inner: uarte, 135 inner: uarte,
@@ -143,7 +143,6 @@ impl<'a, T: Instance> BufferedUarte<'a, T> {
143 tx_waker: WakerRegistration::new(), 143 tx_waker: WakerRegistration::new(),
144 }, 144 },
145 ), 145 ),
146 wtf: PhantomData,
147 } 146 }
148 } 147 }
149} 148}
@@ -158,7 +157,8 @@ impl<'a, T: Instance> Drop for BufferedUarte<'a, T> {
158impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> { 157impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> {
159 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> { 158 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>> {
160 let this = unsafe { self.get_unchecked_mut() }; 159 let this = unsafe { self.get_unchecked_mut() };
161 this.reg.with(|state, _| { 160 let reg = unsafe { Pin::new_unchecked(&mut this.inner) };
161 reg.with(|_irq, state| {
162 let z: Poll<Result<&[u8]>> = state.poll_fill_buf(cx); 162 let z: Poll<Result<&[u8]>> = state.poll_fill_buf(cx);
163 let z: Poll<Result<&[u8]>> = unsafe { mem::transmute(z) }; 163 let z: Poll<Result<&[u8]>> = unsafe { mem::transmute(z) };
164 z 164 z
@@ -167,14 +167,16 @@ impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> {
167 167
168 fn consume(self: Pin<&mut Self>, amt: usize) { 168 fn consume(self: Pin<&mut Self>, amt: usize) {
169 let this = unsafe { self.get_unchecked_mut() }; 169 let this = unsafe { self.get_unchecked_mut() };
170 this.reg.with(|state, irq| state.consume(irq, amt)) 170 let reg = unsafe { Pin::new_unchecked(&mut this.inner) };
171 reg.with(|irq, state| state.consume(irq, amt))
171 } 172 }
172} 173}
173 174
174impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> { 175impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> {
175 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> { 176 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
176 let this = unsafe { self.get_unchecked_mut() }; 177 let this = unsafe { self.get_unchecked_mut() };
177 this.reg.with(|state, irq| state.poll_write(irq, cx, buf)) 178 let reg = unsafe { Pin::new_unchecked(&mut this.inner) };
179 reg.with(|irq, state| state.poll_write(irq, cx, buf))
178 } 180 }
179} 181}
180 182
@@ -262,12 +264,7 @@ impl<'a, T: Instance> State<'a, T> {
262 } 264 }
263} 265}
264 266
265impl<'a, T: Instance> peripheral::State for State<'a, T> { 267impl<'a, T: Instance> PeripheralState for State<'a, T> {
266 type Interrupt = T::Interrupt;
267 fn store<'b>() -> &'b peripheral::Store<Self> {
268 unsafe { mem::transmute(T::storage()) }
269 }
270
271 fn on_interrupt(&mut self) { 268 fn on_interrupt(&mut self) {
272 trace!("irq: start"); 269 trace!("irq: start");
273 let mut more_work = true; 270 let mut more_work = true;
@@ -414,28 +411,15 @@ mod private {
414 impl Sealed for crate::pac::UARTE1 {} 411 impl Sealed for crate::pac::UARTE1 {}
415} 412}
416 413
417pub trait Instance: 414pub trait Instance: Deref<Target = uarte0::RegisterBlock> + private::Sealed {
418 Deref<Target = uarte0::RegisterBlock> + Sized + private::Sealed + 'static
419{
420 type Interrupt: OwnedInterrupt; 415 type Interrupt: OwnedInterrupt;
421 fn storage() -> &'static peripheral::Store<State<'static, Self>>;
422} 416}
423 417
424impl Instance for pac::UARTE0 { 418impl Instance for pac::UARTE0 {
425 type Interrupt = interrupt::UARTE0_UART0Interrupt; 419 type Interrupt = interrupt::UARTE0_UART0Interrupt;
426 fn storage() -> &'static peripheral::Store<State<'static, Self>> {
427 static STORAGE: peripheral::Store<State<'static, crate::pac::UARTE0>> =
428 peripheral::Store::uninit();
429 &STORAGE
430 }
431} 420}
432 421
433#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] 422#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
434impl Instance for pac::UARTE1 { 423impl Instance for pac::UARTE1 {
435 type Interrupt = interrupt::UARTE1Interrupt; 424 type Interrupt = interrupt::UARTE1Interrupt;
436 fn storage() -> &'static peripheral::Store<State<'static, Self>> {
437 static STORAGE: peripheral::Store<State<'static, crate::pac::UARTE1>> =
438 peripheral::Store::uninit();
439 &STORAGE
440 }
441} 425}
diff --git a/embassy-nrf/src/util/peripheral.rs b/embassy-nrf/src/util/peripheral.rs
index 9b3384e5d..07dc4a7bc 100644
--- a/embassy-nrf/src/util/peripheral.rs
+++ b/embassy-nrf/src/util/peripheral.rs
@@ -1,110 +1,70 @@
1use core::mem; 1use core::pin::Pin;
2use core::mem::MaybeUninit;
3use core::ptr;
4use core::sync::atomic::{compiler_fence, Ordering}; 2use core::sync::atomic::{compiler_fence, Ordering};
5use core::{cell::UnsafeCell, marker::PhantomData}; 3use core::{cell::UnsafeCell, marker::PhantomData};
6 4
5use crate::fmt::*;
7use crate::interrupt::OwnedInterrupt; 6use crate::interrupt::OwnedInterrupt;
8 7
9pub struct Store<T>(MaybeUninit<UnsafeCell<T>>); 8pub trait PeripheralState {
10impl<T> Store<T> {
11 pub const fn uninit() -> Self {
12 Self(MaybeUninit::uninit())
13 }
14
15 unsafe fn as_mut_ptr(&self) -> *mut T {
16 (*self.0.as_ptr()).get()
17 }
18
19 unsafe fn as_mut(&self) -> &mut T {
20 &mut *self.as_mut_ptr()
21 }
22
23 unsafe fn write(&self, val: T) {
24 ptr::write(self.as_mut_ptr(), val)
25 }
26
27 unsafe fn drop_in_place(&self) {
28 ptr::drop_in_place(self.as_mut_ptr())
29 }
30
31 unsafe fn read(&self) -> T {
32 ptr::read(self.as_mut_ptr())
33 }
34}
35unsafe impl<T> Send for Store<T> {}
36unsafe impl<T> Sync for Store<T> {}
37
38pub trait State: Sized {
39 type Interrupt: OwnedInterrupt;
40 fn on_interrupt(&mut self); 9 fn on_interrupt(&mut self);
41 #[doc(hidden)]
42 fn store<'a>() -> &'a Store<Self>;
43} 10}
44 11
45pub struct Registration<P: State> { 12pub struct PeripheralMutex<I: OwnedInterrupt, S: PeripheralState> {
46 irq: P::Interrupt, 13 inner: Option<(I, UnsafeCell<S>)>,
47 not_send: PhantomData<*mut P>, 14 not_send: PhantomData<*mut ()>,
48} 15}
49 16
50impl<P: State> Registration<P> { 17impl<I: OwnedInterrupt, S: PeripheralState> PeripheralMutex<I, S> {
51 pub fn new(irq: P::Interrupt, state: P) -> Self { 18 pub fn new(irq: I, state: S) -> Self {
52 // safety:
53 // - No other PeripheralRegistration can already exist because we have the owned interrupt
54 // - therefore, storage is uninitialized
55 // - therefore it's safe to overwrite it without dropping the previous contents
56 unsafe { P::store().write(state) }
57
58 irq.set_handler(
59 |_| {
60 // safety:
61 // - If a PeripheralRegistration instance exists, P::storage() is initialized.
62 // - It's OK to get a &mut to it since the irq is disabled.
63 unsafe { P::store().as_mut() }.on_interrupt();
64 },
65 core::ptr::null_mut(),
66 );
67
68 compiler_fence(Ordering::SeqCst);
69 irq.enable();
70
71 Self { 19 Self {
72 irq, 20 inner: Some((irq, UnsafeCell::new(state))),
73 not_send: PhantomData, 21 not_send: PhantomData,
74 } 22 }
75 } 23 }
76 24
77 pub fn with<R>(&mut self, f: impl FnOnce(&mut P, &mut P::Interrupt) -> R) -> R { 25 pub fn with<R>(self: Pin<&mut Self>, f: impl FnOnce(&mut I, &mut S) -> R) -> R {
78 self.irq.disable(); 26 let this = unsafe { self.get_unchecked_mut() };
27 let (irq, state) = unwrap!(this.inner.as_mut());
28
29 irq.disable();
79 compiler_fence(Ordering::SeqCst); 30 compiler_fence(Ordering::SeqCst);
80 31
81 // safety: 32 irq.set_handler(
82 // - If a PeripheralRegistration instance exists, P::storage() is initialized. 33 |p| {
83 // - It's OK to get a &mut to it since the irq is disabled. 34 // Safety: it's OK to get a &mut to the state, since
84 let r = f(unsafe { P::store().as_mut() }, &mut self.irq); 35 // - We're in the IRQ, no one else can't preempt us
36 // - We can't have preempted a with() call because the irq is disabled during it.
37 let state = unsafe { &mut *(p as *mut S) };
38 state.on_interrupt();
39 },
40 state.get() as *mut (),
41 );
42
43 // Safety: it's OK to get a &mut to the state, since the irq is disabled.
44 let state = unsafe { &mut *state.get() };
45
46 let r = f(irq, state);
85 47
86 compiler_fence(Ordering::SeqCst); 48 compiler_fence(Ordering::SeqCst);
87 self.irq.enable(); 49 irq.enable();
88 50
89 r 51 r
90 } 52 }
91 53
92 pub fn free(self) -> (P::Interrupt, P) { 54 pub fn free(self: Pin<&mut Self>) -> (I, S) {
93 let irq = unsafe { ptr::read(&self.irq) }; 55 let this = unsafe { self.get_unchecked_mut() };
56 let (irq, state) = unwrap!(this.inner.take());
94 irq.disable(); 57 irq.disable();
95 irq.remove_handler(); 58 irq.remove_handler();
96 mem::forget(self); 59 (irq, state.into_inner())
97 let storage = P::store();
98 (irq, unsafe { storage.read() })
99 } 60 }
100} 61}
101 62
102impl<P: State> Drop for Registration<P> { 63impl<I: OwnedInterrupt, S: PeripheralState> Drop for PeripheralMutex<I, S> {
103 fn drop(&mut self) { 64 fn drop(&mut self) {
104 self.irq.disable(); 65 if let Some((irq, state)) = &mut self.inner {
105 self.irq.remove_handler(); 66 irq.disable();
106 67 irq.remove_handler();
107 let storage = P::store(); 68 }
108 unsafe { storage.drop_in_place() };
109 } 69 }
110} 70}