diff options
| -rw-r--r-- | .vscode/settings.json | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/buffered.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 54 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 7 |
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 | ||
| 85 | pub struct State { | 86 | pub 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 | ||
| 93 | impl State { | 94 | impl 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 | ||
| 104 | pub struct BufferedUart<'d, T: BasicInstance> { | 107 | pub 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 | ||
| 109 | pub struct BufferedUartTx<'d, T: BasicInstance> { | 113 | pub 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 | ||
| 113 | pub struct BufferedUartRx<'d, T: BasicInstance> { | 118 | pub 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 | ||
| 144 | impl<'d, T: BasicInstance> BufferedUart<'d, T> { | 149 | impl<'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 | ||
| 4 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 5 | use core::marker::PhantomData; | 6 | use 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 | ||
| 80 | pub enum DataBits { | 82 | pub 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 | ||
| 87 | pub enum Parity { | 92 | pub 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 | ||
| 95 | pub enum StopBits { | 104 | pub 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 | ||
| 109 | pub enum ConfigError { | 119 | pub 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 | ||
| 117 | pub struct Config { | 131 | pub 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 | ||
| 191 | pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { | 212 | pub 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 | ||
| 206 | pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { | 228 | pub 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 | ||
| 220 | pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { | 243 | pub 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 | ||
| 697 | impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | 731 | impl<'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 | ||
| 1295 | pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {} | 1340 | pub trait BasicInstance: Peripheral<P = Self> + sealed::BasicInstance + 'static + Send {} |
| 1296 | 1341 | ||
| 1342 | /// Full UART driver instance | ||
| 1297 | pub trait FullInstance: sealed::FullInstance {} | 1343 | pub trait FullInstance: sealed::FullInstance {} |
| 1298 | 1344 | ||
| 1299 | pin_trait!(RxPin, BasicInstance); | 1345 | pin_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, | |||
| 11 | use crate::dma::ReadableRingBuffer; | 11 | use crate::dma::ReadableRingBuffer; |
| 12 | use crate::usart::{Regs, Sr}; | 12 | use crate::usart::{Regs, Sr}; |
| 13 | 13 | ||
| 14 | /// Rx-only Ring-buffered UART Driver | ||
| 14 | pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> { | 15 | pub 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 | ||
| 28 | impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { | 29 | impl<'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 | ||
| 51 | impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxDma> { | 52 | impl<'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) |
