diff options
Diffstat (limited to 'embassy-nrf/src/uarte.rs')
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 957fa4c71..9e485907c 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -2,12 +2,11 @@ | |||
| 2 | 2 | ||
| 3 | use core::future::Future; | 3 | use core::future::Future; |
| 4 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 5 | use core::pin::Pin; | 5 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 6 | use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; | ||
| 7 | use core::task::Poll; | 6 | use core::task::Poll; |
| 7 | use embassy::interrupt::InterruptExt; | ||
| 8 | use embassy::traits::uart::{Error, Read, Write}; | 8 | use embassy::traits::uart::{Error, Read, Write}; |
| 9 | use embassy::util::{AtomicWaker, OnDrop, PeripheralBorrow}; | 9 | use embassy::util::{AtomicWaker, OnDrop, PeripheralBorrow}; |
| 10 | use embassy_extras::peripheral_shared::{Peripheral, PeripheralState}; | ||
| 11 | use embassy_extras::unborrow; | 10 | use embassy_extras::unborrow; |
| 12 | use futures::future::poll_fn; | 11 | use futures::future::poll_fn; |
| 13 | 12 | ||
| @@ -38,16 +37,9 @@ impl Default for Config { | |||
| 38 | } | 37 | } |
| 39 | } | 38 | } |
| 40 | 39 | ||
| 41 | struct State<T: Instance> { | ||
| 42 | peri: T, | ||
| 43 | |||
| 44 | endrx_waker: AtomicWaker, | ||
| 45 | endtx_waker: AtomicWaker, | ||
| 46 | } | ||
| 47 | |||
| 48 | /// Interface to the UARTE peripheral | 40 | /// Interface to the UARTE peripheral |
| 49 | pub struct Uarte<'d, T: Instance> { | 41 | pub struct Uarte<'d, T: Instance> { |
| 50 | inner: Peripheral<State<T>>, | 42 | peri: T, |
| 51 | phantom: PhantomData<&'d mut T>, | 43 | phantom: PhantomData<&'d mut T>, |
| 52 | } | 44 | } |
| 53 | 45 | ||
| @@ -72,7 +64,7 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 72 | ) -> Self { | 64 | ) -> Self { |
| 73 | unborrow!(uarte, irq, rxd, txd, cts, rts); | 65 | unborrow!(uarte, irq, rxd, txd, cts, rts); |
| 74 | 66 | ||
| 75 | let r = uarte.regs(); | 67 | let r = T::regs(); |
| 76 | 68 | ||
| 77 | assert!(r.enable.read().enable().is_disabled()); | 69 | assert!(r.enable.read().enable().is_disabled()); |
| 78 | 70 | ||
| @@ -115,38 +107,29 @@ impl<'d, T: Instance> Uarte<'d, T> { | |||
| 115 | r.events_rxstarted.reset(); | 107 | r.events_rxstarted.reset(); |
| 116 | r.events_txstarted.reset(); | 108 | r.events_txstarted.reset(); |
| 117 | 109 | ||
| 110 | irq.set_handler(Self::on_interrupt); | ||
| 111 | irq.unpend(); | ||
| 112 | irq.enable(); | ||
| 113 | |||
| 118 | // Enable | 114 | // Enable |
| 119 | r.enable.write(|w| w.enable().enabled()); | 115 | r.enable.write(|w| w.enable().enabled()); |
| 120 | 116 | ||
| 121 | Self { | 117 | Self { |
| 122 | inner: Peripheral::new( | 118 | peri: uarte, |
| 123 | irq, | ||
| 124 | State { | ||
| 125 | peri: uarte, | ||
| 126 | endrx_waker: AtomicWaker::new(), | ||
| 127 | endtx_waker: AtomicWaker::new(), | ||
| 128 | }, | ||
| 129 | ), | ||
| 130 | phantom: PhantomData, | 119 | phantom: PhantomData, |
| 131 | } | 120 | } |
| 132 | } | 121 | } |
| 133 | 122 | ||
| 134 | fn inner(self: Pin<&mut Self>) -> Pin<&mut Peripheral<State<T>>> { | 123 | fn on_interrupt(_: *mut ()) { |
| 135 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | 124 | let r = T::regs(); |
| 136 | } | 125 | let s = T::state(); |
| 137 | } | ||
| 138 | |||
| 139 | impl<T: Instance> PeripheralState for State<T> { | ||
| 140 | type Interrupt = T::Interrupt; | ||
| 141 | 126 | ||
| 142 | fn on_interrupt(&self) { | ||
| 143 | let r = self.peri.regs(); | ||
| 144 | if r.events_endrx.read().bits() != 0 { | 127 | if r.events_endrx.read().bits() != 0 { |
| 145 | self.endrx_waker.wake(); | 128 | s.endrx_waker.wake(); |
| 146 | r.intenclr.write(|w| w.endrx().clear()); | 129 | r.intenclr.write(|w| w.endrx().clear()); |
| 147 | } | 130 | } |
| 148 | if r.events_endtx.read().bits() != 0 { | 131 | if r.events_endtx.read().bits() != 0 { |
| 149 | self.endtx_waker.wake(); | 132 | s.endtx_waker.wake(); |
| 150 | r.intenclr.write(|w| w.endtx().clear()); | 133 | r.intenclr.write(|w| w.endtx().clear()); |
| 151 | } | 134 | } |
| 152 | 135 | ||
| @@ -163,8 +146,7 @@ impl<'a, T: Instance> Drop for Uarte<'a, T> { | |||
| 163 | fn drop(&mut self) { | 146 | fn drop(&mut self) { |
| 164 | info!("uarte drop"); | 147 | info!("uarte drop"); |
| 165 | 148 | ||
| 166 | let s = unsafe { Pin::new_unchecked(&mut self.inner) }.state(); | 149 | let r = T::regs(); |
| 167 | let r = s.peri.regs(); | ||
| 168 | 150 | ||
| 169 | let did_stoprx = r.events_rxstarted.read().bits() != 0; | 151 | let did_stoprx = r.events_rxstarted.read().bits() != 0; |
| 170 | let did_stoptx = r.events_txstarted.read().bits() != 0; | 152 | let did_stoptx = r.events_txstarted.read().bits() != 0; |
| @@ -194,16 +176,14 @@ impl<'d, T: Instance> Read for Uarte<'d, T> { | |||
| 194 | #[rustfmt::skip] | 176 | #[rustfmt::skip] |
| 195 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; | 177 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; |
| 196 | 178 | ||
| 197 | fn read<'a>(mut self: Pin<&'a mut Self>, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { | 179 | fn read<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 198 | self.as_mut().inner().register_interrupt(); | ||
| 199 | |||
| 200 | async move { | 180 | async move { |
| 201 | let ptr = rx_buffer.as_ptr(); | 181 | let ptr = rx_buffer.as_ptr(); |
| 202 | let len = rx_buffer.len(); | 182 | let len = rx_buffer.len(); |
| 203 | assert!(len <= EASY_DMA_SIZE); | 183 | assert!(len <= EASY_DMA_SIZE); |
| 204 | 184 | ||
| 205 | let s = self.inner().state(); | 185 | let r = T::regs(); |
| 206 | let r = s.peri.regs(); | 186 | let s = T::state(); |
| 207 | 187 | ||
| 208 | let drop = OnDrop::new(move || { | 188 | let drop = OnDrop::new(move || { |
| 209 | info!("read drop: stopping"); | 189 | info!("read drop: stopping"); |
| @@ -250,17 +230,15 @@ impl<'d, T: Instance> Write for Uarte<'d, T> { | |||
| 250 | #[rustfmt::skip] | 230 | #[rustfmt::skip] |
| 251 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; | 231 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; |
| 252 | 232 | ||
| 253 | fn write<'a>(mut self: Pin<&'a mut Self>, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { | 233 | fn write<'a>(&'a mut self, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { |
| 254 | self.as_mut().inner().register_interrupt(); | ||
| 255 | |||
| 256 | async move { | 234 | async move { |
| 257 | let ptr = tx_buffer.as_ptr(); | 235 | let ptr = tx_buffer.as_ptr(); |
| 258 | let len = tx_buffer.len(); | 236 | let len = tx_buffer.len(); |
| 259 | assert!(len <= EASY_DMA_SIZE); | 237 | assert!(len <= EASY_DMA_SIZE); |
| 260 | // TODO: panic if buffer is not in SRAM | 238 | // TODO: panic if buffer is not in SRAM |
| 261 | 239 | ||
| 262 | let s = self.inner().state(); | 240 | let r = T::regs(); |
| 263 | let r = s.peri.regs(); | 241 | let s = T::state(); |
| 264 | 242 | ||
| 265 | let drop = OnDrop::new(move || { | 243 | let drop = OnDrop::new(move || { |
| 266 | info!("write drop: stopping"); | 244 | info!("write drop: stopping"); |
| @@ -306,8 +284,22 @@ impl<'d, T: Instance> Write for Uarte<'d, T> { | |||
| 306 | mod sealed { | 284 | mod sealed { |
| 307 | use super::*; | 285 | use super::*; |
| 308 | 286 | ||
| 287 | pub struct State { | ||
| 288 | pub endrx_waker: AtomicWaker, | ||
| 289 | pub endtx_waker: AtomicWaker, | ||
| 290 | } | ||
| 291 | impl State { | ||
| 292 | pub const fn new() -> Self { | ||
| 293 | Self { | ||
| 294 | endrx_waker: AtomicWaker::new(), | ||
| 295 | endtx_waker: AtomicWaker::new(), | ||
| 296 | } | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 309 | pub trait Instance { | 300 | pub trait Instance { |
| 310 | fn regs(&self) -> &pac::uarte0::RegisterBlock; | 301 | fn regs() -> &'static pac::uarte0::RegisterBlock; |
| 302 | fn state() -> &'static State; | ||
| 311 | } | 303 | } |
| 312 | } | 304 | } |
| 313 | 305 | ||
| @@ -318,9 +310,13 @@ pub trait Instance: sealed::Instance + 'static { | |||
| 318 | macro_rules! impl_instance { | 310 | macro_rules! impl_instance { |
| 319 | ($type:ident, $irq:ident) => { | 311 | ($type:ident, $irq:ident) => { |
| 320 | impl sealed::Instance for peripherals::$type { | 312 | impl sealed::Instance for peripherals::$type { |
| 321 | fn regs(&self) -> &pac::uarte0::RegisterBlock { | 313 | fn regs() -> &'static pac::uarte0::RegisterBlock { |
| 322 | unsafe { &*pac::$type::ptr() } | 314 | unsafe { &*pac::$type::ptr() } |
| 323 | } | 315 | } |
| 316 | fn state() -> &'static sealed::State { | ||
| 317 | static STATE: sealed::State = sealed::State::new(); | ||
| 318 | &STATE | ||
| 319 | } | ||
| 324 | } | 320 | } |
| 325 | impl Instance for peripherals::$type { | 321 | impl Instance for peripherals::$type { |
| 326 | type Interrupt = interrupt::$irq; | 322 | type Interrupt = interrupt::$irq; |
