aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-09-27 06:00:33 +0000
committerGitHub <[email protected]>2022-09-27 06:00:33 +0000
commit82d436075633e179f96d49b6afb9045451a591d4 (patch)
tree0e5e66638d2896357070671ff26f8d1cd65269a5
parent86fd4806724a003421897f2e465f0c79e38e849b (diff)
parente129a97d48a00d7923886ab3faa82357b2369f13 (diff)
Merge #934
934: (embassy-rp): Add Buffered UART implementation r=MathiasKoch a=MathiasKoch ### Questions & concerns: - ~~Would it make sense to add `RxBufferedUart` and `TxBufferedUart`, for cases where you would want to only buffer one way?~~ - ~~Do I need to be monitoring more interrupt flags than `Receive` & `Receive timeout`?~~ This PR adds working `BufferedUart` implementation, along with `RxBufferedUart` and `TxBufferedUart`. The implementation leaves room for improvement with respect to performance, as it still does not utilize DMA nor the internal UART buffers. Co-authored-by: Mathias <[email protected]> Co-authored-by: Dario Nieuwenhuis <[email protected]>
-rw-r--r--embassy-rp/Cargo.toml3
-rw-r--r--embassy-rp/src/uart/buffered.rs489
-rw-r--r--embassy-rp/src/uart/mod.rs (renamed from embassy-rp/src/uart.rs)87
-rw-r--r--tests/rp/.cargo/config.toml2
-rw-r--r--tests/rp/Cargo.toml1
-rw-r--r--tests/rp/src/bin/uart_buffered.rs44
6 files changed, 622 insertions, 4 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index c43fd7e72..d0cf8025c 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -27,7 +27,7 @@ intrinsics = []
27rom-v2-intrinsics = [] 27rom-v2-intrinsics = []
28 28
29# Enable nightly-only features 29# Enable nightly-only features
30nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb"] 30nightly = ["embassy-executor/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb", "dep:embedded-io"]
31 31
32# Implement embedded-hal 1.0 alpha traits. 32# Implement embedded-hal 1.0 alpha traits.
33# Implement embedded-hal-async traits if `nightly` is set as well. 33# Implement embedded-hal-async traits if `nightly` is set as well.
@@ -52,6 +52,7 @@ cortex-m = "0.7.6"
52critical-section = "1.1" 52critical-section = "1.1"
53futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 53futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
54chrono = { version = "0.4", default-features = false, optional = true } 54chrono = { version = "0.4", default-features = false, optional = true }
55embedded-io = { version = "0.3.0", features = ["async"], optional = true }
55 56
56rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] } 57rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] }
57#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] } 58#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] }
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
new file mode 100644
index 000000000..87e16f0eb
--- /dev/null
+++ b/embassy-rp/src/uart/buffered.rs
@@ -0,0 +1,489 @@
1use core::future::{poll_fn, Future};
2use core::task::{Poll, Waker};
3
4use atomic_polyfill::{compiler_fence, Ordering};
5use embassy_cortex_m::peripheral::{PeripheralMutex, PeripheralState, StateStorage};
6use embassy_hal_common::ring_buffer::RingBuffer;
7use embassy_sync::waitqueue::WakerRegistration;
8
9use super::*;
10
11pub struct State<'d, T: Instance>(StateStorage<FullStateInner<'d, T>>);
12impl<'d, T: Instance> State<'d, T> {
13 pub const fn new() -> Self {
14 Self(StateStorage::new())
15 }
16}
17
18pub struct RxState<'d, T: Instance>(StateStorage<RxStateInner<'d, T>>);
19impl<'d, T: Instance> RxState<'d, T> {
20 pub const fn new() -> Self {
21 Self(StateStorage::new())
22 }
23}
24
25pub struct TxState<'d, T: Instance>(StateStorage<TxStateInner<'d, T>>);
26impl<'d, T: Instance> TxState<'d, T> {
27 pub const fn new() -> Self {
28 Self(StateStorage::new())
29 }
30}
31
32struct RxStateInner<'d, T: Instance> {
33 phantom: PhantomData<&'d mut T>,
34
35 waker: WakerRegistration,
36 buf: RingBuffer<'d>,
37}
38
39struct TxStateInner<'d, T: Instance> {
40 phantom: PhantomData<&'d mut T>,
41
42 waker: WakerRegistration,
43 buf: RingBuffer<'d>,
44}
45
46struct FullStateInner<'d, T: Instance> {
47 rx: RxStateInner<'d, T>,
48 tx: TxStateInner<'d, T>,
49}
50
51unsafe impl<'d, T: Instance> Send for RxStateInner<'d, T> {}
52unsafe impl<'d, T: Instance> Sync for RxStateInner<'d, T> {}
53
54unsafe impl<'d, T: Instance> Send for TxStateInner<'d, T> {}
55unsafe impl<'d, T: Instance> Sync for TxStateInner<'d, T> {}
56
57unsafe impl<'d, T: Instance> Send for FullStateInner<'d, T> {}
58unsafe impl<'d, T: Instance> Sync for FullStateInner<'d, T> {}
59
60pub struct BufferedUart<'d, T: Instance> {
61 inner: PeripheralMutex<'d, FullStateInner<'d, T>>,
62}
63
64pub struct BufferedUartRx<'d, T: Instance> {
65 inner: PeripheralMutex<'d, RxStateInner<'d, T>>,
66}
67
68pub struct BufferedUartTx<'d, T: Instance> {
69 inner: PeripheralMutex<'d, TxStateInner<'d, T>>,
70}
71
72impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {}
73impl<'d, T: Instance> Unpin for BufferedUartRx<'d, T> {}
74impl<'d, T: Instance> Unpin for BufferedUartTx<'d, T> {}
75
76impl<'d, T: Instance> BufferedUart<'d, T> {
77 pub fn new<M: Mode>(
78 state: &'d mut State<'d, T>,
79 _uart: Uart<'d, T, M>,
80 irq: impl Peripheral<P = T::Interrupt> + 'd,
81 tx_buffer: &'d mut [u8],
82 rx_buffer: &'d mut [u8],
83 ) -> BufferedUart<'d, T> {
84 into_ref!(irq);
85
86 let r = T::regs();
87 unsafe {
88 r.uartimsc().modify(|w| {
89 w.set_rxim(true);
90 w.set_rtim(true);
91 w.set_txim(true);
92 });
93 }
94
95 Self {
96 inner: PeripheralMutex::new(irq, &mut state.0, move || FullStateInner {
97 tx: TxStateInner {
98 phantom: PhantomData,
99 waker: WakerRegistration::new(),
100 buf: RingBuffer::new(tx_buffer),
101 },
102 rx: RxStateInner {
103 phantom: PhantomData,
104 waker: WakerRegistration::new(),
105 buf: RingBuffer::new(rx_buffer),
106 },
107 }),
108 }
109 }
110}
111
112impl<'d, T: Instance> BufferedUartRx<'d, T> {
113 pub fn new<M: Mode>(
114 state: &'d mut RxState<'d, T>,
115 _uart: UartRx<'d, T, M>,
116 irq: impl Peripheral<P = T::Interrupt> + 'd,
117 rx_buffer: &'d mut [u8],
118 ) -> BufferedUartRx<'d, T> {
119 into_ref!(irq);
120
121 let r = T::regs();
122 unsafe {
123 r.uartimsc().modify(|w| {
124 w.set_rxim(true);
125 w.set_rtim(true);
126 });
127 }
128
129 Self {
130 inner: PeripheralMutex::new(irq, &mut state.0, move || RxStateInner {
131 phantom: PhantomData,
132
133 buf: RingBuffer::new(rx_buffer),
134 waker: WakerRegistration::new(),
135 }),
136 }
137 }
138}
139
140impl<'d, T: Instance> BufferedUartTx<'d, T> {
141 pub fn new<M: Mode>(
142 state: &'d mut TxState<'d, T>,
143 _uart: UartTx<'d, T, M>,
144 irq: impl Peripheral<P = T::Interrupt> + 'd,
145 tx_buffer: &'d mut [u8],
146 ) -> BufferedUartTx<'d, T> {
147 into_ref!(irq);
148
149 let r = T::regs();
150 unsafe {
151 r.uartimsc().modify(|w| {
152 w.set_txim(true);
153 });
154 }
155
156 Self {
157 inner: PeripheralMutex::new(irq, &mut state.0, move || TxStateInner {
158 phantom: PhantomData,
159
160 buf: RingBuffer::new(tx_buffer),
161 waker: WakerRegistration::new(),
162 }),
163 }
164 }
165}
166
167impl<'d, T: Instance> PeripheralState for FullStateInner<'d, T>
168where
169 Self: 'd,
170{
171 type Interrupt = T::Interrupt;
172 fn on_interrupt(&mut self) {
173 self.rx.on_interrupt();
174 self.tx.on_interrupt();
175 }
176}
177
178impl<'d, T: Instance> RxStateInner<'d, T>
179where
180 Self: 'd,
181{
182 fn read(&mut self, buf: &mut [u8], waker: &Waker) -> (Poll<Result<usize, Error>>, bool) {
183 // We have data ready in buffer? Return it.
184 let mut do_pend = false;
185 let data = self.buf.pop_buf();
186 if !data.is_empty() {
187 let len = data.len().min(buf.len());
188 buf[..len].copy_from_slice(&data[..len]);
189
190 if self.buf.is_full() {
191 do_pend = true;
192 }
193 self.buf.pop(len);
194
195 return (Poll::Ready(Ok(len)), do_pend);
196 }
197
198 self.waker.register(waker);
199 (Poll::Pending, do_pend)
200 }
201
202 fn fill_buf<'a>(&mut self, waker: &Waker) -> Poll<Result<&'a [u8], Error>> {
203 // We have data ready in buffer? Return it.
204 let buf = self.buf.pop_buf();
205 if !buf.is_empty() {
206 let buf: &[u8] = buf;
207 // Safety: buffer lives as long as uart
208 let buf: &[u8] = unsafe { core::mem::transmute(buf) };
209 return Poll::Ready(Ok(buf));
210 }
211
212 self.waker.register(waker);
213 Poll::Pending
214 }
215
216 fn consume(&mut self, amt: usize) -> bool {
217 let full = self.buf.is_full();
218 self.buf.pop(amt);
219 full
220 }
221}
222
223impl<'d, T: Instance> PeripheralState for RxStateInner<'d, T>
224where
225 Self: 'd,
226{
227 type Interrupt = T::Interrupt;
228 fn on_interrupt(&mut self) {
229 let r = T::regs();
230 unsafe {
231 let ris = r.uartris().read();
232 // Clear interrupt flags
233 r.uarticr().modify(|w| {
234 w.set_rxic(true);
235 w.set_rtic(true);
236 });
237
238 if ris.peris() {
239 warn!("Parity error");
240 r.uarticr().modify(|w| {
241 w.set_peic(true);
242 });
243 }
244 if ris.feris() {
245 warn!("Framing error");
246 r.uarticr().modify(|w| {
247 w.set_feic(true);
248 });
249 }
250 if ris.beris() {
251 warn!("Break error");
252 r.uarticr().modify(|w| {
253 w.set_beic(true);
254 });
255 }
256 if ris.oeris() {
257 warn!("Overrun error");
258 r.uarticr().modify(|w| {
259 w.set_oeic(true);
260 });
261 }
262
263 if !r.uartfr().read().rxfe() {
264 let buf = self.buf.push_buf();
265 if !buf.is_empty() {
266 buf[0] = r.uartdr().read().data();
267 self.buf.push(1);
268 } else {
269 warn!("RX buffer full, discard received byte");
270 }
271
272 if self.buf.is_full() {
273 self.waker.wake();
274 }
275 }
276
277 if ris.rtris() {
278 self.waker.wake();
279 };
280 }
281 }
282}
283
284impl<'d, T: Instance> TxStateInner<'d, T>
285where
286 Self: 'd,
287{
288 fn write(&mut self, buf: &[u8], waker: &Waker) -> (Poll<Result<usize, Error>>, bool) {
289 let empty = self.buf.is_empty();
290 let tx_buf = self.buf.push_buf();
291 if tx_buf.is_empty() {
292 self.waker.register(waker);
293 return (Poll::Pending, empty);
294 }
295
296 let n = core::cmp::min(tx_buf.len(), buf.len());
297 tx_buf[..n].copy_from_slice(&buf[..n]);
298 self.buf.push(n);
299
300 (Poll::Ready(Ok(n)), empty)
301 }
302
303 fn flush(&mut self, waker: &Waker) -> Poll<Result<(), Error>> {
304 if !self.buf.is_empty() {
305 self.waker.register(waker);
306 return Poll::Pending;
307 }
308
309 Poll::Ready(Ok(()))
310 }
311}
312
313impl<'d, T: Instance> PeripheralState for TxStateInner<'d, T>
314where
315 Self: 'd,
316{
317 type Interrupt = T::Interrupt;
318 fn on_interrupt(&mut self) {
319 let r = T::regs();
320 unsafe {
321 let buf = self.buf.pop_buf();
322 if !buf.is_empty() {
323 r.uartimsc().modify(|w| {
324 w.set_txim(true);
325 });
326 r.uartdr().write(|w| w.set_data(buf[0].into()));
327 self.buf.pop(1);
328 self.waker.wake();
329 } else {
330 // Disable interrupt until we have something to transmit again
331 r.uartimsc().modify(|w| {
332 w.set_txim(false);
333 });
334 }
335 }
336 }
337}
338
339impl embedded_io::Error for Error {
340 fn kind(&self) -> embedded_io::ErrorKind {
341 embedded_io::ErrorKind::Other
342 }
343}
344
345impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> {
346 type Error = Error;
347}
348
349impl<'d, T: Instance> embedded_io::Io for BufferedUartRx<'d, T> {
350 type Error = Error;
351}
352
353impl<'d, T: Instance> embedded_io::Io for BufferedUartTx<'d, T> {
354 type Error = Error;
355}
356
357impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUart<'d, T> {
358 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
359 where
360 Self: 'a;
361
362 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
363 poll_fn(move |cx| {
364 let (res, do_pend) = self.inner.with(|state| {
365 compiler_fence(Ordering::SeqCst);
366 state.rx.read(buf, cx.waker())
367 });
368
369 if do_pend {
370 self.inner.pend();
371 }
372
373 res
374 })
375 }
376}
377
378impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUartRx<'d, T> {
379 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
380 where
381 Self: 'a;
382
383 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
384 poll_fn(move |cx| {
385 let (res, do_pend) = self.inner.with(|state| {
386 compiler_fence(Ordering::SeqCst);
387 state.read(buf, cx.waker())
388 });
389
390 if do_pend {
391 self.inner.pend();
392 }
393
394 res
395 })
396 }
397}
398
399impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUart<'d, T> {
400 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>>
401 where
402 Self: 'a;
403
404 fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> {
405 poll_fn(move |cx| {
406 self.inner.with(|state| {
407 compiler_fence(Ordering::SeqCst);
408 state.rx.fill_buf(cx.waker())
409 })
410 })
411 }
412
413 fn consume(&mut self, amt: usize) {
414 let signal = self.inner.with(|state| state.rx.consume(amt));
415 if signal {
416 self.inner.pend();
417 }
418 }
419}
420
421impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUartRx<'d, T> {
422 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>>
423 where
424 Self: 'a;
425
426 fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> {
427 poll_fn(move |cx| {
428 self.inner.with(|state| {
429 compiler_fence(Ordering::SeqCst);
430 state.fill_buf(cx.waker())
431 })
432 })
433 }
434
435 fn consume(&mut self, amt: usize) {
436 let signal = self.inner.with(|state| state.consume(amt));
437 if signal {
438 self.inner.pend();
439 }
440 }
441}
442
443impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> {
444 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
445 where
446 Self: 'a;
447
448 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
449 poll_fn(move |cx| {
450 let (poll, empty) = self.inner.with(|state| state.tx.write(buf, cx.waker()));
451 if empty {
452 self.inner.pend();
453 }
454 poll
455 })
456 }
457
458 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>>
459 where
460 Self: 'a;
461
462 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
463 poll_fn(move |cx| self.inner.with(|state| state.tx.flush(cx.waker())))
464 }
465}
466
467impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T> {
468 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
469 where
470 Self: 'a;
471
472 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
473 poll_fn(move |cx| {
474 let (poll, empty) = self.inner.with(|state| state.write(buf, cx.waker()));
475 if empty {
476 self.inner.pend();
477 }
478 poll
479 })
480 }
481
482 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>>
483 where
484 Self: 'a;
485
486 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
487 poll_fn(move |cx| self.inner.with(|state| state.flush(cx.waker())))
488 }
489}
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart/mod.rs
index 987b716b4..d9285ee51 100644
--- a/embassy-rp/src/uart.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -346,6 +346,11 @@ impl<'d, T: Instance, M: Mode> Uart<'d, T, M> {
346 w.set_fen(true); 346 w.set_fen(true);
347 }); 347 });
348 348
349 r.uartifls().write(|w| {
350 w.set_rxiflsel(0b000);
351 w.set_txiflsel(0b000);
352 });
353
349 r.uartcr().write(|w| { 354 r.uartcr().write(|w| {
350 w.set_uarten(true); 355 w.set_uarten(true);
351 w.set_rxe(true); 356 w.set_rxe(true);
@@ -475,6 +480,75 @@ mod eh1 {
475 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> { 480 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> {
476 type Error = Error; 481 type Error = Error;
477 } 482 }
483
484 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Read for UartRx<'d, T, M> {
485 fn read(&mut self) -> nb::Result<u8, Self::Error> {
486 let r = T::regs();
487 unsafe {
488 let dr = r.uartdr().read();
489
490 if dr.oe() {
491 Err(nb::Error::Other(Error::Overrun))
492 } else if dr.be() {
493 Err(nb::Error::Other(Error::Break))
494 } else if dr.pe() {
495 Err(nb::Error::Other(Error::Parity))
496 } else if dr.fe() {
497 Err(nb::Error::Other(Error::Framing))
498 } else if dr.fe() {
499 Ok(dr.data())
500 } else {
501 Err(nb::Error::WouldBlock)
502 }
503 }
504 }
505 }
506
507 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::blocking::Write for UartTx<'d, T, M> {
508 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
509 self.blocking_write(buffer)
510 }
511
512 fn flush(&mut self) -> Result<(), Self::Error> {
513 self.blocking_flush()
514 }
515 }
516
517 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Write for UartTx<'d, T, M> {
518 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
519 self.blocking_write(&[char]).map_err(nb::Error::Other)
520 }
521
522 fn flush(&mut self) -> nb::Result<(), Self::Error> {
523 self.blocking_flush().map_err(nb::Error::Other)
524 }
525 }
526
527 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Read for Uart<'d, T, M> {
528 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
529 embedded_hal_02::serial::Read::read(&mut self.rx)
530 }
531 }
532
533 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::blocking::Write for Uart<'d, T, M> {
534 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
535 self.blocking_write(buffer)
536 }
537
538 fn flush(&mut self) -> Result<(), Self::Error> {
539 self.blocking_flush()
540 }
541 }
542
543 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Write for Uart<'d, T, M> {
544 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
545 self.blocking_write(&[char]).map_err(nb::Error::Other)
546 }
547
548 fn flush(&mut self) -> nb::Result<(), Self::Error> {
549 self.blocking_flush().map_err(nb::Error::Other)
550 }
551 }
478} 552}
479 553
480#[cfg(all( 554#[cfg(all(
@@ -532,6 +606,11 @@ mod eha {
532 } 606 }
533} 607}
534 608
609#[cfg(feature = "nightly")]
610mod buffered;
611#[cfg(feature = "nightly")]
612pub use buffered::*;
613
535mod sealed { 614mod sealed {
536 use super::*; 615 use super::*;
537 616
@@ -541,6 +620,8 @@ mod sealed {
541 const TX_DREQ: u8; 620 const TX_DREQ: u8;
542 const RX_DREQ: u8; 621 const RX_DREQ: u8;
543 622
623 type Interrupt: crate::interrupt::Interrupt;
624
544 fn regs() -> pac::uart::Uart; 625 fn regs() -> pac::uart::Uart;
545 } 626 }
546 pub trait TxPin<T: Instance> {} 627 pub trait TxPin<T: Instance> {}
@@ -572,6 +653,8 @@ macro_rules! impl_instance {
572 const TX_DREQ: u8 = $tx_dreq; 653 const TX_DREQ: u8 = $tx_dreq;
573 const RX_DREQ: u8 = $rx_dreq; 654 const RX_DREQ: u8 = $rx_dreq;
574 655
656 type Interrupt = crate::interrupt::$irq;
657
575 fn regs() -> pac::uart::Uart { 658 fn regs() -> pac::uart::Uart {
576 pac::$inst 659 pac::$inst
577 } 660 }
@@ -580,8 +663,8 @@ macro_rules! impl_instance {
580 }; 663 };
581} 664}
582 665
583impl_instance!(UART0, UART0, 20, 21); 666impl_instance!(UART0, UART0_IRQ, 20, 21);
584impl_instance!(UART1, UART1, 22, 23); 667impl_instance!(UART1, UART1_IRQ, 22, 23);
585 668
586pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 669pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
587pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 670pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}
diff --git a/tests/rp/.cargo/config.toml b/tests/rp/.cargo/config.toml
index 0330025e4..9611db3a0 100644
--- a/tests/rp/.cargo/config.toml
+++ b/tests/rp/.cargo/config.toml
@@ -3,7 +3,7 @@ build-std = ["core"]
3build-std-features = ["panic_immediate_abort"] 3build-std-features = ["panic_immediate_abort"]
4 4
5[target.'cfg(all(target_arch = "arm", target_os = "none"))'] 5[target.'cfg(all(target_arch = "arm", target_os = "none"))']
6#runner = "teleprobe client run --target bluepill-stm32f103c8 --elf" 6#runner = "teleprobe client run --target rpi-pico --elf"
7runner = "teleprobe local run --chip RP2040 --elf" 7runner = "teleprobe local run --chip RP2040 --elf"
8 8
9rustflags = [ 9rustflags = [
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index 7e2717ddf..503373759 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -20,6 +20,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
20embedded-hal-async = { version = "0.1.0-alpha.1" } 20embedded-hal-async = { version = "0.1.0-alpha.1" }
21panic-probe = { version = "0.3.0", features = ["print-defmt"] } 21panic-probe = { version = "0.3.0", features = ["print-defmt"] }
22futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 22futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
23embedded-io = { version = "0.3.0", features = ["async"] }
23 24
24[profile.dev] 25[profile.dev]
25debug = 2 26debug = 2
diff --git a/tests/rp/src/bin/uart_buffered.rs b/tests/rp/src/bin/uart_buffered.rs
new file mode 100644
index 000000000..9cc20bb98
--- /dev/null
+++ b/tests/rp/src/bin/uart_buffered.rs
@@ -0,0 +1,44 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::{assert_eq, *};
6use embassy_executor::Spawner;
7use embassy_rp::interrupt;
8use embassy_rp::uart::{BufferedUart, Config, State, Uart};
9use embedded_io::asynch::{Read, Write};
10use {defmt_rtt as _, panic_probe as _};
11
12#[embassy_executor::main]
13async fn main(_spawner: Spawner) {
14 let p = embassy_rp::init(Default::default());
15 info!("Hello World!");
16
17 let (tx, rx, uart) = (p.PIN_0, p.PIN_1, p.UART0);
18
19 let config = Config::default();
20 let uart = Uart::new_blocking(uart, tx, rx, config);
21
22 let irq = interrupt::take!(UART0_IRQ);
23 let tx_buf = &mut [0u8; 16];
24 let rx_buf = &mut [0u8; 16];
25 let mut state = State::new();
26 let mut uart = BufferedUart::new(&mut state, uart, irq, tx_buf, rx_buf);
27
28 // Make sure we send more bytes than fits in the FIFO, to test the actual
29 // bufferedUart.
30
31 let data = [
32 1_u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
33 30, 31, 32,
34 ];
35 uart.write_all(&data).await.unwrap();
36 info!("Done writing");
37
38 let mut buf = [0; 32];
39 uart.read_exact(&mut buf).await.unwrap();
40 assert_eq!(buf, data);
41
42 info!("Test OK");
43 cortex_m::asm::bkpt();
44}