From 0ab88ea27974af5987cbe6efcf9d1849900b2bd7 Mon Sep 17 00:00:00 2001
From: Dario Nieuwenhuis <dirbaio@dirbaio.net>
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 e8230c81a..cb38e8fcb 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<pac::UARTE0>) {
     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<pac::UARTE0>) {
             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 3983c96b4..648298b84 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<T: Instance> embassy::uart::Uart for Uarte<T> {
+    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<Self::Output> {
         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<Self::Output> {
         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<Target = pac::uarte0::RegisterBlock> + Sized + private::Sealed {
+pub trait Instance:
+    Deref<Target = pac::uarte0::RegisterBlock> + Sized + private::Sealed + 'static
+{
     type Interrupt: OwnedInterrupt;
 
     #[doc(hidden)]
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs
index 8f93535e3..02d72a84f 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 000000000..b40b9e9bd
--- /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<Output = Result<(), Error>>;
+    type SendFuture<'a>: Future<Output = Result<(), Error>>;
+    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>;
+}