aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-03-22 01:15:44 +0100
committerDario Nieuwenhuis <[email protected]>2021-03-29 00:58:58 +0200
commitdf42c384923579c449a13511b0fdb8de3b2a4773 (patch)
tree0c89eb75183e972e81748f9a3e601df30191c14a
parent7b6086d19eca2d51c7cddf9dbbbc47eacf371472 (diff)
nrf/uarte: update to new api
-rw-r--r--embassy-nrf-examples/src/bin/uart.rs56
-rw-r--r--embassy-nrf/src/uarte.rs427
-rw-r--r--embassy-traits/src/uart.rs34
-rw-r--r--embassy/src/util/mod.rs2
-rw-r--r--embassy/src/util/on_drop.rs24
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;
12use defmt::panic; 12use defmt::panic;
13use embassy::executor::{task, Executor}; 13use embassy::executor::{task, Executor};
14use embassy::time::{Duration, Timer}; 14use embassy::time::{Duration, Timer};
15use embassy::traits::uart::Uart; 15use embassy::traits::uart::{Read, Write};
16use embassy::util::Forever; 16use embassy::util::Forever;
17use embassy_nrf::{interrupt, pac, rtc, uarte}; 17use embassy_nrf::{interrupt, pac, rtc, uarte, Peripherals};
18use futures::future::{select, Either}; 18use futures::future::{select, Either};
19use futures::pin_mut;
19use nrf52840_hal::clocks; 20use nrf52840_hal::clocks;
20use nrf52840_hal::gpio; 21use nrf52840_hal::gpio;
21 22
22#[task] 23#[task]
23async fn run(uart: pac::UARTE0, port: pac::P0) { 24async 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
7use core::future::Future; 7use core::future::Future;
8use core::ops::Deref; 8use core::marker::PhantomData;
9use core::pin::Pin;
9use core::sync::atomic::{compiler_fence, Ordering}; 10use core::sync::atomic::{compiler_fence, Ordering};
10use core::task::{Context, Poll}; 11use core::task::Poll;
11 12use embassy::traits::uart::{Error, Read, Write};
12use embassy::interrupt::InterruptExt; 13use embassy::util::{wake_on_interrupt, OnDrop, PeripheralBorrow, Signal};
13use embassy::util::Signal; 14use embassy_extras::unborrow;
15use futures::future::poll_fn;
14 16
15use crate::fmt::{assert, *}; 17use crate::fmt::{assert, *};
18use crate::gpio::Pin as GpioPin;
16use crate::hal::pac; 19use crate::hal::pac;
17use crate::hal::prelude::*;
18use crate::hal::target_constants::EASY_DMA_SIZE; 20use crate::hal::target_constants::EASY_DMA_SIZE;
19use crate::interrupt; 21use crate::interrupt;
20use crate::interrupt::Interrupt; 22use crate::interrupt::Interrupt;
23use crate::peripherals;
21 24
22pub 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.
24pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 26pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
25 27
26/// Interface to the UARTE peripheral 28#[non_exhaustive]
27pub struct Uarte<T> 29pub struct Config {
28where 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
36pub struct State { 34impl 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
41impl<T> Uarte<T> 43/// Interface to the UARTE peripheral
42where 44pub struct Uarte<'d, T: Instance> {
43 T: Instance, 45 peri: T,
44{ 46 irq: T::Interrupt,
47 phantom: PhantomData<&'d mut T>,
48}
49
50impl<'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
191impl<T: Instance> embassy::traits::uart::Uart for Uarte<T> { 161impl<'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. 219impl<'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.
238pub struct SendFuture<'a, T> 280pub struct SendFuture<'a, T>
239where 281where
@@ -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
267impl<'a, T> Future for SendFuture<'a, T>
268where
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.
308pub struct ReceiveFuture<'a, T> 307pub struct ReceiveFuture<'a, T>
309where 308where
@@ -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
386mod sealed {
387 use super::*;
399 388
400mod private { 389 pub trait Instance {
401 pub trait Sealed {} 390 fn regs(&self) -> &pac::uarte0::RegisterBlock;
391 }
402} 392}
403 393
404pub trait Instance: 394pub 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
413static UARTE0_STATE: State = State { 398macro_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 {
417impl private::Sealed for pac::UARTE0 {} 402 unsafe { &*pac::$type::ptr() }
418impl 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
411make_impl!(UARTE0, UARTE0_UART0);
426#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] 412#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
427static UARTE1_STATE: State = State { 413make_impl!(UARTE1, UARTE1);
428 tx_done: Signal::new(),
429 rx_done: Signal::new(),
430};
431#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
432impl private::Sealed for pac::UARTE1 {}
433#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))]
434impl 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 @@
1use core::future::Future; 1use core::future::Future;
2use 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
10pub trait Uart { 11pub 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
19pub trait IdleUart { 19pub 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
32pub 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 @@
2mod drop_bomb; 2mod drop_bomb;
3mod forever; 3mod forever;
4mod mutex; 4mod mutex;
5mod on_drop;
5mod portal; 6mod portal;
6mod signal; 7mod signal;
7 8
@@ -11,6 +12,7 @@ mod waker;
11pub use drop_bomb::*; 12pub use drop_bomb::*;
12pub use forever::*; 13pub use forever::*;
13pub use mutex::*; 14pub use mutex::*;
15pub use on_drop::*;
14pub use portal::*; 16pub use portal::*;
15pub use signal::*; 17pub use signal::*;
16pub use waker::*; 18pub 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 @@
1use core::mem;
2use core::mem::MaybeUninit;
3
4pub struct OnDrop<F: FnOnce()> {
5 f: MaybeUninit<F>,
6}
7
8impl<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
20impl<F: FnOnce()> Drop for OnDrop<F> {
21 fn drop(&mut self) {
22 unsafe { self.f.as_ptr().read()() }
23 }
24}