aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-01-02 19:59:37 +0100
committerDario Nieuwenhuis <[email protected]>2021-01-02 19:59:37 +0100
commit0ab88ea27974af5987cbe6efcf9d1849900b2bd7 (patch)
treec67bb189011723bc99526bac61b1d93f5301ef37
parent1d53985abed58354bed9959e94b306870af214a4 (diff)
Add Uart trait, implement it for nrf.
-rw-r--r--embassy-nrf-examples/src/bin/uart.rs5
-rw-r--r--embassy-nrf/src/uarte.rs101
-rw-r--r--embassy/src/lib.rs1
-rw-r--r--embassy/src/uart.rs15
4 files changed, 73 insertions, 49 deletions
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;
10use defmt::panic; 10use defmt::panic;
11use embassy::executor::{task, Executor}; 11use embassy::executor::{task, Executor};
12use embassy::time::{Duration, Timer}; 12use embassy::time::{Duration, Timer};
13use embassy::uart::Uart;
13use embassy::util::Forever; 14use embassy::util::Forever;
14use embassy_nrf::{interrupt, pac, rtc, uarte}; 15use embassy_nrf::{interrupt, pac, rtc, uarte};
15use futures::future::{select, Either}; 16use futures::future::{select, Either};
@@ -24,7 +25,7 @@ async fn run(mut uart: uarte::Uarte<pac::UARTE0>) {
24 let mut buf = [0; 8]; 25 let mut buf = [0; 8];
25 buf.copy_from_slice(b"Hello!\r\n"); 26 buf.copy_from_slice(b"Hello!\r\n");
26 27
27 uart.send(&buf).await; 28 unwrap!(uart.send(&buf).await);
28 info!("wrote hello in uart!"); 29 info!("wrote hello in uart!");
29 30
30 loop { 31 loop {
@@ -54,7 +55,7 @@ async fn run(mut uart: uarte::Uarte<pac::UARTE0>) {
54 info!("read done, got {:[u8]}", received); 55 info!("read done, got {:[u8]}", received);
55 56
56 // Echo back received data 57 // Echo back received data
57 uart.send(received).await; 58 unwrap!(uart.send(received).await);
58 } 59 }
59 } 60 }
60} 61}
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
139 self.instance.enable.write(|w| w.enable().enabled()); 139 self.instance.enable.write(|w| w.enable().enabled());
140 } 140 }
141 141
142 /// Sends serial data.
143 ///
144 /// `tx_buffer` is marked as static as per `embedded-dma` requirements.
145 /// It it safe to use a buffer with a non static lifetime if memory is not
146 /// reused until the future has finished.
147 pub fn send<'a>(&'a mut self, tx_buffer: &'a [u8]) -> SendFuture<'a, T> {
148 // Panic if TX is running which can happen if the user has called
149 // `mem::forget()` on a previous future after polling it once.
150 assert!(!self.tx_started());
151
152 self.enable();
153
154 SendFuture {
155 uarte: self,
156 buf: tx_buffer,
157 }
158 }
159
160 fn tx_started(&self) -> bool { 142 fn tx_started(&self) -> bool {
161 self.instance.events_txstarted.read().bits() != 0 143 self.instance.events_txstarted.read().bits() != 0
162 } 144 }
163 145
164 /// Receives serial data.
165 ///
166 /// The future is pending until the buffer is completely filled.
167 /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel
168 /// unfinished transfers after a timeout to prevent lockup when no more data
169 /// is incoming.
170 ///
171 /// `rx_buffer` is marked as static as per `embedded-dma` requirements.
172 /// It it safe to use a buffer with a non static lifetime if memory is not
173 /// reused until the future has finished.
174 pub fn receive<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> ReceiveFuture<'a, T> {
175 // Panic if RX is running which can happen if the user has called
176 // `mem::forget()` on a previous future after polling it once.
177 assert!(!self.rx_started());
178
179 self.enable();
180
181 ReceiveFuture {
182 uarte: self,
183 buf: rx_buffer,
184 }
185 }
186
187 fn rx_started(&self) -> bool { 146 fn rx_started(&self) -> bool {
188 self.instance.events_rxstarted.read().bits() != 0 147 self.instance.events_rxstarted.read().bits() != 0
189 } 148 }
@@ -231,6 +190,52 @@ where
231 } 190 }
232} 191}
233 192
193impl<T: Instance> embassy::uart::Uart for Uarte<T> {
194 type ReceiveFuture<'a> = ReceiveFuture<'a, T>;
195 type SendFuture<'a> = SendFuture<'a, T>;
196
197 /// Sends serial data.
198 ///
199 /// `tx_buffer` is marked as static as per `embedded-dma` requirements.
200 /// It it safe to use a buffer with a non static lifetime if memory is not
201 /// reused until the future has finished.
202 fn send<'a>(&'a mut self, tx_buffer: &'a [u8]) -> SendFuture<'a, T> {
203 // Panic if TX is running which can happen if the user has called
204 // `mem::forget()` on a previous future after polling it once.
205 assert!(!self.tx_started());
206
207 self.enable();
208
209 SendFuture {
210 uarte: self,
211 buf: tx_buffer,
212 }
213 }
214
215 /// Receives serial data.
216 ///
217 /// The future is pending until the buffer is completely filled.
218 /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel
219 /// unfinished transfers after a timeout to prevent lockup when no more data
220 /// is incoming.
221 ///
222 /// `rx_buffer` is marked as static as per `embedded-dma` requirements.
223 /// It it safe to use a buffer with a non static lifetime if memory is not
224 /// reused until the future has finished.
225 fn receive<'a>(&'a mut self, rx_buffer: &'a mut [u8]) -> ReceiveFuture<'a, T> {
226 // Panic if RX is running which can happen if the user has called
227 // `mem::forget()` on a previous future after polling it once.
228 assert!(!self.rx_started());
229
230 self.enable();
231
232 ReceiveFuture {
233 uarte: self,
234 buf: rx_buffer,
235 }
236 }
237}
238
234/// Future for the [`Uarte::send()`] method. 239/// Future for the [`Uarte::send()`] method.
235pub struct SendFuture<'a, T> 240pub struct SendFuture<'a, T>
236where 241where
@@ -263,9 +268,9 @@ impl<'a, T> Future for SendFuture<'a, T>
263where 268where
264 T: Instance, 269 T: Instance,
265{ 270{
266 type Output = (); 271 type Output = Result<(), embassy::uart::Error>;
267 272
268 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> { 273 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
269 let Self { uarte, buf } = unsafe { self.get_unchecked_mut() }; 274 let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
270 275
271 if !uarte.tx_started() { 276 if !uarte.tx_started() {
@@ -289,7 +294,7 @@ where
289 uarte.tasks_starttx.write(|w| unsafe { w.bits(1) }); 294 uarte.tasks_starttx.write(|w| unsafe { w.bits(1) });
290 } 295 }
291 296
292 T::state().tx_done.poll_wait(cx) 297 T::state().tx_done.poll_wait(cx).map(|()| Ok(()))
293 } 298 }
294} 299}
295 300
@@ -324,7 +329,7 @@ impl<'a, T> Future for ReceiveFuture<'a, T>
324where 329where
325 T: Instance, 330 T: Instance,
326{ 331{
327 type Output = (); 332 type Output = Result<(), embassy::uart::Error>;
328 333
329 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { 334 fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
330 let Self { uarte, buf } = unsafe { self.get_unchecked_mut() }; 335 let Self { uarte, buf } = unsafe { self.get_unchecked_mut() };
@@ -349,7 +354,7 @@ where
349 uarte.tasks_startrx.write(|w| unsafe { w.bits(1) }); 354 uarte.tasks_startrx.write(|w| unsafe { w.bits(1) });
350 } 355 }
351 356
352 T::state().rx_done.poll_wait(cx).map(|_| ()) 357 T::state().rx_done.poll_wait(cx).map(|_| Ok(()))
353 } 358 }
354} 359}
355 360
@@ -370,7 +375,9 @@ mod private {
370 pub trait Sealed {} 375 pub trait Sealed {}
371} 376}
372 377
373pub trait Instance: Deref<Target = pac::uarte0::RegisterBlock> + Sized + private::Sealed { 378pub trait Instance:
379 Deref<Target = pac::uarte0::RegisterBlock> + Sized + private::Sealed + 'static
380{
374 type Interrupt: OwnedInterrupt; 381 type Interrupt: OwnedInterrupt;
375 382
376 #[doc(hidden)] 383 #[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;
12pub mod io; 12pub mod io;
13pub mod rand; 13pub mod rand;
14pub mod time; 14pub mod time;
15pub mod uart;
15pub mod util; 16pub 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 @@
1use core::future::Future;
2
3#[derive(Copy, Clone, Debug, Eq, PartialEq)]
4#[cfg_attr(feature = "defmt", derive(defmt::Format))]
5#[non_exhaustive]
6pub enum Error {
7 Other,
8}
9
10pub trait Uart {
11 type ReceiveFuture<'a>: Future<Output = Result<(), Error>>;
12 type SendFuture<'a>: Future<Output = Result<(), Error>>;
13 fn receive<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReceiveFuture<'a>;
14 fn send<'a>(&'a mut self, buf: &'a [u8]) -> Self::SendFuture<'a>;
15}