diff options
| author | Mathias <[email protected]> | 2023-02-16 08:47:22 +0100 |
|---|---|---|
| committer | Mathias <[email protected]> | 2023-03-14 10:36:30 +0100 |
| commit | bce1ce7dcb7fff272a2658a8dda08b70af679e7b (patch) | |
| tree | c5ba7a7deca35b1aaeada5c0afa4c5a2f04e8cac | |
| parent | 055597063f2d3f1156a9f8076c601dd300d85542 (diff) | |
Allow upgrading a blocking uart to a BufferedUart, and implement blocking serial traits for BufferedUart
| -rw-r--r-- | embassy-rp/src/uart/buffered.rs | 340 | ||||
| -rw-r--r-- | embassy-rp/src/uart/mod.rs | 50 |
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 | ||
| 30 | pub struct BufferedUart<'d, T: Instance> { | 30 | pub 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 | ||
| 35 | pub struct BufferedUartRx<'d, T: Instance> { | 35 | pub struct BufferedUartRx<'d, T: Instance> { |
| 36 | phantom: PhantomData<&'d mut T>, | 36 | pub(crate) phantom: PhantomData<&'d mut T>, |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | pub struct BufferedUartTx<'d, T: Instance> { | 39 | pub struct BufferedUartTx<'d, T: Instance> { |
| 40 | phantom: PhantomData<&'d mut T>, | 40 | pub(crate) phantom: PhantomData<&'d mut T>, |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | fn init<'d, T: Instance + 'd>( | 43 | pub(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 | ||
| 305 | impl<'d, T: Instance> Drop for BufferedUartRx<'d, T> { | 360 | impl<'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 | |||
| 536 | mod 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")] | ||
| 600 | mod 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 | ))] | ||
| 673 | mod 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 @@ | |||
| 1 | use core::marker::PhantomData; | 1 | use core::marker::PhantomData; |
| 2 | 2 | ||
| 3 | use embassy_cortex_m::interrupt::InterruptExt; | ||
| 3 | use embassy_hal_common::{into_ref, PeripheralRef}; | 4 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 4 | 5 | ||
| 5 | use crate::dma::{AnyChannel, Channel}; | 6 | use crate::dma::{AnyChannel, Channel}; |
| 6 | use crate::gpio::sealed::Pin; | 7 | use crate::gpio::sealed::Pin; |
| 7 | use crate::gpio::AnyPin; | 8 | use crate::gpio::AnyPin; |
| 8 | use crate::{pac, peripherals, Peripheral}; | 9 | use crate::{pac, peripherals, Peripheral, RegExt}; |
| 9 | 10 | ||
| 10 | #[cfg(feature = "nightly")] | 11 | #[cfg(feature = "nightly")] |
| 11 | mod buffered; | 12 | mod buffered; |
| @@ -135,6 +136,21 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> { | |||
| 135 | } | 136 | } |
| 136 | } | 137 | } |
| 137 | 138 | ||
| 139 | impl<'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 | |||
| 138 | impl<'d, T: Instance> UartTx<'d, T, Async> { | 154 | impl<'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 | ||
| 219 | impl<'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 | |||
| 203 | impl<'d, T: Instance> UartRx<'d, T, Async> { | 234 | impl<'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 | ||
| 254 | impl<'d, T: Instance> Uart<'d, T, Async> { | 302 | impl<'d, T: Instance> Uart<'d, T, Async> { |
