diff options
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 42 | ||||
| -rw-r--r-- | embassy-nrf/src/util/peripheral.rs | 118 |
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 |
| 7 | use core::cmp::min; | 7 | use core::cmp::min; |
| 8 | use core::marker::PhantomData; | ||
| 9 | use core::mem; | 8 | use core::mem; |
| 10 | use core::ops::Deref; | 9 | use core::ops::Deref; |
| 11 | use core::pin::Pin; | 10 | use core::pin::Pin; |
| @@ -20,7 +19,7 @@ use crate::hal::gpio::Port as GpioPort; | |||
| 20 | use crate::interrupt::{self, OwnedInterrupt}; | 19 | use crate::interrupt::{self, OwnedInterrupt}; |
| 21 | use crate::pac; | 20 | use crate::pac; |
| 22 | use crate::pac::uarte0; | 21 | use crate::pac::uarte0; |
| 23 | use crate::util::peripheral; | 22 | use crate::util::peripheral::{PeripheralMutex, PeripheralState}; |
| 24 | use crate::util::ring_buffer::RingBuffer; | 23 | use 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 |
| 51 | pub struct BufferedUarte<'a, T: Instance> { | 50 | pub 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 | ||
| 56 | impl<'a, T: Instance> Unpin for BufferedUarte<'a, T> {} | 54 | impl<'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> { | |||
| 158 | impl<'a, T: Instance> AsyncBufRead for BufferedUarte<'a, T> { | 157 | impl<'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 | ||
| 174 | impl<'a, T: Instance> AsyncWrite for BufferedUarte<'a, T> { | 175 | impl<'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 | ||
| 265 | impl<'a, T: Instance> peripheral::State for State<'a, T> { | 267 | impl<'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 | ||
| 417 | pub trait Instance: | 414 | pub 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 | ||
| 424 | impl Instance for pac::UARTE0 { | 418 | impl 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"))] |
| 434 | impl Instance for pac::UARTE1 { | 423 | impl 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 @@ | |||
| 1 | use core::mem; | 1 | use core::pin::Pin; |
| 2 | use core::mem::MaybeUninit; | ||
| 3 | use core::ptr; | ||
| 4 | use core::sync::atomic::{compiler_fence, Ordering}; | 2 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 5 | use core::{cell::UnsafeCell, marker::PhantomData}; | 3 | use core::{cell::UnsafeCell, marker::PhantomData}; |
| 6 | 4 | ||
| 5 | use crate::fmt::*; | ||
| 7 | use crate::interrupt::OwnedInterrupt; | 6 | use crate::interrupt::OwnedInterrupt; |
| 8 | 7 | ||
| 9 | pub struct Store<T>(MaybeUninit<UnsafeCell<T>>); | 8 | pub trait PeripheralState { |
| 10 | impl<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 | } | ||
| 35 | unsafe impl<T> Send for Store<T> {} | ||
| 36 | unsafe impl<T> Sync for Store<T> {} | ||
| 37 | |||
| 38 | pub 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 | ||
| 45 | pub struct Registration<P: State> { | 12 | pub 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 | ||
| 50 | impl<P: State> Registration<P> { | 17 | impl<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 | ||
| 102 | impl<P: State> Drop for Registration<P> { | 63 | impl<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 | } |
