aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/uart/buffered.rs340
-rw-r--r--embassy-rp/src/uart/mod.rs50
2 files changed, 340 insertions, 50 deletions
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index 0da5bfca1..32e5ddf14 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -28,30 +28,23 @@ impl State {
28} 28}
29 29
30pub struct BufferedUart<'d, T: Instance> { 30pub struct BufferedUart<'d, T: Instance> {
31 rx: BufferedUartRx<'d, T>, 31 pub(crate) rx: BufferedUartRx<'d, T>,
32 tx: BufferedUartTx<'d, T>, 32 pub(crate) tx: BufferedUartTx<'d, T>,
33} 33}
34 34
35pub struct BufferedUartRx<'d, T: Instance> { 35pub struct BufferedUartRx<'d, T: Instance> {
36 phantom: PhantomData<&'d mut T>, 36 pub(crate) phantom: PhantomData<&'d mut T>,
37} 37}
38 38
39pub struct BufferedUartTx<'d, T: Instance> { 39pub struct BufferedUartTx<'d, T: Instance> {
40 phantom: PhantomData<&'d mut T>, 40 pub(crate) phantom: PhantomData<&'d mut T>,
41} 41}
42 42
43fn init<'d, T: Instance + 'd>( 43pub(crate) fn init_buffers<'d, T: Instance + 'd>(
44 irq: PeripheralRef<'d, T::Interrupt>, 44 irq: PeripheralRef<'d, T::Interrupt>,
45 tx: Option<PeripheralRef<'d, AnyPin>>,
46 rx: Option<PeripheralRef<'d, AnyPin>>,
47 rts: Option<PeripheralRef<'d, AnyPin>>,
48 cts: Option<PeripheralRef<'d, AnyPin>>,
49 tx_buffer: &'d mut [u8], 45 tx_buffer: &'d mut [u8],
50 rx_buffer: &'d mut [u8], 46 rx_buffer: &'d mut [u8],
51 config: Config,
52) { 47) {
53 super::Uart::<'d, T, Async>::init(tx, rx, rts, cts, config);
54
55 let state = T::state(); 48 let state = T::state();
56 let len = tx_buffer.len(); 49 let len = tx_buffer.len();
57 unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) }; 50 unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
@@ -69,7 +62,13 @@ fn init<'d, T: Instance + 'd>(
69 // we clear it after it happens. The downside is that the we manually have 62 // we clear it after it happens. The downside is that the we manually have
70 // to pend the ISR when we want data transmission to start. 63 // to pend the ISR when we want data transmission to start.
71 let regs = T::regs(); 64 let regs = T::regs();
72 unsafe { regs.uartimsc().write_set(|w| w.set_txim(true)) }; 65 unsafe {
66 regs.uartimsc().write_set(|w| {
67 w.set_rxim(true);
68 w.set_rtim(true);
69 w.set_txim(true);
70 });
71 };
73 72
74 irq.set_handler(on_interrupt::<T>); 73 irq.set_handler(on_interrupt::<T>);
75 irq.unpend(); 74 irq.unpend();
@@ -87,16 +86,10 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
87 config: Config, 86 config: Config,
88 ) -> Self { 87 ) -> Self {
89 into_ref!(irq, tx, rx); 88 into_ref!(irq, tx, rx);
90 init::<T>( 89
91 irq, 90 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), Some(rx.map_into()), None, None, config);
92 Some(tx.map_into()), 91 init_buffers::<T>(irq, tx_buffer, rx_buffer);
93 Some(rx.map_into()), 92
94 None,
95 None,
96 tx_buffer,
97 rx_buffer,
98 config,
99 );
100 Self { 93 Self {
101 rx: BufferedUartRx { phantom: PhantomData }, 94 rx: BufferedUartRx { phantom: PhantomData },
102 tx: BufferedUartTx { phantom: PhantomData }, 95 tx: BufferedUartTx { phantom: PhantomData },
@@ -115,22 +108,34 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
115 config: Config, 108 config: Config,
116 ) -> Self { 109 ) -> Self {
117 into_ref!(irq, tx, rx, cts, rts); 110 into_ref!(irq, tx, rx, cts, rts);
118 init::<T>( 111
119 irq, 112 super::Uart::<'d, T, Async>::init(
120 Some(tx.map_into()), 113 Some(tx.map_into()),
121 Some(rx.map_into()), 114 Some(rx.map_into()),
122 Some(rts.map_into()), 115 Some(rts.map_into()),
123 Some(cts.map_into()), 116 Some(cts.map_into()),
124 tx_buffer,
125 rx_buffer,
126 config, 117 config,
127 ); 118 );
119 init_buffers::<T>(irq, tx_buffer, rx_buffer);
120
128 Self { 121 Self {
129 rx: BufferedUartRx { phantom: PhantomData }, 122 rx: BufferedUartRx { phantom: PhantomData },
130 tx: BufferedUartTx { phantom: PhantomData }, 123 tx: BufferedUartTx { phantom: PhantomData },
131 } 124 }
132 } 125 }
133 126
127 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
128 self.tx.blocking_write(buffer)
129 }
130
131 pub fn blocking_flush(&mut self) -> Result<(), Error> {
132 self.tx.blocking_flush()
133 }
134
135 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
136 self.rx.blocking_read(buffer)
137 }
138
134 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) { 139 pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
135 (self.rx, self.tx) 140 (self.rx, self.tx)
136 } 141 }
@@ -145,7 +150,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
145 config: Config, 150 config: Config,
146 ) -> Self { 151 ) -> Self {
147 into_ref!(irq, rx); 152 into_ref!(irq, rx);
148 init::<T>(irq, None, Some(rx.map_into()), None, None, &mut [], rx_buffer, config); 153
154 super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), None, None, config);
155 init_buffers::<T>(irq, &mut [], rx_buffer);
156
149 Self { phantom: PhantomData } 157 Self { phantom: PhantomData }
150 } 158 }
151 159
@@ -158,16 +166,10 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
158 config: Config, 166 config: Config,
159 ) -> Self { 167 ) -> Self {
160 into_ref!(irq, rx, rts); 168 into_ref!(irq, rx, rts);
161 init::<T>( 169
162 irq, 170 super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), Some(rts.map_into()), None, config);
163 None, 171 init_buffers::<T>(irq, &mut [], rx_buffer);
164 Some(rx.map_into()), 172
165 Some(rts.map_into()),
166 None,
167 &mut [],
168 rx_buffer,
169 config,
170 );
171 Self { phantom: PhantomData } 173 Self { phantom: PhantomData }
172 } 174 }
173 175
@@ -199,6 +201,32 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
199 }) 201 })
200 } 202 }
201 203
204 pub fn blocking_read(&mut self, buf: &mut [u8]) -> Result<(), Error> {
205 loop {
206 let state = T::state();
207 let mut rx_reader = unsafe { state.rx_buf.reader() };
208 let n = rx_reader.pop(|data| {
209 let n = data.len().min(buf.len());
210 buf[..n].copy_from_slice(&data[..n]);
211 n
212 });
213
214 if n > 0 {
215 // (Re-)Enable the interrupt to receive more data in case it was
216 // disabled because the buffer was full.
217 let regs = T::regs();
218 unsafe {
219 regs.uartimsc().write_set(|w| {
220 w.set_rxim(true);
221 w.set_rtim(true);
222 });
223 }
224
225 return Ok(());
226 }
227 }
228 }
229
202 fn fill_buf<'a>() -> impl Future<Output = Result<&'a [u8], Error>> { 230 fn fill_buf<'a>() -> impl Future<Output = Result<&'a [u8], Error>> {
203 poll_fn(move |cx| { 231 poll_fn(move |cx| {
204 let state = T::state(); 232 let state = T::state();
@@ -240,7 +268,10 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
240 config: Config, 268 config: Config,
241 ) -> Self { 269 ) -> Self {
242 into_ref!(irq, tx); 270 into_ref!(irq, tx);
243 init::<T>(irq, Some(tx.map_into()), None, None, None, tx_buffer, &mut [], config); 271
272 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, None, config);
273 init_buffers::<T>(irq, tx_buffer, &mut []);
274
244 Self { phantom: PhantomData } 275 Self { phantom: PhantomData }
245 } 276 }
246 277
@@ -253,16 +284,10 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
253 config: Config, 284 config: Config,
254 ) -> Self { 285 ) -> Self {
255 into_ref!(irq, tx, cts); 286 into_ref!(irq, tx, cts);
256 init::<T>( 287
257 irq, 288 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, Some(cts.map_into()), config);
258 Some(tx.map_into()), 289 init_buffers::<T>(irq, tx_buffer, &mut []);
259 None, 290
260 None,
261 Some(cts.map_into()),
262 tx_buffer,
263 &mut [],
264 config,
265 );
266 Self { phantom: PhantomData } 291 Self { phantom: PhantomData }
267 } 292 }
268 293
@@ -300,6 +325,36 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
300 Poll::Ready(Ok(())) 325 Poll::Ready(Ok(()))
301 }) 326 })
302 } 327 }
328
329 pub fn blocking_write(&mut self, buf: &[u8]) -> Result<(), Error> {
330 loop {
331 let state = T::state();
332 let mut tx_writer = unsafe { state.tx_buf.writer() };
333 let n = tx_writer.push(|data| {
334 let n = data.len().min(buf.len());
335 data[..n].copy_from_slice(&buf[..n]);
336 n
337 });
338
339 if n != 0 {
340 // The TX interrupt only triggers when the there was data in the
341 // FIFO and the number of bytes drops below a threshold. When the
342 // FIFO was empty we have to manually pend the interrupt to shovel
343 // TX data from the buffer into the FIFO.
344 unsafe { T::Interrupt::steal() }.pend();
345 return Ok(());
346 }
347 }
348 }
349
350 pub fn blocking_flush(&mut self) -> Result<(), Error> {
351 loop {
352 let state = T::state();
353 if state.tx_buf.is_empty() {
354 return Ok(());
355 }
356 }
357 }
303} 358}
304 359
305impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { 360impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> {
@@ -477,3 +532,190 @@ impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUartTx<'d, T>
477 Self::flush().await 532 Self::flush().await
478 } 533 }
479} 534}
535
536mod eh02 {
537 use super::*;
538
539 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUartRx<'d, T> {
540 type Error = Error;
541
542 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
543 let r = T::regs();
544 unsafe {
545 if r.uartfr().read().rxfe() {
546 return Err(nb::Error::WouldBlock);
547 }
548
549 let dr = r.uartdr().read();
550
551 if dr.oe() {
552 Err(nb::Error::Other(Error::Overrun))
553 } else if dr.be() {
554 Err(nb::Error::Other(Error::Break))
555 } else if dr.pe() {
556 Err(nb::Error::Other(Error::Parity))
557 } else if dr.fe() {
558 Err(nb::Error::Other(Error::Framing))
559 } else {
560 Ok(dr.data())
561 }
562 }
563 }
564 }
565
566 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUartTx<'d, T> {
567 type Error = Error;
568
569 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
570 self.blocking_write(buffer)
571 }
572
573 fn bflush(&mut self) -> Result<(), Self::Error> {
574 self.blocking_flush()
575 }
576 }
577
578 impl<'d, T: Instance> embedded_hal_02::serial::Read<u8> for BufferedUart<'d, T> {
579 type Error = Error;
580
581 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
582 embedded_hal_02::serial::Read::read(&mut self.rx)
583 }
584 }
585
586 impl<'d, T: Instance> embedded_hal_02::blocking::serial::Write<u8> for BufferedUart<'d, T> {
587 type Error = Error;
588
589 fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
590 self.blocking_write(buffer)
591 }
592
593 fn bflush(&mut self) -> Result<(), Self::Error> {
594 self.blocking_flush()
595 }
596 }
597}
598
599#[cfg(feature = "unstable-traits")]
600mod eh1 {
601 use super::*;
602
603 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for BufferedUart<'d, T> {
604 type Error = Error;
605 }
606
607 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for BufferedUartTx<'d, T> {
608 type Error = Error;
609 }
610
611 impl<'d, T: Instance> embedded_hal_1::serial::ErrorType for BufferedUartRx<'d, T> {
612 type Error = Error;
613 }
614
615 impl<'d, T: Instance> embedded_hal_nb::serial::Read for BufferedUartRx<'d, T> {
616 fn read(&mut self) -> nb::Result<u8, Self::Error> {
617 embedded_hal_02::serial::Read::read(self)
618 }
619 }
620
621 impl<'d, T: Instance> embedded_hal_1::serial::Write for BufferedUartTx<'d, T> {
622 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
623 self.blocking_write(buffer)
624 }
625
626 fn flush(&mut self) -> Result<(), Self::Error> {
627 self.blocking_flush()
628 }
629 }
630
631 impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUartTx<'d, T> {
632 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
633 self.blocking_write(&[char]).map_err(nb::Error::Other)
634 }
635
636 fn flush(&mut self) -> nb::Result<(), Self::Error> {
637 self.blocking_flush().map_err(nb::Error::Other)
638 }
639 }
640
641 impl<'d, T: Instance> embedded_hal_nb::serial::Read for BufferedUart<'d, T> {
642 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
643 embedded_hal_02::serial::Read::read(&mut self.rx)
644 }
645 }
646
647 impl<'d, T: Instance> embedded_hal_1::serial::Write for BufferedUart<'d, T> {
648 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
649 self.blocking_write(buffer)
650 }
651
652 fn flush(&mut self) -> Result<(), Self::Error> {
653 self.blocking_flush()
654 }
655 }
656
657 impl<'d, T: Instance> embedded_hal_nb::serial::Write for BufferedUart<'d, T> {
658 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
659 self.blocking_write(&[char]).map_err(nb::Error::Other)
660 }
661
662 fn flush(&mut self) -> nb::Result<(), Self::Error> {
663 self.blocking_flush().map_err(nb::Error::Other)
664 }
665 }
666}
667
668#[cfg(all(
669 feature = "unstable-traits",
670 feature = "nightly",
671 feature = "_todo_embedded_hal_serial"
672))]
673mod eha {
674 use core::future::Future;
675
676 use super::*;
677
678 impl<'d, T: Instance> embedded_hal_async::serial::Write for BufferedUartTx<'d, T> {
679 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
680
681 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
682 Self::write(buf)
683 }
684
685 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
686
687 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
688 Self::flush()
689 }
690 }
691
692 impl<'d, T: Instance> embedded_hal_async::serial::Read for BufferedUartRx<'d, T> {
693 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
694
695 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
696 Self::read(buf)
697 }
698 }
699
700 impl<'d, T: Instance> embedded_hal_async::serial::Write for BufferedUart<'d, T> {
701 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
702
703 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
704 BufferedUartTx::<'d, T>::write(buf)
705 }
706
707 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
708
709 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
710 BufferedUartTx::<'d, T>::flush()
711 }
712 }
713
714 impl<'d, T: Instance> embedded_hal_async::serial::Read for BufferedUart<'d, T> {
715 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
716
717 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
718 BufferedUartRx::<'d, T>::read(buf)
719 }
720 }
721}
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index 42b3671a0..97f4463e5 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -1,11 +1,12 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_cortex_m::interrupt::InterruptExt;
3use embassy_hal_common::{into_ref, PeripheralRef}; 4use embassy_hal_common::{into_ref, PeripheralRef};
4 5
5use crate::dma::{AnyChannel, Channel}; 6use crate::dma::{AnyChannel, Channel};
6use crate::gpio::sealed::Pin; 7use crate::gpio::sealed::Pin;
7use crate::gpio::AnyPin; 8use crate::gpio::AnyPin;
8use crate::{pac, peripherals, Peripheral}; 9use crate::{pac, peripherals, Peripheral, RegExt};
9 10
10#[cfg(feature = "nightly")] 11#[cfg(feature = "nightly")]
11mod buffered; 12mod buffered;
@@ -135,6 +136,21 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
135 } 136 }
136} 137}
137 138
139impl<'d, T: Instance> UartTx<'d, T, Blocking> {
140 #[cfg(feature = "nightly")]
141 pub fn into_buffered(
142 self,
143 irq: impl Peripheral<P = T::Interrupt> + 'd,
144 tx_buffer: &'d mut [u8],
145 ) -> BufferedUartTx<'d, T> {
146 into_ref!(irq);
147
148 buffered::init_buffers::<T>(irq, tx_buffer, &mut []);
149
150 BufferedUartTx { phantom: PhantomData }
151 }
152}
153
138impl<'d, T: Instance> UartTx<'d, T, Async> { 154impl<'d, T: Instance> UartTx<'d, T, Async> {
139 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { 155 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
140 let ch = self.tx_dma.as_mut().unwrap(); 156 let ch = self.tx_dma.as_mut().unwrap();
@@ -200,6 +216,21 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
200 } 216 }
201} 217}
202 218
219impl<'d, T: Instance> UartRx<'d, T, Blocking> {
220 #[cfg(feature = "nightly")]
221 pub fn into_buffered(
222 self,
223 irq: impl Peripheral<P = T::Interrupt> + 'd,
224 rx_buffer: &'d mut [u8],
225 ) -> BufferedUartRx<'d, T> {
226 into_ref!(irq);
227
228 buffered::init_buffers::<T>(irq, &mut [], rx_buffer);
229
230 BufferedUartRx { phantom: PhantomData }
231 }
232}
233
203impl<'d, T: Instance> UartRx<'d, T, Async> { 234impl<'d, T: Instance> UartRx<'d, T, Async> {
204 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 235 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
205 let ch = self.rx_dma.as_mut().unwrap(); 236 let ch = self.rx_dma.as_mut().unwrap();
@@ -249,6 +280,23 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
249 config, 280 config,
250 ) 281 )
251 } 282 }
283
284 #[cfg(feature = "nightly")]
285 pub fn into_buffered(
286 self,
287 irq: impl Peripheral<P = T::Interrupt> + 'd,
288 tx_buffer: &'d mut [u8],
289 rx_buffer: &'d mut [u8],
290 ) -> BufferedUart<'d, T> {
291 into_ref!(irq);
292
293 buffered::init_buffers::<T>(irq, tx_buffer, rx_buffer);
294
295 BufferedUart {
296 rx: BufferedUartRx { phantom: PhantomData },
297 tx: BufferedUartTx { phantom: PhantomData },
298 }
299 }
252} 300}
253 301
254impl<'d, T: Instance> Uart<'d, T, Async> { 302impl<'d, T: Instance> Uart<'d, T, Async> {