diff options
| -rw-r--r-- | embassy-nrf-examples/src/bin/uart.rs | 56 | ||||
| -rw-r--r-- | embassy-nrf/src/uarte.rs | 427 | ||||
| -rw-r--r-- | embassy-traits/src/uart.rs | 34 | ||||
| -rw-r--r-- | embassy/src/util/mod.rs | 2 | ||||
| -rw-r--r-- | embassy/src/util/on_drop.rs | 24 |
5 files changed, 273 insertions, 270 deletions
diff --git a/embassy-nrf-examples/src/bin/uart.rs b/embassy-nrf-examples/src/bin/uart.rs index 0acd6fded..c39e70d53 100644 --- a/embassy-nrf-examples/src/bin/uart.rs +++ b/embassy-nrf-examples/src/bin/uart.rs | |||
| @@ -12,38 +12,26 @@ use cortex_m_rt::entry; | |||
| 12 | use defmt::panic; | 12 | use defmt::panic; |
| 13 | use embassy::executor::{task, Executor}; | 13 | use embassy::executor::{task, Executor}; |
| 14 | use embassy::time::{Duration, Timer}; | 14 | use embassy::time::{Duration, Timer}; |
| 15 | use embassy::traits::uart::Uart; | 15 | use embassy::traits::uart::{Read, Write}; |
| 16 | use embassy::util::Forever; | 16 | use embassy::util::Forever; |
| 17 | use embassy_nrf::{interrupt, pac, rtc, uarte}; | 17 | use embassy_nrf::{interrupt, pac, rtc, uarte, Peripherals}; |
| 18 | use futures::future::{select, Either}; | 18 | use futures::future::{select, Either}; |
| 19 | use futures::pin_mut; | ||
| 19 | use nrf52840_hal::clocks; | 20 | use nrf52840_hal::clocks; |
| 20 | use nrf52840_hal::gpio; | 21 | use nrf52840_hal::gpio; |
| 21 | 22 | ||
| 22 | #[task] | 23 | #[task] |
| 23 | async fn run(uart: pac::UARTE0, port: pac::P0) { | 24 | async fn run() { |
| 24 | // Init UART | 25 | let p = Peripherals::take().unwrap(); |
| 25 | let port0 = gpio::p0::Parts::new(port); | 26 | |
| 26 | 27 | let mut config = uarte::Config::default(); | |
| 27 | let pins = uarte::Pins { | 28 | config.parity = uarte::Parity::EXCLUDED; |
| 28 | rxd: port0.p0_08.into_floating_input().degrade(), | 29 | config.baudrate = uarte::Baudrate::BAUD115200; |
| 29 | txd: port0 | 30 | |
| 30 | .p0_06 | 31 | let irq = interrupt::take!(UARTE0_UART0); |
| 31 | .into_push_pull_output(gpio::Level::Low) | 32 | let uart = |
| 32 | .degrade(), | 33 | unsafe { uarte::Uarte::new(p.uarte0, irq, p.p0_08, p.p0_06, p.p0_07, p.p0_05, config) }; |
| 33 | cts: None, | 34 | pin_mut!(uart); |
| 34 | rts: None, | ||
| 35 | }; | ||
| 36 | |||
| 37 | // NOTE(unsafe): Safe becasue we do not use `mem::forget` anywhere. | ||
| 38 | let mut uart = unsafe { | ||
| 39 | uarte::Uarte::new( | ||
| 40 | uart, | ||
| 41 | interrupt::take!(UARTE0_UART0), | ||
| 42 | pins, | ||
| 43 | uarte::Parity::EXCLUDED, | ||
| 44 | uarte::Baudrate::BAUD115200, | ||
| 45 | ) | ||
| 46 | }; | ||
| 47 | 35 | ||
| 48 | info!("uarte initialized!"); | 36 | info!("uarte initialized!"); |
| 49 | 37 | ||
| @@ -51,19 +39,22 @@ async fn run(uart: pac::UARTE0, port: pac::P0) { | |||
| 51 | let mut buf = [0; 8]; | 39 | let mut buf = [0; 8]; |
| 52 | buf.copy_from_slice(b"Hello!\r\n"); | 40 | buf.copy_from_slice(b"Hello!\r\n"); |
| 53 | 41 | ||
| 54 | unwrap!(uart.send(&buf).await); | 42 | unwrap!(uart.as_mut().write(&buf).await); |
| 55 | info!("wrote hello in uart!"); | 43 | info!("wrote hello in uart!"); |
| 56 | 44 | ||
| 57 | loop { | 45 | loop { |
| 58 | let buf_len = buf.len(); | ||
| 59 | info!("reading..."); | 46 | info!("reading..."); |
| 47 | unwrap!(uart.as_mut().read(&mut buf).await); | ||
| 48 | info!("writing..."); | ||
| 49 | unwrap!(uart.as_mut().write(&buf).await); | ||
| 60 | 50 | ||
| 51 | /* | ||
| 61 | // `receive()` doesn't return until the buffer has been completely filled with | 52 | // `receive()` doesn't return until the buffer has been completely filled with |
| 62 | // incoming data, which in this case is 8 bytes. | 53 | // incoming data, which in this case is 8 bytes. |
| 63 | // | 54 | // |
| 64 | // This example shows how to use `select` to run an uart receive concurrently with a | 55 | // This example shows how to use `select` to run an uart receive concurrently with a |
| 65 | // 1 second timer, effectively adding a timeout to the receive operation. | 56 | // 1 second timer, effectively adding a timeout to the receive operation. |
| 66 | let recv_fut = uart.receive(&mut buf); | 57 | let recv_fut = uart.read(&mut buf); |
| 67 | let timer_fut = Timer::after(Duration::from_millis(1000)); | 58 | let timer_fut = Timer::after(Duration::from_millis(1000)); |
| 68 | let received_len = match select(recv_fut, timer_fut).await { | 59 | let received_len = match select(recv_fut, timer_fut).await { |
| 69 | // recv_fut completed first, so we've received `buf_len` bytes. | 60 | // recv_fut completed first, so we've received `buf_len` bytes. |
| @@ -81,8 +72,9 @@ async fn run(uart: pac::UARTE0, port: pac::P0) { | |||
| 81 | info!("read done, got {}", received); | 72 | info!("read done, got {}", received); |
| 82 | 73 | ||
| 83 | // Echo back received data | 74 | // Echo back received data |
| 84 | unwrap!(uart.send(received).await); | 75 | unwrap!(uart.write(received).await); |
| 85 | } | 76 | } |
| 77 | */ | ||
| 86 | } | 78 | } |
| 87 | } | 79 | } |
| 88 | 80 | ||
| @@ -110,9 +102,7 @@ fn main() -> ! { | |||
| 110 | let executor = EXECUTOR.put(Executor::new()); | 102 | let executor = EXECUTOR.put(Executor::new()); |
| 111 | executor.set_alarm(alarm); | 103 | executor.set_alarm(alarm); |
| 112 | 104 | ||
| 113 | let uarte0 = p.UARTE0; | ||
| 114 | let p0 = p.P0; | ||
| 115 | executor.run(|spawner| { | 105 | executor.run(|spawner| { |
| 116 | unwrap!(spawner.spawn(run(uarte0, p0))); | 106 | unwrap!(spawner.spawn(run())); |
| 117 | }); | 107 | }); |
| 118 | } | 108 | } |
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index b5e4da862..fc57f406b 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs | |||
| @@ -5,43 +5,49 @@ | |||
| 5 | //! are dropped correctly (e.g. not using `mem::forget()`). | 5 | //! are dropped correctly (e.g. not using `mem::forget()`). |
| 6 | 6 | ||
| 7 | use core::future::Future; | 7 | use core::future::Future; |
| 8 | use core::ops::Deref; | 8 | use core::marker::PhantomData; |
| 9 | use core::pin::Pin; | ||
| 9 | use core::sync::atomic::{compiler_fence, Ordering}; | 10 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 10 | use core::task::{Context, Poll}; | 11 | use core::task::Poll; |
| 11 | 12 | use embassy::traits::uart::{Error, Read, Write}; | |
| 12 | use embassy::interrupt::InterruptExt; | 13 | use embassy::util::{wake_on_interrupt, OnDrop, PeripheralBorrow, Signal}; |
| 13 | use embassy::util::Signal; | 14 | use embassy_extras::unborrow; |
| 15 | use futures::future::poll_fn; | ||
| 14 | 16 | ||
| 15 | use crate::fmt::{assert, *}; | 17 | use crate::fmt::{assert, *}; |
| 18 | use crate::gpio::Pin as GpioPin; | ||
| 16 | use crate::hal::pac; | 19 | use crate::hal::pac; |
| 17 | use crate::hal::prelude::*; | ||
| 18 | use crate::hal::target_constants::EASY_DMA_SIZE; | 20 | use crate::hal::target_constants::EASY_DMA_SIZE; |
| 19 | use crate::interrupt; | 21 | use crate::interrupt; |
| 20 | use crate::interrupt::Interrupt; | 22 | use crate::interrupt::Interrupt; |
| 23 | use crate::peripherals; | ||
| 21 | 24 | ||
| 22 | pub use crate::hal::uarte::Pins; | ||
| 23 | // Re-export SVD variants to allow user to directly set values. | 25 | // Re-export SVD variants to allow user to directly set values. |
| 24 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 26 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
| 25 | 27 | ||
| 26 | /// Interface to the UARTE peripheral | 28 | #[non_exhaustive] |
| 27 | pub struct Uarte<T> | 29 | pub struct Config { |
| 28 | where | 30 | pub parity: Parity, |
| 29 | T: Instance, | 31 | pub baudrate: Baudrate, |
| 30 | { | ||
| 31 | instance: T, | ||
| 32 | irq: T::Interrupt, | ||
| 33 | pins: Pins, | ||
| 34 | } | 32 | } |
| 35 | 33 | ||
| 36 | pub struct State { | 34 | impl Default for Config { |
| 37 | tx_done: Signal<()>, | 35 | fn default() -> Self { |
| 38 | rx_done: Signal<u32>, | 36 | Self { |
| 37 | parity: Parity::EXCLUDED, | ||
| 38 | baudrate: Baudrate::BAUD115200, | ||
| 39 | } | ||
| 40 | } | ||
| 39 | } | 41 | } |
| 40 | 42 | ||
| 41 | impl<T> Uarte<T> | 43 | /// Interface to the UARTE peripheral |
| 42 | where | 44 | pub struct Uarte<'d, T: Instance> { |
| 43 | T: Instance, | 45 | peri: T, |
| 44 | { | 46 | irq: T::Interrupt, |
| 47 | phantom: PhantomData<&'d mut T>, | ||
| 48 | } | ||
| 49 | |||
| 50 | impl<'d, T: Instance> Uarte<'d, T> { | ||
| 45 | /// Creates the interface to a UARTE instance. | 51 | /// Creates the interface to a UARTE instance. |
| 46 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. | 52 | /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. |
| 47 | /// | 53 | /// |
| @@ -52,85 +58,48 @@ where | |||
| 52 | /// or [`receive`](Uarte::receive). | 58 | /// or [`receive`](Uarte::receive). |
| 53 | #[allow(unused_unsafe)] | 59 | #[allow(unused_unsafe)] |
| 54 | pub unsafe fn new( | 60 | pub unsafe fn new( |
| 55 | uarte: T, | 61 | uarte: impl PeripheralBorrow<Target = T> + 'd, |
| 56 | irq: T::Interrupt, | 62 | irq: impl PeripheralBorrow<Target = T::Interrupt> + 'd, |
| 57 | mut pins: Pins, | 63 | rxd: impl PeripheralBorrow<Target = impl GpioPin> + 'd, |
| 58 | parity: Parity, | 64 | txd: impl PeripheralBorrow<Target = impl GpioPin> + 'd, |
| 59 | baudrate: Baudrate, | 65 | cts: impl PeripheralBorrow<Target = impl GpioPin> + 'd, |
| 66 | rts: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 67 | config: Config, | ||
| 60 | ) -> Self { | 68 | ) -> Self { |
| 61 | assert!(uarte.enable.read().enable().is_disabled()); | 69 | unborrow!(uarte, irq, rxd, txd, cts, rts); |
| 62 | |||
| 63 | uarte.psel.rxd.write(|w| { | ||
| 64 | unsafe { w.bits(pins.rxd.psel_bits()) }; | ||
| 65 | w.connect().connected() | ||
| 66 | }); | ||
| 67 | |||
| 68 | pins.txd.set_high().unwrap(); | ||
| 69 | uarte.psel.txd.write(|w| { | ||
| 70 | unsafe { w.bits(pins.txd.psel_bits()) }; | ||
| 71 | w.connect().connected() | ||
| 72 | }); | ||
| 73 | |||
| 74 | // Optional pins | ||
| 75 | uarte.psel.cts.write(|w| { | ||
| 76 | if let Some(ref pin) = pins.cts { | ||
| 77 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 78 | w.connect().connected() | ||
| 79 | } else { | ||
| 80 | w.connect().disconnected() | ||
| 81 | } | ||
| 82 | }); | ||
| 83 | |||
| 84 | uarte.psel.rts.write(|w| { | ||
| 85 | if let Some(ref pin) = pins.rts { | ||
| 86 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 87 | w.connect().connected() | ||
| 88 | } else { | ||
| 89 | w.connect().disconnected() | ||
| 90 | } | ||
| 91 | }); | ||
| 92 | 70 | ||
| 93 | uarte.baudrate.write(|w| w.baudrate().variant(baudrate)); | 71 | let r = uarte.regs(); |
| 94 | uarte.config.write(|w| w.parity().variant(parity)); | ||
| 95 | 72 | ||
| 96 | // Enable interrupts | 73 | assert!(r.enable.read().enable().is_disabled()); |
| 97 | uarte.events_endtx.reset(); | ||
| 98 | uarte.events_endrx.reset(); | ||
| 99 | uarte | ||
| 100 | .intenset | ||
| 101 | .write(|w| w.endtx().set().txstopped().set().endrx().set().rxto().set()); | ||
| 102 | 74 | ||
| 103 | // Register ISR | 75 | // TODO OptionalPin for RTS/CTS. |
| 104 | irq.set_handler(Self::on_irq); | ||
| 105 | irq.unpend(); | ||
| 106 | irq.enable(); | ||
| 107 | 76 | ||
| 108 | Uarte { | 77 | txd.set_high(); |
| 109 | instance: uarte, | 78 | rts.set_high(); |
| 110 | irq, | 79 | rxd.conf().write(|w| w.input().connect().drive().h0h1()); |
| 111 | pins, | 80 | txd.conf().write(|w| w.dir().output().drive().h0h1()); |
| 112 | } | 81 | //cts.conf().write(|w| w.input().connect().drive().h0h1()); |
| 113 | } | 82 | //rts.conf().write(|w| w.dir().output().drive().h0h1()); |
| 114 | 83 | ||
| 115 | pub fn free(self) -> (T, T::Interrupt, Pins) { | 84 | r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); |
| 116 | // Wait for the peripheral to be disabled from the ISR. | 85 | r.psel.txd.write(|w| unsafe { w.bits(txd.psel_bits()) }); |
| 117 | while self.instance.enable.read().enable().is_enabled() {} | 86 | //r.psel.cts.write(|w| unsafe { w.bits(cts.psel_bits()) }); |
| 118 | (self.instance, self.irq, self.pins) | 87 | //r.psel.rts.write(|w| unsafe { w.bits(rts.psel_bits()) }); |
| 119 | } | ||
| 120 | 88 | ||
| 121 | fn enable(&mut self) { | 89 | r.baudrate.write(|w| w.baudrate().variant(config.baudrate)); |
| 122 | trace!("enable"); | 90 | r.config.write(|w| w.parity().variant(config.parity)); |
| 123 | self.instance.enable.write(|w| w.enable().enabled()); | ||
| 124 | } | ||
| 125 | 91 | ||
| 126 | fn tx_started(&self) -> bool { | 92 | // Enable |
| 127 | self.instance.events_txstarted.read().bits() != 0 | 93 | r.enable.write(|w| w.enable().enabled()); |
| 128 | } | ||
| 129 | 94 | ||
| 130 | fn rx_started(&self) -> bool { | 95 | Self { |
| 131 | self.instance.events_rxstarted.read().bits() != 0 | 96 | peri: uarte, |
| 97 | irq, | ||
| 98 | phantom: PhantomData, | ||
| 99 | } | ||
| 132 | } | 100 | } |
| 133 | 101 | ||
| 102 | /* | ||
| 134 | unsafe fn on_irq(_ctx: *mut ()) { | 103 | unsafe fn on_irq(_ctx: *mut ()) { |
| 135 | let uarte = &*pac::UARTE0::ptr(); | 104 | let uarte = &*pac::UARTE0::ptr(); |
| 136 | 105 | ||
| @@ -186,54 +155,127 @@ where | |||
| 186 | uarte.enable.write(|w| w.enable().disabled()); | 155 | uarte.enable.write(|w| w.enable().disabled()); |
| 187 | } | 156 | } |
| 188 | } | 157 | } |
| 158 | */ | ||
| 189 | } | 159 | } |
| 190 | 160 | ||
| 191 | impl<T: Instance> embassy::traits::uart::Uart for Uarte<T> { | 161 | impl<'d, T: Instance> Read for Uarte<'d, T> { |
| 192 | type ReceiveFuture<'a> = ReceiveFuture<'a, T>; | 162 | #[rustfmt::skip] |
| 193 | type SendFuture<'a> = SendFuture<'a, T>; | 163 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; |
| 194 | 164 | ||
| 195 | /// Sends serial data. | 165 | fn read<'a>(self: Pin<&'a mut Self>, rx_buffer: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 196 | /// | 166 | async move { |
| 197 | /// `tx_buffer` is marked as static as per `embedded-dma` requirements. | 167 | let this = unsafe { self.get_unchecked_mut() }; |
| 198 | /// It it safe to use a buffer with a non static lifetime if memory is not | 168 | |
| 199 | /// reused until the future has finished. | 169 | let ptr = rx_buffer.as_ptr(); |
| 200 | fn send<'a>(&'a mut self, tx_buffer: &'a [u8]) -> SendFuture<'a, T> { | 170 | let len = rx_buffer.len(); |
| 201 | // Panic if TX is running which can happen if the user has called | 171 | assert!(len <= EASY_DMA_SIZE); |
| 202 | // `mem::forget()` on a previous future after polling it once. | 172 | |
| 203 | assert!(!self.tx_started()); | 173 | let r = this.peri.regs(); |
| 204 | 174 | ||
| 205 | T::state().tx_done.reset(); | 175 | let drop = OnDrop::new(move || { |
| 206 | 176 | info!("read drop: stopping"); | |
| 207 | SendFuture { | 177 | |
| 208 | uarte: self, | 178 | r.intenclr.write(|w| w.endrx().clear()); |
| 209 | buf: tx_buffer, | 179 | r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| 180 | |||
| 181 | // TX is stopped almost instantly, spinning is fine. | ||
| 182 | while r.events_endrx.read().bits() == 0 {} | ||
| 183 | info!("read drop: stopped"); | ||
| 184 | }); | ||
| 185 | |||
| 186 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 187 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 188 | |||
| 189 | r.events_endrx.reset(); | ||
| 190 | r.intenset.write(|w| w.endrx().set()); | ||
| 191 | |||
| 192 | compiler_fence(Ordering::SeqCst); | ||
| 193 | |||
| 194 | trace!("startrx"); | ||
| 195 | r.tasks_startrx.write(|w| unsafe { w.bits(1) }); | ||
| 196 | |||
| 197 | let irq = &mut this.irq; | ||
| 198 | poll_fn(|cx| { | ||
| 199 | if r.events_endrx.read().bits() != 0 { | ||
| 200 | r.events_endrx.reset(); | ||
| 201 | return Poll::Ready(()); | ||
| 202 | } | ||
| 203 | |||
| 204 | wake_on_interrupt(irq, cx.waker()); | ||
| 205 | |||
| 206 | Poll::Pending | ||
| 207 | }) | ||
| 208 | .await; | ||
| 209 | |||
| 210 | compiler_fence(Ordering::SeqCst); | ||
| 211 | r.intenclr.write(|w| w.endrx().clear()); | ||
| 212 | drop.defuse(); | ||
| 213 | |||
| 214 | Ok(()) | ||
| 210 | } | 215 | } |
| 211 | } | 216 | } |
| 217 | } | ||
| 212 | 218 | ||
| 213 | /// Receives serial data. | 219 | impl<'d, T: Instance> Write for Uarte<'d, T> { |
| 214 | /// | 220 | #[rustfmt::skip] |
| 215 | /// The future is pending until the buffer is completely filled. | 221 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; |
| 216 | /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel | 222 | |
| 217 | /// unfinished transfers after a timeout to prevent lockup when no more data | 223 | fn write<'a>(self: Pin<&'a mut Self>, tx_buffer: &'a [u8]) -> Self::WriteFuture<'a> { |
| 218 | /// is incoming. | 224 | async move { |
| 219 | /// | 225 | let this = unsafe { self.get_unchecked_mut() }; |
| 220 | /// `rx_buffer` is marked as static as per `embedded-dma` requirements. | 226 | |
| 221 | /// It it safe to use a buffer with a non static lifetime if memory is not | 227 | let ptr = tx_buffer.as_ptr(); |
| 222 | /// reused until the future has finished. | 228 | let len = tx_buffer.len(); |
| 223 | fn receive<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> ReceiveFuture<'a, T> { | 229 | assert!(len <= EASY_DMA_SIZE); |
| 224 | // Panic if RX is running which can happen if the user has called | 230 | // TODO: panic if buffer is not in SRAM |
| 225 | // `mem::forget()` on a previous future after polling it once. | 231 | |
| 226 | assert!(!self.rx_started()); | 232 | let r = this.peri.regs(); |
| 227 | 233 | ||
| 228 | T::state().rx_done.reset(); | 234 | let drop = OnDrop::new(move || { |
| 229 | 235 | info!("write drop: stopping"); | |
| 230 | ReceiveFuture { | 236 | |
| 231 | uarte: self, | 237 | r.intenclr.write(|w| w.endtx().clear()); |
| 232 | buf: rx_buffer, | 238 | r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); |
| 239 | |||
| 240 | // TX is stopped almost instantly, spinning is fine. | ||
| 241 | while r.events_endtx.read().bits() == 0 {} | ||
| 242 | info!("write drop: stopped"); | ||
| 243 | }); | ||
| 244 | |||
| 245 | r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 246 | r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 247 | |||
| 248 | r.events_endtx.reset(); | ||
| 249 | r.intenset.write(|w| w.endtx().set()); | ||
| 250 | |||
| 251 | compiler_fence(Ordering::SeqCst); | ||
| 252 | |||
| 253 | trace!("starttx"); | ||
| 254 | r.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 255 | |||
| 256 | let irq = &mut this.irq; | ||
| 257 | poll_fn(|cx| { | ||
| 258 | if r.events_endtx.read().bits() != 0 { | ||
| 259 | r.events_endtx.reset(); | ||
| 260 | return Poll::Ready(()); | ||
| 261 | } | ||
| 262 | |||
| 263 | wake_on_interrupt(irq, cx.waker()); | ||
| 264 | |||
| 265 | Poll::Pending | ||
| 266 | }) | ||
| 267 | .await; | ||
| 268 | |||
| 269 | compiler_fence(Ordering::SeqCst); | ||
| 270 | r.intenclr.write(|w| w.endtx().clear()); | ||
| 271 | drop.defuse(); | ||
| 272 | |||
| 273 | Ok(()) | ||
| 233 | } | 274 | } |
| 234 | } | 275 | } |
| 235 | } | 276 | } |
| 236 | 277 | ||
| 278 | /* | ||
| 237 | /// Future for the [`Uarte::send()`] method. | 279 | /// Future for the [`Uarte::send()`] method. |
| 238 | pub struct SendFuture<'a, T> | 280 | pub struct SendFuture<'a, T> |
| 239 | where | 281 | where |
| @@ -252,11 +294,8 @@ where | |||
| 252 | trace!("stoptx"); | 294 | trace!("stoptx"); |
| 253 | 295 | ||
| 254 | // Stop the transmitter to minimize the current consumption. | 296 | // Stop the transmitter to minimize the current consumption. |
| 255 | self.uarte.instance.events_txstarted.reset(); | 297 | self.uarte.peri.events_txstarted.reset(); |
| 256 | self.uarte | 298 | self.uarte.peri.tasks_stoptx.write(|w| unsafe { w.bits(1) }); |
| 257 | .instance | ||
| 258 | .tasks_stoptx | ||
| 259 | .write(|w| unsafe { w.bits(1) }); | ||
| 260 | 299 | ||
| 261 | // TX is stopped almost instantly, spinning is fine. | 300 | // TX is stopped almost instantly, spinning is fine. |
| 262 | while !T::state().tx_done.signaled() {} | 301 | while !T::state().tx_done.signaled() {} |
| @@ -264,46 +303,6 @@ where | |||
| 264 | } | 303 | } |
| 265 | } | 304 | } |
| 266 | 305 | ||
| 267 | impl<'a, T> Future for SendFuture<'a, T> | ||
| 268 | where | ||
| 269 | T: Instance, | ||
| 270 | { | ||
| 271 | type Output = Result<(), embassy::traits::uart::Error>; | ||
| 272 | |||
| 273 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
| 274 | let Self { uarte, buf } = unsafe { self.get_unchecked_mut() }; | ||
| 275 | |||
| 276 | if T::state().tx_done.poll_wait(cx).is_pending() { | ||
| 277 | let ptr = buf.as_ptr(); | ||
| 278 | let len = buf.len(); | ||
| 279 | assert!(len <= EASY_DMA_SIZE); | ||
| 280 | // TODO: panic if buffer is not in SRAM | ||
| 281 | |||
| 282 | uarte.enable(); | ||
| 283 | |||
| 284 | compiler_fence(Ordering::SeqCst); | ||
| 285 | uarte | ||
| 286 | .instance | ||
| 287 | .txd | ||
| 288 | .ptr | ||
| 289 | .write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 290 | uarte | ||
| 291 | .instance | ||
| 292 | .txd | ||
| 293 | .maxcnt | ||
| 294 | .write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 295 | |||
| 296 | trace!("starttx"); | ||
| 297 | uarte.instance.tasks_starttx.write(|w| unsafe { w.bits(1) }); | ||
| 298 | while !uarte.tx_started() {} // Make sure transmission has started | ||
| 299 | |||
| 300 | Poll::Pending | ||
| 301 | } else { | ||
| 302 | Poll::Ready(Ok(())) | ||
| 303 | } | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /// Future for the [`Uarte::receive()`] method. | 306 | /// Future for the [`Uarte::receive()`] method. |
| 308 | pub struct ReceiveFuture<'a, T> | 307 | pub struct ReceiveFuture<'a, T> |
| 309 | where | 308 | where |
| @@ -321,11 +320,8 @@ where | |||
| 321 | if self.uarte.rx_started() { | 320 | if self.uarte.rx_started() { |
| 322 | trace!("stoprx (drop)"); | 321 | trace!("stoprx (drop)"); |
| 323 | 322 | ||
| 324 | self.uarte.instance.events_rxstarted.reset(); | 323 | self.uarte.peri.events_rxstarted.reset(); |
| 325 | self.uarte | 324 | self.uarte.peri.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| 326 | .instance | ||
| 327 | .tasks_stoprx | ||
| 328 | .write(|w| unsafe { w.bits(1) }); | ||
| 329 | 325 | ||
| 330 | embassy_extras::low_power_wait_until(|| T::state().rx_done.signaled()) | 326 | embassy_extras::low_power_wait_until(|| T::state().rx_done.signaled()) |
| 331 | } | 327 | } |
| @@ -350,19 +346,11 @@ where | |||
| 350 | uarte.enable(); | 346 | uarte.enable(); |
| 351 | 347 | ||
| 352 | compiler_fence(Ordering::SeqCst); | 348 | compiler_fence(Ordering::SeqCst); |
| 353 | uarte | 349 | r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as u32) }); |
| 354 | .instance | 350 | r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); |
| 355 | .rxd | ||
| 356 | .ptr | ||
| 357 | .write(|w| unsafe { w.ptr().bits(ptr as u32) }); | ||
| 358 | uarte | ||
| 359 | .instance | ||
| 360 | .rxd | ||
| 361 | .maxcnt | ||
| 362 | .write(|w| unsafe { w.maxcnt().bits(len as _) }); | ||
| 363 | 351 | ||
| 364 | trace!("startrx"); | 352 | trace!("startrx"); |
| 365 | uarte.instance.tasks_startrx.write(|w| unsafe { w.bits(1) }); | 353 | uarte.peri.tasks_startrx.write(|w| unsafe { w.bits(1) }); |
| 366 | while !uarte.rx_started() {} // Make sure reception has started | 354 | while !uarte.rx_started() {} // Make sure reception has started |
| 367 | 355 | ||
| 368 | Poll::Pending | 356 | Poll::Pending |
| @@ -383,11 +371,8 @@ where | |||
| 383 | let len = if self.uarte.rx_started() { | 371 | let len = if self.uarte.rx_started() { |
| 384 | trace!("stoprx (stop)"); | 372 | trace!("stoprx (stop)"); |
| 385 | 373 | ||
| 386 | self.uarte.instance.events_rxstarted.reset(); | 374 | self.uarte.peri.events_rxstarted.reset(); |
| 387 | self.uarte | 375 | self.uarte.peri.tasks_stoprx.write(|w| unsafe { w.bits(1) }); |
| 388 | .instance | ||
| 389 | .tasks_stoprx | ||
| 390 | .write(|w| unsafe { w.bits(1) }); | ||
| 391 | T::state().rx_done.wait().await | 376 | T::state().rx_done.wait().await |
| 392 | } else { | 377 | } else { |
| 393 | // Transfer was stopped before it even started. No bytes were sent. | 378 | // Transfer was stopped before it even started. No bytes were sent. |
| @@ -396,45 +381,33 @@ where | |||
| 396 | len as _ | 381 | len as _ |
| 397 | } | 382 | } |
| 398 | } | 383 | } |
| 384 | */ | ||
| 385 | |||
| 386 | mod sealed { | ||
| 387 | use super::*; | ||
| 399 | 388 | ||
| 400 | mod private { | 389 | pub trait Instance { |
| 401 | pub trait Sealed {} | 390 | fn regs(&self) -> &pac::uarte0::RegisterBlock; |
| 391 | } | ||
| 402 | } | 392 | } |
| 403 | 393 | ||
| 404 | pub trait Instance: | 394 | pub trait Instance: sealed::Instance + 'static { |
| 405 | Deref<Target = pac::uarte0::RegisterBlock> + Sized + private::Sealed + 'static | ||
| 406 | { | ||
| 407 | type Interrupt: Interrupt; | 395 | type Interrupt: Interrupt; |
| 408 | |||
| 409 | #[doc(hidden)] | ||
| 410 | fn state() -> &'static State; | ||
| 411 | } | 396 | } |
| 412 | 397 | ||
| 413 | static UARTE0_STATE: State = State { | 398 | macro_rules! make_impl { |
| 414 | tx_done: Signal::new(), | 399 | ($type:ident, $irq:ident) => { |
| 415 | rx_done: Signal::new(), | 400 | impl sealed::Instance for peripherals::$type { |
| 416 | }; | 401 | fn regs(&self) -> &pac::uarte0::RegisterBlock { |
| 417 | impl private::Sealed for pac::UARTE0 {} | 402 | unsafe { &*pac::$type::ptr() } |
| 418 | impl Instance for pac::UARTE0 { | 403 | } |
| 419 | type Interrupt = interrupt::UARTE0_UART0; | 404 | } |
| 420 | 405 | impl Instance for peripherals::$type { | |
| 421 | fn state() -> &'static State { | 406 | type Interrupt = interrupt::$irq; |
| 422 | &UARTE0_STATE | 407 | } |
| 423 | } | 408 | }; |
| 424 | } | 409 | } |
| 425 | 410 | ||
| 411 | make_impl!(UARTE0, UARTE0_UART0); | ||
| 426 | #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] | 412 | #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] |
| 427 | static UARTE1_STATE: State = State { | 413 | make_impl!(UARTE1, UARTE1); |
| 428 | tx_done: Signal::new(), | ||
| 429 | rx_done: Signal::new(), | ||
| 430 | }; | ||
| 431 | #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] | ||
| 432 | impl private::Sealed for pac::UARTE1 {} | ||
| 433 | #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] | ||
| 434 | impl Instance for pac::UARTE1 { | ||
| 435 | type Interrupt = interrupt::UARTE1; | ||
| 436 | |||
| 437 | fn state() -> &'static State { | ||
| 438 | &UARTE1_STATE | ||
| 439 | } | ||
| 440 | } | ||
diff --git a/embassy-traits/src/uart.rs b/embassy-traits/src/uart.rs index 441747181..5676e3fca 100644 --- a/embassy-traits/src/uart.rs +++ b/embassy-traits/src/uart.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use core::future::Future; | 1 | use core::future::Future; |
| 2 | use core::pin::Pin; | ||
| 2 | 3 | ||
| 3 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | 4 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
| 4 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -7,18 +8,31 @@ pub enum Error { | |||
| 7 | Other, | 8 | Other, |
| 8 | } | 9 | } |
| 9 | 10 | ||
| 10 | pub trait Uart { | 11 | pub trait Read { |
| 11 | type ReceiveFuture<'a>: Future<Output = Result<(), Error>>; | 12 | type ReadFuture<'a>: Future<Output = Result<(), Error>> |
| 12 | type SendFuture<'a>: Future<Output = Result<(), Error>>; | 13 | where |
| 13 | /// Receive into the buffer until the buffer is full | 14 | Self: 'a; |
| 14 | fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>; | 15 | |
| 15 | /// Send the specified buffer, and return when the transmission has completed | 16 | fn read<'a>(self: Pin<&'a mut Self>, buf: &'a mut [u8]) -> Self::ReadFuture<'a>; |
| 16 | fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a>; | ||
| 17 | } | 17 | } |
| 18 | 18 | ||
| 19 | pub trait IdleUart { | 19 | pub trait ReadUntilIdle { |
| 20 | type ReceiveFuture<'a>: Future<Output = Result<usize, Error>>; | 20 | type ReadUntilIdleFuture<'a>: Future<Output = Result<usize, Error>> |
| 21 | where | ||
| 22 | Self: 'a; | ||
| 23 | |||
| 21 | /// Receive into the buffer until the buffer is full or the line is idle after some bytes are received | 24 | /// Receive into the buffer until the buffer is full or the line is idle after some bytes are received |
| 22 | /// Return the number of bytes received | 25 | /// Return the number of bytes received |
| 23 | fn receive_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>; | 26 | fn read_until_idle<'a>( |
| 27 | self: Pin<&'a mut Self>, | ||
| 28 | buf: &'a mut [u8], | ||
| 29 | ) -> Self::ReadUntilIdleFuture<'a>; | ||
| 30 | } | ||
| 31 | |||
| 32 | pub trait Write { | ||
| 33 | type WriteFuture<'a>: Future<Output = Result<(), Error>> | ||
| 34 | where | ||
| 35 | Self: 'a; | ||
| 36 | |||
| 37 | fn write<'a>(self: Pin<&'a mut Self>, buf: &'a [u8]) -> Self::WriteFuture<'a>; | ||
| 24 | } | 38 | } |
diff --git a/embassy/src/util/mod.rs b/embassy/src/util/mod.rs index 3166c65d9..9f82422dd 100644 --- a/embassy/src/util/mod.rs +++ b/embassy/src/util/mod.rs | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | mod drop_bomb; | 2 | mod drop_bomb; |
| 3 | mod forever; | 3 | mod forever; |
| 4 | mod mutex; | 4 | mod mutex; |
| 5 | mod on_drop; | ||
| 5 | mod portal; | 6 | mod portal; |
| 6 | mod signal; | 7 | mod signal; |
| 7 | 8 | ||
| @@ -11,6 +12,7 @@ mod waker; | |||
| 11 | pub use drop_bomb::*; | 12 | pub use drop_bomb::*; |
| 12 | pub use forever::*; | 13 | pub use forever::*; |
| 13 | pub use mutex::*; | 14 | pub use mutex::*; |
| 15 | pub use on_drop::*; | ||
| 14 | pub use portal::*; | 16 | pub use portal::*; |
| 15 | pub use signal::*; | 17 | pub use signal::*; |
| 16 | pub use waker::*; | 18 | pub use waker::*; |
diff --git a/embassy/src/util/on_drop.rs b/embassy/src/util/on_drop.rs new file mode 100644 index 000000000..10f3407f4 --- /dev/null +++ b/embassy/src/util/on_drop.rs | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | use core::mem; | ||
| 2 | use core::mem::MaybeUninit; | ||
| 3 | |||
| 4 | pub struct OnDrop<F: FnOnce()> { | ||
| 5 | f: MaybeUninit<F>, | ||
| 6 | } | ||
| 7 | |||
| 8 | impl<F: FnOnce()> OnDrop<F> { | ||
| 9 | pub fn new(f: F) -> Self { | ||
| 10 | Self { | ||
| 11 | f: MaybeUninit::new(f), | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | pub fn defuse(self) { | ||
| 16 | mem::forget(self) | ||
| 17 | } | ||
| 18 | } | ||
| 19 | |||
| 20 | impl<F: FnOnce()> Drop for OnDrop<F> { | ||
| 21 | fn drop(&mut self) { | ||
| 22 | unsafe { self.f.as_ptr().read()() } | ||
| 23 | } | ||
| 24 | } | ||
