aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-08-26 09:05:12 +0200
committerDario Nieuwenhuis <[email protected]>2022-09-26 20:34:55 +0200
commitee76831f93e792757bf43136be712c343c4d5336 (patch)
tree8bd9604b974e357e1c976069dd45cb2c7e034ecb
parent75e93cc142c1c017e94dd28f6f04d3a4cb1ac67b (diff)
Add BufferedUart implementation, and feature-guard time-driver initialization, to free up TIMER peripheral if not used with embassy executor
-rw-r--r--embassy-rp/Cargo.toml1
-rw-r--r--embassy-rp/src/uart/buffered.rs286
-rw-r--r--embassy-rp/src/uart/mod.rs (renamed from embassy-rp/src/uart.rs)84
3 files changed, 369 insertions, 2 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index c43fd7e72..211b6a401 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -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..c31af8018
--- /dev/null
+++ b/embassy-rp/src/uart/buffered.rs
@@ -0,0 +1,286 @@
1use core::future::Future;
2use core::task::Poll;
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;
8use futures::future::poll_fn;
9
10use super::*;
11
12pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>);
13impl<'d, T: Instance> State<'d, T> {
14 pub fn new() -> Self {
15 Self(StateStorage::new())
16 }
17}
18
19struct StateInner<'d, T: Instance> {
20 phantom: PhantomData<&'d mut T>,
21
22 rx_waker: WakerRegistration,
23 rx: RingBuffer<'d>,
24
25 tx_waker: WakerRegistration,
26 tx: RingBuffer<'d>,
27}
28
29unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {}
30unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {}
31
32pub struct BufferedUart<'d, T: Instance> {
33 inner: PeripheralMutex<'d, StateInner<'d, T>>,
34}
35
36impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {}
37
38impl<'d, T: Instance> BufferedUart<'d, T> {
39 pub fn new<M: Mode>(
40 state: &'d mut State<'d, T>,
41 _uart: Uart<'d, T, M>,
42 irq: impl Peripheral<P = T::Interrupt> + 'd,
43 tx_buffer: &'d mut [u8],
44 rx_buffer: &'d mut [u8],
45 ) -> BufferedUart<'d, T> {
46 into_ref!(irq);
47
48 let r = T::regs();
49 unsafe {
50 r.uartimsc().modify(|w| {
51 // TODO: Should and more or fewer interrupts be enabled?
52 w.set_rxim(true);
53 w.set_rtim(true);
54 });
55 }
56
57 Self {
58 inner: PeripheralMutex::new(irq, &mut state.0, move || StateInner {
59 phantom: PhantomData,
60 tx: RingBuffer::new(tx_buffer),
61 tx_waker: WakerRegistration::new(),
62
63 rx: RingBuffer::new(rx_buffer),
64 rx_waker: WakerRegistration::new(),
65 }),
66 }
67 }
68}
69
70impl<'d, T: Instance> StateInner<'d, T>
71where
72 Self: 'd,
73{
74 fn on_rx(&mut self) {
75 let r = T::regs();
76 unsafe {
77 let ris = r.uartris().read();
78 // Clear interrupt flags
79 r.uarticr().write(|w| {
80 w.set_rxic(true);
81 w.set_rtic(true);
82 });
83
84 if ris.rxris() {
85 if ris.peris() {
86 warn!("Parity error");
87 }
88 if ris.feris() {
89 warn!("Framing error");
90 }
91 if ris.beris() {
92 warn!("Break error");
93 }
94 if ris.oeris() {
95 warn!("Overrun error");
96 }
97
98 let buf = self.rx.push_buf();
99 if !buf.is_empty() {
100 buf[0] = r.uartdr().read().data();
101 self.rx.push(1);
102 } else {
103 warn!("RX buffer full, discard received byte");
104 }
105
106 if self.rx.is_full() {
107 self.rx_waker.wake();
108 }
109 }
110
111 if ris.rtris() {
112 self.rx_waker.wake();
113 };
114 }
115 }
116
117 fn on_tx(&mut self) {
118 let r = T::regs();
119 unsafe {
120 let ris = r.uartris().read();
121 // Clear interrupt flags
122 r.uarticr().write(|w| {
123 w.set_rtic(true);
124 });
125
126 if ris.txris() {
127 let buf = self.tx.pop_buf();
128 if !buf.is_empty() {
129 r.uartimsc().modify(|w| {
130 w.set_txim(true);
131 });
132 r.uartdr().write(|w| w.set_data(buf[0].into()));
133 self.tx.pop(1);
134 self.tx_waker.wake();
135 } else {
136 // Disable interrupt until we have something to transmit again
137 r.uartimsc().modify(|w| {
138 w.set_txim(false);
139 });
140 }
141 }
142 }
143 }
144}
145
146impl<'d, T: Instance> PeripheralState for StateInner<'d, T>
147where
148 Self: 'd,
149{
150 type Interrupt = T::Interrupt;
151 fn on_interrupt(&mut self) {
152 self.on_rx();
153 self.on_tx();
154 }
155}
156
157impl embedded_io::Error for Error {
158 fn kind(&self) -> embedded_io::ErrorKind {
159 embedded_io::ErrorKind::Other
160 }
161}
162
163impl<'d, T: Instance> embedded_io::Io for BufferedUart<'d, T> {
164 type Error = Error;
165}
166
167impl<'d, T: Instance + 'd> embedded_io::asynch::Read for BufferedUart<'d, T> {
168 type ReadFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
169 where
170 Self: 'a;
171
172 fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> {
173 poll_fn(move |cx| {
174 let mut do_pend = false;
175 let res = self.inner.with(|state| {
176 compiler_fence(Ordering::SeqCst);
177
178 // We have data ready in buffer? Return it.
179 let data = state.rx.pop_buf();
180 if !data.is_empty() {
181 let len = data.len().min(buf.len());
182 buf[..len].copy_from_slice(&data[..len]);
183
184 if state.rx.is_full() {
185 do_pend = true;
186 }
187 state.rx.pop(len);
188
189 return Poll::Ready(Ok(len));
190 }
191
192 state.rx_waker.register(cx.waker());
193 Poll::Pending
194 });
195
196 if do_pend {
197 self.inner.pend();
198 }
199
200 res
201 })
202 }
203}
204
205impl<'d, T: Instance + 'd> embedded_io::asynch::BufRead for BufferedUart<'d, T> {
206 type FillBufFuture<'a> = impl Future<Output = Result<&'a [u8], Self::Error>>
207 where
208 Self: 'a;
209
210 fn fill_buf<'a>(&'a mut self) -> Self::FillBufFuture<'a> {
211 poll_fn(move |cx| {
212 self.inner.with(|state| {
213 compiler_fence(Ordering::SeqCst);
214
215 // We have data ready in buffer? Return it.
216 let buf = state.rx.pop_buf();
217 if !buf.is_empty() {
218 let buf: &[u8] = buf;
219 // Safety: buffer lives as long as uart
220 let buf: &[u8] = unsafe { core::mem::transmute(buf) };
221 return Poll::Ready(Ok(buf));
222 }
223
224 state.rx_waker.register(cx.waker());
225 Poll::<Result<&[u8], Self::Error>>::Pending
226 })
227 })
228 }
229
230 fn consume(&mut self, amt: usize) {
231 let signal = self.inner.with(|state| {
232 let full = state.rx.is_full();
233 state.rx.pop(amt);
234 full
235 });
236 if signal {
237 self.inner.pend();
238 }
239 }
240}
241
242impl<'d, T: Instance + 'd> embedded_io::asynch::Write for BufferedUart<'d, T> {
243 type WriteFuture<'a> = impl Future<Output = Result<usize, Self::Error>>
244 where
245 Self: 'a;
246
247 fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> {
248 poll_fn(move |cx| {
249 let (poll, empty) = self.inner.with(|state| {
250 let empty = state.tx.is_empty();
251 let tx_buf = state.tx.push_buf();
252 if tx_buf.is_empty() {
253 state.tx_waker.register(cx.waker());
254 return (Poll::Pending, empty);
255 }
256
257 let n = core::cmp::min(tx_buf.len(), buf.len());
258 tx_buf[..n].copy_from_slice(&buf[..n]);
259 state.tx.push(n);
260
261 (Poll::Ready(Ok(n)), empty)
262 });
263 if empty {
264 self.inner.pend();
265 }
266 poll
267 })
268 }
269
270 type FlushFuture<'a> = impl Future<Output = Result<(), Self::Error>>
271 where
272 Self: 'a;
273
274 fn flush<'a>(&'a mut self) -> Self::FlushFuture<'a> {
275 poll_fn(move |cx| {
276 self.inner.with(|state| {
277 if !state.tx.is_empty() {
278 state.tx_waker.register(cx.waker());
279 return Poll::Pending;
280 }
281
282 Poll::Ready(Ok(()))
283 })
284 })
285 }
286}
diff --git a/embassy-rp/src/uart.rs b/embassy-rp/src/uart/mod.rs
index 987b716b4..3b71d87be 100644
--- a/embassy-rp/src/uart.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -475,6 +475,76 @@ mod eh1 {
475 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> { 475 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::ErrorType for UartRx<'d, T, M> {
476 type Error = Error; 476 type Error = Error;
477 } 477 }
478
479 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Read for UartRx<'d, T, M> {
480 fn read(&mut self) -> nb::Result<u8, Self::Error> {
481 let r = T::regs();
482 unsafe {
483 let dr = r.uartdr().read();
484
485 if dr.oe() {
486 Err(nb::Error::Other(Error::Overrun))
487 } else if dr.be() {
488 Err(nb::Error::Other(Error::Break))
489 } else if dr.pe() {
490 Err(nb::Error::Other(Error::Parity))
491 } else if dr.fe() {
492 Err(nb::Error::Other(Error::Framing))
493 } else if dr.fe() {
494 Ok(dr.data())
495 } else {
496 Err(nb::Error::WouldBlock)
497 }
498 }
499 }
500 }
501
502 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::blocking::Write for UartTx<'d, T, M> {
503 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
504 self.blocking_write(buffer)
505 }
506
507 fn flush(&mut self) -> Result<(), Self::Error> {
508 self.blocking_flush()
509 }
510 }
511
512 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Write for UartTx<'d, T, M> {
513 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
514 self.blocking_write(&[char]).map_err(nb::Error::Other)
515 }
516
517 fn flush(&mut self) -> nb::Result<(), Self::Error> {
518 self.blocking_flush().map_err(nb::Error::Other)
519 }
520 }
521
522 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Read for Uart<'d, T, M> {
523 fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> {
524 embedded_hal_02::serial::Read::read(&mut self.rx)
525 }
526 }
527
528 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::blocking::Write for Uart<'d, T, M> {
529 fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
530 self.blocking_write(buffer)
531 }
532
533 fn flush(&mut self) -> Result<(), Self::Error> {
534 self.blocking_flush()
535 }
536 }
537
538 impl<'d, T: Instance, M: Mode> embedded_hal_1::serial::nb::Write for Uart<'d, T, M> {
539 fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
540 self.blocking_write(&[char]).map_err(nb::Error::Other)
541 }
542
543 fn flush(&mut self) -> nb::Result<(), Self::Error> {
544 self.blocking_flush().map_err(nb::Error::Other)
545 }
546 }
547
478} 548}
479 549
480#[cfg(all( 550#[cfg(all(
@@ -532,6 +602,12 @@ mod eha {
532 } 602 }
533} 603}
534 604
605#[cfg(feature = "nightly")]
606mod buffered;
607#[cfg(feature = "nightly")]
608pub use buffered::*;
609
610
535mod sealed { 611mod sealed {
536 use super::*; 612 use super::*;
537 613
@@ -541,6 +617,8 @@ mod sealed {
541 const TX_DREQ: u8; 617 const TX_DREQ: u8;
542 const RX_DREQ: u8; 618 const RX_DREQ: u8;
543 619
620 type Interrupt: crate::interrupt::Interrupt;
621
544 fn regs() -> pac::uart::Uart; 622 fn regs() -> pac::uart::Uart;
545 } 623 }
546 pub trait TxPin<T: Instance> {} 624 pub trait TxPin<T: Instance> {}
@@ -571,6 +649,8 @@ macro_rules! impl_instance {
571 impl sealed::Instance for peripherals::$inst { 649 impl sealed::Instance for peripherals::$inst {
572 const TX_DREQ: u8 = $tx_dreq; 650 const TX_DREQ: u8 = $tx_dreq;
573 const RX_DREQ: u8 = $rx_dreq; 651 const RX_DREQ: u8 = $rx_dreq;
652
653 type Interrupt = crate::interrupt::$irq;
574 654
575 fn regs() -> pac::uart::Uart { 655 fn regs() -> pac::uart::Uart {
576 pac::$inst 656 pac::$inst
@@ -580,8 +660,8 @@ macro_rules! impl_instance {
580 }; 660 };
581} 661}
582 662
583impl_instance!(UART0, UART0, 20, 21); 663impl_instance!(UART0, UART0_IRQ, 20, 21);
584impl_instance!(UART1, UART1, 22, 23); 664impl_instance!(UART1, UART1_IRQ, 22, 23);
585 665
586pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {} 666pub trait TxPin<T: Instance>: sealed::TxPin<T> + crate::gpio::Pin {}
587pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {} 667pub trait RxPin<T: Instance>: sealed::RxPin<T> + crate::gpio::Pin {}