aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarnaby Walters <[email protected]>2023-12-19 16:41:00 +0100
committerBarnaby Walters <[email protected]>2023-12-19 16:41:00 +0100
commitf97ef61ef896fa3abff7e35d78823c36ff50d9a8 (patch)
treec0d6ce4925561cb06e636d44ffa0fc7739501e55
parent5e76c8b41a05c89652a6c53061107482adc4125f (diff)
Documented usart public API
-rw-r--r--.vscode/settings.json6
-rw-r--r--embassy-stm32/src/usart/buffered.rs12
-rw-r--r--embassy-stm32/src/usart/mod.rs54
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs7
4 files changed, 70 insertions, 9 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index d46ce603b..016df796d 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -17,12 +17,12 @@
17 //"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf", 17 //"rust-analyzer.cargo.target": "thumbv8m.main-none-eabihf",
18 "rust-analyzer.cargo.features": [ 18 "rust-analyzer.cargo.features": [
19 // Uncomment if the example has a "nightly" feature. 19 // Uncomment if the example has a "nightly" feature.
20 "nightly", 20 //"nightly",
21 ], 21 ],
22 "rust-analyzer.linkedProjects": [ 22 "rust-analyzer.linkedProjects": [
23 // Uncomment ONE line for the chip you want to work on. 23 // Uncomment ONE line for the chip you want to work on.
24 // This makes rust-analyzer work on the example crate and all its dependencies. 24 // This makes rust-analyzer work on the example crate and all its dependencies.
25 "examples/nrf52840/Cargo.toml", 25 //"examples/nrf52840/Cargo.toml",
26 // "examples/nrf52840-rtic/Cargo.toml", 26 // "examples/nrf52840-rtic/Cargo.toml",
27 // "examples/nrf5340/Cargo.toml", 27 // "examples/nrf5340/Cargo.toml",
28 // "examples/nrf-rtos-trace/Cargo.toml", 28 // "examples/nrf-rtos-trace/Cargo.toml",
@@ -39,7 +39,7 @@
39 // "examples/stm32g0/Cargo.toml", 39 // "examples/stm32g0/Cargo.toml",
40 // "examples/stm32g4/Cargo.toml", 40 // "examples/stm32g4/Cargo.toml",
41 // "examples/stm32h5/Cargo.toml", 41 // "examples/stm32h5/Cargo.toml",
42 // "examples/stm32h7/Cargo.toml", 42 "examples/stm32h7/Cargo.toml",
43 // "examples/stm32l0/Cargo.toml", 43 // "examples/stm32l0/Cargo.toml",
44 // "examples/stm32l1/Cargo.toml", 44 // "examples/stm32l1/Cargo.toml",
45 // "examples/stm32l4/Cargo.toml", 45 // "examples/stm32l4/Cargo.toml",
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index a2e4ceaae..962547bd7 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -82,6 +82,7 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
82 } 82 }
83} 83}
84 84
85/// Buffered UART State
85pub struct State { 86pub struct State {
86 rx_waker: AtomicWaker, 87 rx_waker: AtomicWaker,
87 rx_buf: RingBuffer, 88 rx_buf: RingBuffer,
@@ -91,6 +92,7 @@ pub struct State {
91} 92}
92 93
93impl State { 94impl State {
95 /// Create new state
94 pub const fn new() -> Self { 96 pub const fn new() -> Self {
95 Self { 97 Self {
96 rx_buf: RingBuffer::new(), 98 rx_buf: RingBuffer::new(),
@@ -101,15 +103,18 @@ impl State {
101 } 103 }
102} 104}
103 105
106/// Bidirectional buffered UART
104pub struct BufferedUart<'d, T: BasicInstance> { 107pub struct BufferedUart<'d, T: BasicInstance> {
105 rx: BufferedUartRx<'d, T>, 108 rx: BufferedUartRx<'d, T>,
106 tx: BufferedUartTx<'d, T>, 109 tx: BufferedUartTx<'d, T>,
107} 110}
108 111
112/// Tx-only buffered UART
109pub struct BufferedUartTx<'d, T: BasicInstance> { 113pub struct BufferedUartTx<'d, T: BasicInstance> {
110 phantom: PhantomData<&'d mut T>, 114 phantom: PhantomData<&'d mut T>,
111} 115}
112 116
117/// Rx-only buffered UART
113pub struct BufferedUartRx<'d, T: BasicInstance> { 118pub struct BufferedUartRx<'d, T: BasicInstance> {
114 phantom: PhantomData<&'d mut T>, 119 phantom: PhantomData<&'d mut T>,
115} 120}
@@ -142,6 +147,7 @@ impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> {
142} 147}
143 148
144impl<'d, T: BasicInstance> BufferedUart<'d, T> { 149impl<'d, T: BasicInstance> BufferedUart<'d, T> {
150 /// Create a new bidirectional buffered UART driver
145 pub fn new( 151 pub fn new(
146 peri: impl Peripheral<P = T> + 'd, 152 peri: impl Peripheral<P = T> + 'd,
147 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 153 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -158,6 +164,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
158 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 164 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
159 } 165 }
160 166
167 /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins
161 pub fn new_with_rtscts( 168 pub fn new_with_rtscts(
162 peri: impl Peripheral<P = T> + 'd, 169 peri: impl Peripheral<P = T> + 'd,
163 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 170 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -185,6 +192,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
185 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 192 Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
186 } 193 }
187 194
195 /// Create a new bidirectional buffered UART driver with a driver-enable pin
188 #[cfg(not(any(usart_v1, usart_v2)))] 196 #[cfg(not(any(usart_v1, usart_v2)))]
189 pub fn new_with_de( 197 pub fn new_with_de(
190 peri: impl Peripheral<P = T> + 'd, 198 peri: impl Peripheral<P = T> + 'd,
@@ -246,10 +254,12 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
246 }) 254 })
247 } 255 }
248 256
257 /// Split the driver into a Tx and Rx part (useful for sending to separate tasks)
249 pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) { 258 pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
250 (self.tx, self.rx) 259 (self.tx, self.rx)
251 } 260 }
252 261
262 /// Reconfigure the driver
253 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 263 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
254 reconfigure::<T>(config)?; 264 reconfigure::<T>(config)?;
255 265
@@ -337,6 +347,7 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
337 } 347 }
338 } 348 }
339 349
350 /// Reconfigure the driver
340 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 351 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
341 reconfigure::<T>(config)?; 352 reconfigure::<T>(config)?;
342 353
@@ -418,6 +429,7 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
418 } 429 }
419 } 430 }
420 431
432 /// Reconfigure the driver
421 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 433 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
422 reconfigure::<T>(config)?; 434 reconfigure::<T>(config)?;
423 435
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index e2e3bd3eb..8a0c85d2c 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -1,5 +1,6 @@
1//! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART) 1//! Universal Synchronous/Asynchronous Receiver Transmitter (USART, UART, LPUART)
2#![macro_use] 2#![macro_use]
3#![warn(missing_docs)]
3 4
4use core::future::poll_fn; 5use core::future::poll_fn;
5use core::marker::PhantomData; 6use core::marker::PhantomData;
@@ -77,21 +78,29 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
77 78
78#[derive(Clone, Copy, PartialEq, Eq, Debug)] 79#[derive(Clone, Copy, PartialEq, Eq, Debug)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))] 80#[cfg_attr(feature = "defmt", derive(defmt::Format))]
81/// Number of data bits
80pub enum DataBits { 82pub enum DataBits {
83 /// 8 Data Bits
81 DataBits8, 84 DataBits8,
85 /// 9 Data Bits
82 DataBits9, 86 DataBits9,
83} 87}
84 88
85#[derive(Clone, Copy, PartialEq, Eq, Debug)] 89#[derive(Clone, Copy, PartialEq, Eq, Debug)]
86#[cfg_attr(feature = "defmt", derive(defmt::Format))] 90#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91/// Parity
87pub enum Parity { 92pub enum Parity {
93 /// No parity
88 ParityNone, 94 ParityNone,
95 /// Even Parity
89 ParityEven, 96 ParityEven,
97 /// Odd Parity
90 ParityOdd, 98 ParityOdd,
91} 99}
92 100
93#[derive(Clone, Copy, PartialEq, Eq, Debug)] 101#[derive(Clone, Copy, PartialEq, Eq, Debug)]
94#[cfg_attr(feature = "defmt", derive(defmt::Format))] 102#[cfg_attr(feature = "defmt", derive(defmt::Format))]
103/// Number of stop bits
95pub enum StopBits { 104pub enum StopBits {
96 #[doc = "1 stop bit"] 105 #[doc = "1 stop bit"]
97 STOP1, 106 STOP1,
@@ -106,26 +115,37 @@ pub enum StopBits {
106#[non_exhaustive] 115#[non_exhaustive]
107#[derive(Clone, Copy, PartialEq, Eq, Debug)] 116#[derive(Clone, Copy, PartialEq, Eq, Debug)]
108#[cfg_attr(feature = "defmt", derive(defmt::Format))] 117#[cfg_attr(feature = "defmt", derive(defmt::Format))]
118/// Config Error
109pub enum ConfigError { 119pub enum ConfigError {
120 /// Baudrate too low
110 BaudrateTooLow, 121 BaudrateTooLow,
122 /// Baudrate too high
111 BaudrateTooHigh, 123 BaudrateTooHigh,
124 /// Rx or Tx not enabled
112 RxOrTxNotEnabled, 125 RxOrTxNotEnabled,
113} 126}
114 127
115#[non_exhaustive] 128#[non_exhaustive]
116#[derive(Clone, Copy, PartialEq, Eq, Debug)] 129#[derive(Clone, Copy, PartialEq, Eq, Debug)]
130/// Config
117pub struct Config { 131pub struct Config {
132 /// Baud rate
118 pub baudrate: u32, 133 pub baudrate: u32,
134 /// Number of data bits
119 pub data_bits: DataBits, 135 pub data_bits: DataBits,
136 /// Number of stop bits
120 pub stop_bits: StopBits, 137 pub stop_bits: StopBits,
138 /// Parity type
121 pub parity: Parity, 139 pub parity: Parity,
122 /// if true, on read-like method, if there is a latent error pending, 140
123 /// read will abort, the error reported and cleared 141 /// If true: on a read-like method, if there is a latent error pending,
124 /// if false, the error is ignored and cleared 142 /// the read will abort and the error will be reported and cleared
143 ///
144 /// If false: the error is ignored and cleared
125 pub detect_previous_overrun: bool, 145 pub detect_previous_overrun: bool,
126 146
127 /// Set this to true if the line is considered noise free. 147 /// Set this to true if the line is considered noise free.
128 /// This will increase the receivers tolerance to clock deviations, 148 /// This will increase the receiver’s tolerance to clock deviations,
129 /// but will effectively disable noise detection. 149 /// but will effectively disable noise detection.
130 #[cfg(not(usart_v1))] 150 #[cfg(not(usart_v1))]
131 pub assume_noise_free: bool, 151 pub assume_noise_free: bool,
@@ -188,6 +208,7 @@ enum ReadCompletionEvent {
188 Idle(usize), 208 Idle(usize),
189} 209}
190 210
211/// Bidirectional UART Driver
191pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { 212pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
192 tx: UartTx<'d, T, TxDma>, 213 tx: UartTx<'d, T, TxDma>,
193 rx: UartRx<'d, T, RxDma>, 214 rx: UartRx<'d, T, RxDma>,
@@ -203,6 +224,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma>
203 } 224 }
204} 225}
205 226
227/// Tx-only UART Driver
206pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { 228pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
207 phantom: PhantomData<&'d mut T>, 229 phantom: PhantomData<&'d mut T>,
208 tx_dma: PeripheralRef<'d, TxDma>, 230 tx_dma: PeripheralRef<'d, TxDma>,
@@ -217,6 +239,7 @@ impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> {
217 } 239 }
218} 240}
219 241
242/// Rx-only UART Driver
220pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { 243pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
221 _peri: PeripheralRef<'d, T>, 244 _peri: PeripheralRef<'d, T>,
222 rx_dma: PeripheralRef<'d, RxDma>, 245 rx_dma: PeripheralRef<'d, RxDma>,
@@ -247,6 +270,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
247 Self::new_inner(peri, tx, tx_dma, config) 270 Self::new_inner(peri, tx, tx_dma, config)
248 } 271 }
249 272
273 /// Create a new tx-only UART with a clear-to-send pin
250 pub fn new_with_cts( 274 pub fn new_with_cts(
251 peri: impl Peripheral<P = T> + 'd, 275 peri: impl Peripheral<P = T> + 'd,
252 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 276 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
@@ -288,10 +312,12 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
288 }) 312 })
289 } 313 }
290 314
315 /// Reconfigure the driver
291 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 316 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
292 reconfigure::<T>(config) 317 reconfigure::<T>(config)
293 } 318 }
294 319
320 /// Initiate an asynchronous UART write
295 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> 321 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
296 where 322 where
297 TxDma: crate::usart::TxDma<T>, 323 TxDma: crate::usart::TxDma<T>,
@@ -308,6 +334,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
308 Ok(()) 334 Ok(())
309 } 335 }
310 336
337 /// Perform a blocking UART write
311 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 338 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
312 let r = T::regs(); 339 let r = T::regs();
313 for &b in buffer { 340 for &b in buffer {
@@ -317,6 +344,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
317 Ok(()) 344 Ok(())
318 } 345 }
319 346
347 /// Block until transmission complete
320 pub fn blocking_flush(&mut self) -> Result<(), Error> { 348 pub fn blocking_flush(&mut self) -> Result<(), Error> {
321 let r = T::regs(); 349 let r = T::regs();
322 while !sr(r).read().tc() {} 350 while !sr(r).read().tc() {}
@@ -338,6 +366,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
338 Self::new_inner(peri, rx, rx_dma, config) 366 Self::new_inner(peri, rx, rx_dma, config)
339 } 367 }
340 368
369 /// Create a new rx-only UART with a request-to-send pin
341 pub fn new_with_rts( 370 pub fn new_with_rts(
342 peri: impl Peripheral<P = T> + 'd, 371 peri: impl Peripheral<P = T> + 'd,
343 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 372 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
@@ -387,6 +416,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
387 }) 416 })
388 } 417 }
389 418
419 /// Reconfigure the driver
390 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 420 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
391 reconfigure::<T>(config) 421 reconfigure::<T>(config)
392 } 422 }
@@ -444,6 +474,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
444 Ok(sr.rxne()) 474 Ok(sr.rxne())
445 } 475 }
446 476
477 /// Initiate an asynchronous UART read
447 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> 478 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
448 where 479 where
449 RxDma: crate::usart::RxDma<T>, 480 RxDma: crate::usart::RxDma<T>,
@@ -453,6 +484,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
453 Ok(()) 484 Ok(())
454 } 485 }
455 486
487 /// Read a single u8 if there is one available, otherwise return WouldBlock
456 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { 488 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
457 let r = T::regs(); 489 let r = T::regs();
458 if self.check_rx_flags()? { 490 if self.check_rx_flags()? {
@@ -462,6 +494,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
462 } 494 }
463 } 495 }
464 496
497 /// Perform a blocking read into `buffer`
465 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 498 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
466 let r = T::regs(); 499 let r = T::regs();
467 for b in buffer { 500 for b in buffer {
@@ -471,6 +504,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
471 Ok(()) 504 Ok(())
472 } 505 }
473 506
507 /// Initiate an asynchronous read with idle line detection enabled
474 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> 508 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
475 where 509 where
476 RxDma: crate::usart::RxDma<T>, 510 RxDma: crate::usart::RxDma<T>,
@@ -695,6 +729,7 @@ impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
695} 729}
696 730
697impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 731impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
732 /// Create a new bidirectional UART
698 pub fn new( 733 pub fn new(
699 peri: impl Peripheral<P = T> + 'd, 734 peri: impl Peripheral<P = T> + 'd,
700 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 735 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -711,6 +746,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
711 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config) 746 Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
712 } 747 }
713 748
749 /// Create a new bidirectional UART with request-to-send and clear-to-send pins
714 pub fn new_with_rtscts( 750 pub fn new_with_rtscts(
715 peri: impl Peripheral<P = T> + 'd, 751 peri: impl Peripheral<P = T> + 'd,
716 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 752 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -738,6 +774,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
738 } 774 }
739 775
740 #[cfg(not(any(usart_v1, usart_v2)))] 776 #[cfg(not(any(usart_v1, usart_v2)))]
777 /// Create a new bidirectional UART with a driver-enable pin
741 pub fn new_with_de( 778 pub fn new_with_de(
742 peri: impl Peripheral<P = T> + 'd, 779 peri: impl Peripheral<P = T> + 'd,
743 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 780 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@@ -813,6 +850,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
813 }) 850 })
814 } 851 }
815 852
853 /// Initiate an asynchronous write
816 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> 854 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
817 where 855 where
818 TxDma: crate::usart::TxDma<T>, 856 TxDma: crate::usart::TxDma<T>,
@@ -820,14 +858,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
820 self.tx.write(buffer).await 858 self.tx.write(buffer).await
821 } 859 }
822 860
861 /// Perform a blocking write
823 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { 862 pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
824 self.tx.blocking_write(buffer) 863 self.tx.blocking_write(buffer)
825 } 864 }
826 865
866 /// Block until transmission complete
827 pub fn blocking_flush(&mut self) -> Result<(), Error> { 867 pub fn blocking_flush(&mut self) -> Result<(), Error> {
828 self.tx.blocking_flush() 868 self.tx.blocking_flush()
829 } 869 }
830 870
871 /// Initiate an asynchronous read into `buffer`
831 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> 872 pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
832 where 873 where
833 RxDma: crate::usart::RxDma<T>, 874 RxDma: crate::usart::RxDma<T>,
@@ -835,14 +876,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
835 self.rx.read(buffer).await 876 self.rx.read(buffer).await
836 } 877 }
837 878
879 /// Read a single `u8` or return `WouldBlock`
838 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { 880 pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> {
839 self.rx.nb_read() 881 self.rx.nb_read()
840 } 882 }
841 883
884 /// Perform a blocking read into `buffer`
842 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { 885 pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
843 self.rx.blocking_read(buffer) 886 self.rx.blocking_read(buffer)
844 } 887 }
845 888
889 /// Initiate an an asynchronous read with idle line detection enabled
846 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> 890 pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
847 where 891 where
848 RxDma: crate::usart::RxDma<T>, 892 RxDma: crate::usart::RxDma<T>,
@@ -1292,8 +1336,10 @@ pub(crate) mod sealed {
1292 } 1336 }
1293} 1337}
1294 1338
1339/// Basic UART driver instance
1295pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {} 1340pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {}
1296 1341
1342/// Full UART driver instance
1297pub trait FullInstance: sealed::FullInstance {} 1343pub trait FullInstance: sealed::FullInstance {}
1298 1344
1299pin_trait!(RxPin, BasicInstance); 1345pin_trait!(RxPin, BasicInstance);
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index f8ada3926..4391bfef7 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -11,6 +11,7 @@ use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config,
11use crate::dma::ReadableRingBuffer; 11use crate::dma::ReadableRingBuffer;
12use crate::usart::{Regs, Sr}; 12use crate::usart::{Regs, Sr};
13 13
14/// Rx-only Ring-buffered UART Driver
14pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> { 15pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
15 _peri: PeripheralRef<'d, T>, 16 _peri: PeripheralRef<'d, T>,
16 ring_buf: ReadableRingBuffer<'d, RxDma, u8>, 17 ring_buf: ReadableRingBuffer<'d, RxDma, u8>,
@@ -27,8 +28,8 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUar
27 28
28impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { 29impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
29 /// Turn the `UartRx` into a buffered uart which can continously receive in the background 30 /// Turn the `UartRx` into a buffered uart which can continously receive in the background
30 /// without the possibility of loosing bytes. The `dma_buf` is a buffer registered to the 31 /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
31 /// DMA controller, and must be sufficiently large, such that it will not overflow. 32 /// DMA controller, and must be large enough to prevent overflows.
32 pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> { 33 pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T, RxDma> {
33 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); 34 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
34 35
@@ -49,6 +50,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
49} 50}
50 51
51impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> { 52impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> {
53 /// Clear the ring buffer and start receiving in the background
52 pub fn start(&mut self) -> Result<(), Error> { 54 pub fn start(&mut self) -> Result<(), Error> {
53 // Clear the ring buffer so that it is ready to receive data 55 // Clear the ring buffer so that it is ready to receive data
54 self.ring_buf.clear(); 56 self.ring_buf.clear();
@@ -64,6 +66,7 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
64 Err(err) 66 Err(err)
65 } 67 }
66 68
69 /// Cleanly stop and reconfigure the driver
67 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { 70 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
68 self.teardown_uart(); 71 self.teardown_uart();
69 reconfigure::<T>(config) 72 reconfigure::<T>(config)