From 0ab88ea27974af5987cbe6efcf9d1849900b2bd7 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 2 Jan 2021 19:59:37 +0100 Subject: [PATCH] Add Uart trait, implement it for nrf. --- embassy-nrf-examples/src/bin/uart.rs | 5 +- embassy-nrf/src/uarte.rs | 101 ++++++++++++++------------- embassy/src/lib.rs | 1 + embassy/src/uart.rs | 15 ++++ 4 files changed, 73 insertions(+), 49 deletions(-) create mode 100644 embassy/src/uart.rs diff --git a/embassy-nrf-examples/src/bin/uart.rs b/embassy-nrf-examples/src/bin/uart.rs index e8230c81..cb38e8fc 100644 --- a/embassy-nrf-examples/src/bin/uart.rs +++ b/embassy-nrf-examples/src/bin/uart.rs @@ -10,6 +10,7 @@ use cortex_m_rt::entry; use defmt::panic; use embassy::executor::{task, Executor}; use embassy::time::{Duration, Timer}; +use embassy::uart::Uart; use embassy::util::Forever; use embassy_nrf::{interrupt, pac, rtc, uarte}; use futures::future::{select, Either}; @@ -24,7 +25,7 @@ async fn run(mut uart: uarte::Uarte) { let mut buf = [0; 8]; buf.copy_from_slice(b"Hello!\r\n"); - uart.send(&buf).await; + unwrap!(uart.send(&buf).await); info!("wrote hello in uart!"); loop { @@ -54,7 +55,7 @@ async fn run(mut uart: uarte::Uarte) { info!("read done, got {:[u8]}", received); // Echo back received data - uart.send(received).await; + unwrap!(uart.send(received).await); } } } diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 3983c96b..648298b8 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -139,51 +139,10 @@ where self.instance.enable.write(|w| w.enable().enabled()); } - /// Sends serial data. - /// - /// `tx_buffer` is marked as static as per `embedded-dma` requirements. - /// It it safe to use a buffer with a non static lifetime if memory is not - /// reused until the future has finished. - pub fn send<'a>(&'a mut self, tx_buffer: &'a [u8]) -> SendFuture<'a, T> { - // Panic if TX is running which can happen if the user has called - // `mem::forget()` on a previous future after polling it once. - assert!(!self.tx_started()); - - self.enable(); - - SendFuture { - uarte: self, - buf: tx_buffer, - } - } - fn tx_started(&self) -> bool { self.instance.events_txstarted.read().bits() != 0 } - /// Receives serial data. - /// - /// The future is pending until the buffer is completely filled. - /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel - /// unfinished transfers after a timeout to prevent lockup when no more data - /// is incoming. - /// - /// `rx_buffer` is marked as static as per `embedded-dma` requirements. - /// It it safe to use a buffer with a non static lifetime if memory is not - /// reused until the future has finished. - pub fn receive<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> ReceiveFuture<'a, T> { - // Panic if RX is running which can happen if the user has called - // `mem::forget()` on a previous future after polling it once. - assert!(!self.rx_started()); - - self.enable(); - - ReceiveFuture { - uarte: self, - buf: rx_buffer, - } - } - fn rx_started(&self) -> bool { self.instance.events_rxstarted.read().bits() != 0 } @@ -231,6 +190,52 @@ where } } +impl embassy::uart::Uart for Uarte { + type ReceiveFuture<'a> = ReceiveFuture<'a, T>; + type SendFuture<'a> = SendFuture<'a, T>; + + /// Sends serial data. + /// + /// `tx_buffer` is marked as static as per `embedded-dma` requirements. + /// It it safe to use a buffer with a non static lifetime if memory is not + /// reused until the future has finished. + fn send<'a>(&'a mut self, tx_buffer: &'a [u8]) -> SendFuture<'a, T> { + // Panic if TX is running which can happen if the user has called + // `mem::forget()` on a previous future after polling it once. + assert!(!self.tx_started()); + + self.enable(); + + SendFuture { + uarte: self, + buf: tx_buffer, + } + } + + /// Receives serial data. + /// + /// The future is pending until the buffer is completely filled. + /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel + /// unfinished transfers after a timeout to prevent lockup when no more data + /// is incoming. + /// + /// `rx_buffer` is marked as static as per `embedded-dma` requirements. + /// It it safe to use a buffer with a non static lifetime if memory is not + /// reused until the future has finished. + fn receive<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> ReceiveFuture<'a, T> { + // Panic if RX is running which can happen if the user has called + // `mem::forget()` on a previous future after polling it once. + assert!(!self.rx_started()); + + self.enable(); + + ReceiveFuture { + uarte: self, + buf: rx_buffer, + } + } +} + /// Future for the [`Uarte::send()`] method. pub struct SendFuture<'a, T> where @@ -263,9 +268,9 @@ impl<'a, T> Future for SendFuture<'a, T> where T: Instance, { - type Output = (); + type Output = Result<(), embassy::uart::Error>; - fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { + fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { uarte, buf } = unsafe { self.get_unchecked_mut() }; if !uarte.tx_started() { @@ -289,7 +294,7 @@ where uarte.tasks_starttx.write(|w| unsafe { w.bits(1) }); } - T::state().tx_done.poll_wait(cx) + T::state().tx_done.poll_wait(cx).map(|()| Ok(())) } } @@ -324,7 +329,7 @@ impl<'a, T> Future for ReceiveFuture<'a, T> where T: Instance, { - type Output = (); + type Output = Result<(), embassy::uart::Error>; fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { let Self { uarte, buf } = unsafe { self.get_unchecked_mut() }; @@ -349,7 +354,7 @@ where uarte.tasks_startrx.write(|w| unsafe { w.bits(1) }); } - T::state().rx_done.poll_wait(cx).map(|_| ()) + T::state().rx_done.poll_wait(cx).map(|_| Ok(())) } } @@ -370,7 +375,9 @@ mod private { pub trait Sealed {} } -pub trait Instance: Deref + Sized + private::Sealed { +pub trait Instance: + Deref + Sized + private::Sealed + 'static +{ type Interrupt: OwnedInterrupt; #[doc(hidden)] diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index 8f93535e..02d72a84 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs @@ -12,4 +12,5 @@ pub mod interrupt; pub mod io; pub mod rand; pub mod time; +pub mod uart; pub mod util; diff --git a/embassy/src/uart.rs b/embassy/src/uart.rs new file mode 100644 index 00000000..b40b9e9b --- /dev/null +++ b/embassy/src/uart.rs @@ -0,0 +1,15 @@ +use core::future::Future; + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + Other, +} + +pub trait Uart { + type ReceiveFuture<'a>: Future>; + type SendFuture<'a>: Future>; + fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>; + fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a>; +}