diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-04-16 02:00:43 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-04-16 02:00:55 +0200 |
| commit | d6b1233f16407e3501efcd1885460645a75ed57b (patch) | |
| tree | 1bda1d6cd4316c24dc5f7c2cc362d3513167c860 | |
| parent | 524c24c8b3ee3693c3bacd20deede29eb1107159 (diff) | |
stm32/usart: remove DMA generic params.
| -rw-r--r-- | embassy-stm32/src/macros.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 854 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 20 | ||||
| -rw-r--r-- | examples/stm32f3/src/bin/usart_dma.rs | 3 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/usart.rs | 3 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/usart_dma.rs | 3 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/usart_dma.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/usart.rs | 8 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/usart_dma.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/usart_split.rs | 18 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/usart.rs | 8 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/usart_dma.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/usart_split.rs | 18 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/usart.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/usart_dma.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/usart.rs | 8 | ||||
| -rw-r--r-- | tests/stm32/src/bin/usart_rx_ringbuffered.rs | 3 |
17 files changed, 567 insertions, 404 deletions
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index f603f661f..14137bc37 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs | |||
| @@ -82,12 +82,12 @@ macro_rules! new_dma { | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | macro_rules! new_pin { | 84 | macro_rules! new_pin { |
| 85 | ($name:ident, $aftype:expr, $speed:expr) => {{ | 85 | ($name:ident, $aftype:expr) => {{ |
| 86 | let pin = $name.into_ref(); | 86 | new_pin!($name, $aftype, crate::gpio::Speed::Medium, crate::gpio::Pull::None) |
| 87 | pin.set_as_af(pin.af_num(), $aftype); | ||
| 88 | pin.set_speed($speed); | ||
| 89 | Some(pin.map_into()) | ||
| 90 | }}; | 87 | }}; |
| 88 | ($name:ident, $aftype:expr, $speed:expr) => { | ||
| 89 | new_pin!($name, $aftype, $speed, crate::gpio::Pull::None) | ||
| 90 | }; | ||
| 91 | ($name:ident, $aftype:expr, $speed:expr, $pull:expr) => {{ | 91 | ($name:ident, $aftype:expr, $speed:expr, $pull:expr) => {{ |
| 92 | let pin = $name.into_ref(); | 92 | let pin = $name.into_ref(); |
| 93 | pin.set_as_af_pull(pin.af_num(), $aftype, $pull); | 93 | pin.set_as_af_pull(pin.af_num(), $aftype, $pull); |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 7c0523a25..e7fdf4da6 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -13,9 +13,10 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | |||
| 13 | use embassy_sync::waitqueue::AtomicWaker; | 13 | use embassy_sync::waitqueue::AtomicWaker; |
| 14 | use futures::future::{select, Either}; | 14 | use futures::future::{select, Either}; |
| 15 | 15 | ||
| 16 | use crate::dma::{NoDma, Transfer}; | 16 | use crate::dma::ChannelAndRequest; |
| 17 | use crate::gpio::AFType; | 17 | use crate::gpio::{AFType, AnyPin, SealedPin}; |
| 18 | use crate::interrupt::typelevel::Interrupt; | 18 | use crate::interrupt::typelevel::Interrupt; |
| 19 | use crate::mode::{Async, Blocking, Mode}; | ||
| 19 | #[allow(unused_imports)] | 20 | #[allow(unused_imports)] |
| 20 | #[cfg(not(any(usart_v1, usart_v2)))] | 21 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 21 | use crate::pac::usart::regs::Isr as Sr; | 22 | use crate::pac::usart::regs::Isr as Sr; |
| @@ -162,6 +163,26 @@ pub struct Config { | |||
| 162 | /// Set this to true to invert RX pin signal values (V<sub>DD</sub> =0/mark, Gnd = 1/idle). | 163 | /// Set this to true to invert RX pin signal values (V<sub>DD</sub> =0/mark, Gnd = 1/idle). |
| 163 | #[cfg(any(usart_v3, usart_v4))] | 164 | #[cfg(any(usart_v3, usart_v4))] |
| 164 | pub invert_rx: bool, | 165 | pub invert_rx: bool, |
| 166 | |||
| 167 | // private: set by new_half_duplex, not by the user. | ||
| 168 | half_duplex: bool, | ||
| 169 | } | ||
| 170 | |||
| 171 | impl Config { | ||
| 172 | fn tx_af(&self) -> AFType { | ||
| 173 | #[cfg(any(usart_v3, usart_v4))] | ||
| 174 | if self.swap_rx_tx { | ||
| 175 | return AFType::Input; | ||
| 176 | }; | ||
| 177 | AFType::OutputPushPull | ||
| 178 | } | ||
| 179 | fn rx_af(&self) -> AFType { | ||
| 180 | #[cfg(any(usart_v3, usart_v4))] | ||
| 181 | if self.swap_rx_tx { | ||
| 182 | return AFType::OutputPushPull; | ||
| 183 | }; | ||
| 184 | AFType::Input | ||
| 185 | } | ||
| 165 | } | 186 | } |
| 166 | 187 | ||
| 167 | impl Default for Config { | 188 | impl Default for Config { |
| @@ -181,6 +202,7 @@ impl Default for Config { | |||
| 181 | invert_tx: false, | 202 | invert_tx: false, |
| 182 | #[cfg(any(usart_v3, usart_v4))] | 203 | #[cfg(any(usart_v3, usart_v4))] |
| 183 | invert_rx: false, | 204 | invert_rx: false, |
| 205 | half_duplex: false, | ||
| 184 | } | 206 | } |
| 185 | } | 207 | } |
| 186 | } | 208 | } |
| @@ -217,12 +239,12 @@ enum ReadCompletionEvent { | |||
| 217 | /// | 239 | /// |
| 218 | /// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] | 240 | /// See [`UartRx`] for more details, and see [`BufferedUart`] and [`RingBufferedUartRx`] |
| 219 | /// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. | 241 | /// as alternatives that do provide the necessary guarantees for `embedded_io::Read`. |
| 220 | pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { | 242 | pub struct Uart<'d, T: BasicInstance, M: Mode> { |
| 221 | tx: UartTx<'d, T, TxDma>, | 243 | tx: UartTx<'d, T, M>, |
| 222 | rx: UartRx<'d, T, RxDma>, | 244 | rx: UartRx<'d, T, M>, |
| 223 | } | 245 | } |
| 224 | 246 | ||
| 225 | impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> { | 247 | impl<'d, T: BasicInstance, M: Mode> SetConfig for Uart<'d, T, M> { |
| 226 | type Config = Config; | 248 | type Config = Config; |
| 227 | type ConfigError = ConfigError; | 249 | type ConfigError = ConfigError; |
| 228 | 250 | ||
| @@ -236,12 +258,15 @@ impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> | |||
| 236 | /// | 258 | /// |
| 237 | /// Can be obtained from [`Uart::split`], or can be constructed independently, | 259 | /// Can be obtained from [`Uart::split`], or can be constructed independently, |
| 238 | /// if you do not need the receiving half of the driver. | 260 | /// if you do not need the receiving half of the driver. |
| 239 | pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { | 261 | pub struct UartTx<'d, T: BasicInstance, M: Mode> { |
| 240 | phantom: PhantomData<&'d mut T>, | 262 | _phantom: PhantomData<(T, M)>, |
| 241 | tx_dma: PeripheralRef<'d, TxDma>, | 263 | tx: Option<PeripheralRef<'d, AnyPin>>, |
| 264 | cts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 265 | de: Option<PeripheralRef<'d, AnyPin>>, | ||
| 266 | tx_dma: Option<ChannelAndRequest<'d>>, | ||
| 242 | } | 267 | } |
| 243 | 268 | ||
| 244 | impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> { | 269 | impl<'d, T: BasicInstance, M: Mode> SetConfig for UartTx<'d, T, M> { |
| 245 | type Config = Config; | 270 | type Config = Config; |
| 246 | type ConfigError = ConfigError; | 271 | type ConfigError = ConfigError; |
| 247 | 272 | ||
| @@ -279,15 +304,17 @@ impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> { | |||
| 279 | /// store data received between calls. | 304 | /// store data received between calls. |
| 280 | /// | 305 | /// |
| 281 | /// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043). | 306 | /// Also see [this github comment](https://github.com/embassy-rs/embassy/pull/2185#issuecomment-1810047043). |
| 282 | pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { | 307 | pub struct UartRx<'d, T: BasicInstance, M: Mode> { |
| 283 | _peri: PeripheralRef<'d, T>, | 308 | _phantom: PhantomData<(T, M)>, |
| 284 | rx_dma: PeripheralRef<'d, RxDma>, | 309 | rx: Option<PeripheralRef<'d, AnyPin>>, |
| 310 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 311 | rx_dma: Option<ChannelAndRequest<'d>>, | ||
| 285 | detect_previous_overrun: bool, | 312 | detect_previous_overrun: bool, |
| 286 | #[cfg(any(usart_v1, usart_v2))] | 313 | #[cfg(any(usart_v1, usart_v2))] |
| 287 | buffered_sr: stm32_metapac::usart::regs::Sr, | 314 | buffered_sr: stm32_metapac::usart::regs::Sr, |
| 288 | } | 315 | } |
| 289 | 316 | ||
| 290 | impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> { | 317 | impl<'d, T: BasicInstance, M: Mode> SetConfig for UartRx<'d, T, M> { |
| 291 | type Config = Config; | 318 | type Config = Config; |
| 292 | type ConfigError = ConfigError; | 319 | type ConfigError = ConfigError; |
| 293 | 320 | ||
| @@ -296,17 +323,21 @@ impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> { | |||
| 296 | } | 323 | } |
| 297 | } | 324 | } |
| 298 | 325 | ||
| 299 | impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | 326 | impl<'d, T: BasicInstance> UartTx<'d, T, Async> { |
| 300 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. | 327 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. |
| 301 | pub fn new( | 328 | pub fn new( |
| 302 | peri: impl Peripheral<P = T> + 'd, | 329 | peri: impl Peripheral<P = T> + 'd, |
| 303 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 330 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 304 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 331 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| 305 | config: Config, | 332 | config: Config, |
| 306 | ) -> Result<Self, ConfigError> { | 333 | ) -> Result<Self, ConfigError> { |
| 307 | T::enable_and_reset(); | 334 | Self::new_inner( |
| 308 | 335 | peri, | |
| 309 | Self::new_inner(peri, tx, tx_dma, config) | 336 | new_pin!(tx, AFType::OutputPushPull), |
| 337 | None, | ||
| 338 | new_dma!(tx_dma), | ||
| 339 | config, | ||
| 340 | ) | ||
| 310 | } | 341 | } |
| 311 | 342 | ||
| 312 | /// Create a new tx-only UART with a clear-to-send pin | 343 | /// Create a new tx-only UART with a clear-to-send pin |
| @@ -314,40 +345,86 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | |||
| 314 | peri: impl Peripheral<P = T> + 'd, | 345 | peri: impl Peripheral<P = T> + 'd, |
| 315 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 346 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 316 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, | 347 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
| 317 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 348 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| 318 | config: Config, | 349 | config: Config, |
| 319 | ) -> Result<Self, ConfigError> { | 350 | ) -> Result<Self, ConfigError> { |
| 320 | into_ref!(cts); | 351 | Self::new_inner( |
| 321 | 352 | peri, | |
| 322 | T::enable_and_reset(); | 353 | new_pin!(tx, AFType::OutputPushPull), |
| 354 | new_pin!(cts, AFType::Input), | ||
| 355 | new_dma!(tx_dma), | ||
| 356 | config, | ||
| 357 | ) | ||
| 358 | } | ||
| 323 | 359 | ||
| 324 | cts.set_as_af(cts.af_num(), AFType::Input); | 360 | /// Initiate an asynchronous UART write |
| 325 | T::regs().cr3().write(|w| { | 361 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 326 | w.set_ctse(true); | 362 | let ch = self.tx_dma.as_mut().unwrap(); |
| 363 | T::regs().cr3().modify(|reg| { | ||
| 364 | reg.set_dmat(true); | ||
| 327 | }); | 365 | }); |
| 328 | Self::new_inner(peri, tx, tx_dma, config) | 366 | // If we don't assign future to a variable, the data register pointer |
| 367 | // is held across an await and makes the future non-Send. | ||
| 368 | let transfer = unsafe { ch.write(buffer, tdr(T::regs()), Default::default()) }; | ||
| 369 | transfer.await; | ||
| 370 | Ok(()) | ||
| 329 | } | 371 | } |
| 372 | } | ||
| 330 | 373 | ||
| 331 | fn new_inner( | 374 | impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> { |
| 332 | _peri: impl Peripheral<P = T> + 'd, | 375 | /// Create a new blocking tx-only UART with no hardware flow control. |
| 376 | /// | ||
| 377 | /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. | ||
| 378 | pub fn new_blocking( | ||
| 379 | peri: impl Peripheral<P = T> + 'd, | ||
| 333 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 380 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 334 | tx_dma: impl Peripheral<P = TxDma> + 'd, | ||
| 335 | config: Config, | 381 | config: Config, |
| 336 | ) -> Result<Self, ConfigError> { | 382 | ) -> Result<Self, ConfigError> { |
| 337 | into_ref!(_peri, tx, tx_dma); | 383 | Self::new_inner(peri, new_pin!(tx, AFType::OutputPushPull), None, None, config) |
| 384 | } | ||
| 338 | 385 | ||
| 339 | let r = T::regs(); | 386 | /// Create a new blocking tx-only UART with a clear-to-send pin |
| 387 | pub fn new_blocking_with_cts( | ||
| 388 | peri: impl Peripheral<P = T> + 'd, | ||
| 389 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | ||
| 390 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, | ||
| 391 | config: Config, | ||
| 392 | ) -> Result<Self, ConfigError> { | ||
| 393 | Self::new_inner( | ||
| 394 | peri, | ||
| 395 | new_pin!(tx, AFType::OutputPushPull), | ||
| 396 | new_pin!(cts, AFType::Input), | ||
| 397 | None, | ||
| 398 | config, | ||
| 399 | ) | ||
| 400 | } | ||
| 401 | } | ||
| 340 | 402 | ||
| 341 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | 403 | impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> { |
| 404 | fn new_inner( | ||
| 405 | _peri: impl Peripheral<P = T> + 'd, | ||
| 406 | tx: Option<PeripheralRef<'d, AnyPin>>, | ||
| 407 | cts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 408 | tx_dma: Option<ChannelAndRequest<'d>>, | ||
| 409 | config: Config, | ||
| 410 | ) -> Result<Self, ConfigError> { | ||
| 411 | T::enable_and_reset(); | ||
| 342 | 412 | ||
| 413 | let r = T::regs(); | ||
| 414 | r.cr3().modify(|w| { | ||
| 415 | w.set_ctse(cts.is_some()); | ||
| 416 | }); | ||
| 343 | configure(r, &config, T::frequency(), T::KIND, false, true)?; | 417 | configure(r, &config, T::frequency(), T::KIND, false, true)?; |
| 344 | 418 | ||
| 345 | // create state once! | 419 | // create state once! |
| 346 | let _s = T::state(); | 420 | let _s = T::state(); |
| 347 | 421 | ||
| 348 | Ok(Self { | 422 | Ok(Self { |
| 423 | tx, | ||
| 424 | cts, | ||
| 425 | de: None, | ||
| 349 | tx_dma, | 426 | tx_dma, |
| 350 | phantom: PhantomData, | 427 | _phantom: PhantomData, |
| 351 | }) | 428 | }) |
| 352 | } | 429 | } |
| 353 | 430 | ||
| @@ -356,23 +433,6 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | |||
| 356 | reconfigure::<T>(config) | 433 | reconfigure::<T>(config) |
| 357 | } | 434 | } |
| 358 | 435 | ||
| 359 | /// Initiate an asynchronous UART write | ||
| 360 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> | ||
| 361 | where | ||
| 362 | TxDma: crate::usart::TxDma<T>, | ||
| 363 | { | ||
| 364 | let ch = &mut self.tx_dma; | ||
| 365 | let request = ch.request(); | ||
| 366 | T::regs().cr3().modify(|reg| { | ||
| 367 | reg.set_dmat(true); | ||
| 368 | }); | ||
| 369 | // If we don't assign future to a variable, the data register pointer | ||
| 370 | // is held across an await and makes the future non-Send. | ||
| 371 | let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) }; | ||
| 372 | transfer.await; | ||
| 373 | Ok(()) | ||
| 374 | } | ||
| 375 | |||
| 376 | /// Perform a blocking UART write | 436 | /// Perform a blocking UART write |
| 377 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 437 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 378 | let r = T::regs(); | 438 | let r = T::regs(); |
| @@ -391,18 +451,18 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { | |||
| 391 | } | 451 | } |
| 392 | } | 452 | } |
| 393 | 453 | ||
| 394 | impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | 454 | impl<'d, T: BasicInstance> UartRx<'d, T, Async> { |
| 455 | /// Create a new rx-only UART with no hardware flow control. | ||
| 456 | /// | ||
| 395 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. | 457 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. |
| 396 | pub fn new( | 458 | pub fn new( |
| 397 | peri: impl Peripheral<P = T> + 'd, | 459 | peri: impl Peripheral<P = T> + 'd, |
| 398 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 460 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 399 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 461 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 400 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 462 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
| 401 | config: Config, | 463 | config: Config, |
| 402 | ) -> Result<Self, ConfigError> { | 464 | ) -> Result<Self, ConfigError> { |
| 403 | T::enable_and_reset(); | 465 | Self::new_inner(peri, new_pin!(rx, AFType::Input), None, new_dma!(rx_dma), config) |
| 404 | |||
| 405 | Self::new_inner(peri, rx, rx_dma, config) | ||
| 406 | } | 466 | } |
| 407 | 467 | ||
| 408 | /// Create a new rx-only UART with a request-to-send pin | 468 | /// Create a new rx-only UART with a request-to-send pin |
| @@ -411,143 +471,27 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 411 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 471 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 412 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 472 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 413 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, | 473 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, |
| 414 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 474 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
| 415 | config: Config, | ||
| 416 | ) -> Result<Self, ConfigError> { | ||
| 417 | into_ref!(rts); | ||
| 418 | |||
| 419 | T::enable_and_reset(); | ||
| 420 | |||
| 421 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | ||
| 422 | T::regs().cr3().write(|w| { | ||
| 423 | w.set_rtse(true); | ||
| 424 | }); | ||
| 425 | |||
| 426 | Self::new_inner(peri, rx, rx_dma, config) | ||
| 427 | } | ||
| 428 | |||
| 429 | fn new_inner( | ||
| 430 | peri: impl Peripheral<P = T> + 'd, | ||
| 431 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 432 | rx_dma: impl Peripheral<P = RxDma> + 'd, | ||
| 433 | config: Config, | 475 | config: Config, |
| 434 | ) -> Result<Self, ConfigError> { | 476 | ) -> Result<Self, ConfigError> { |
| 435 | into_ref!(peri, rx, rx_dma); | 477 | Self::new_inner( |
| 436 | 478 | peri, | |
| 437 | let r = T::regs(); | 479 | new_pin!(rx, AFType::Input), |
| 438 | 480 | new_pin!(rts, AFType::OutputPushPull), | |
| 439 | rx.set_as_af(rx.af_num(), AFType::Input); | 481 | new_dma!(rx_dma), |
| 440 | 482 | config, | |
| 441 | configure(r, &config, T::frequency(), T::KIND, true, false)?; | 483 | ) |
| 442 | |||
| 443 | T::Interrupt::unpend(); | ||
| 444 | unsafe { T::Interrupt::enable() }; | ||
| 445 | |||
| 446 | // create state once! | ||
| 447 | let _s = T::state(); | ||
| 448 | |||
| 449 | Ok(Self { | ||
| 450 | _peri: peri, | ||
| 451 | rx_dma, | ||
| 452 | detect_previous_overrun: config.detect_previous_overrun, | ||
| 453 | #[cfg(any(usart_v1, usart_v2))] | ||
| 454 | buffered_sr: stm32_metapac::usart::regs::Sr(0), | ||
| 455 | }) | ||
| 456 | } | ||
| 457 | |||
| 458 | /// Reconfigure the driver | ||
| 459 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | ||
| 460 | reconfigure::<T>(config) | ||
| 461 | } | ||
| 462 | |||
| 463 | #[cfg(any(usart_v1, usart_v2))] | ||
| 464 | fn check_rx_flags(&mut self) -> Result<bool, Error> { | ||
| 465 | let r = T::regs(); | ||
| 466 | loop { | ||
| 467 | // Handle all buffered error flags. | ||
| 468 | if self.buffered_sr.pe() { | ||
| 469 | self.buffered_sr.set_pe(false); | ||
| 470 | return Err(Error::Parity); | ||
| 471 | } else if self.buffered_sr.fe() { | ||
| 472 | self.buffered_sr.set_fe(false); | ||
| 473 | return Err(Error::Framing); | ||
| 474 | } else if self.buffered_sr.ne() { | ||
| 475 | self.buffered_sr.set_ne(false); | ||
| 476 | return Err(Error::Noise); | ||
| 477 | } else if self.buffered_sr.ore() { | ||
| 478 | self.buffered_sr.set_ore(false); | ||
| 479 | return Err(Error::Overrun); | ||
| 480 | } else if self.buffered_sr.rxne() { | ||
| 481 | self.buffered_sr.set_rxne(false); | ||
| 482 | return Ok(true); | ||
| 483 | } else { | ||
| 484 | // No error flags from previous iterations were set: Check the actual status register | ||
| 485 | let sr = r.sr().read(); | ||
| 486 | if !sr.rxne() { | ||
| 487 | return Ok(false); | ||
| 488 | } | ||
| 489 | |||
| 490 | // Buffer the status register and let the loop handle the error flags. | ||
| 491 | self.buffered_sr = sr; | ||
| 492 | } | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | #[cfg(any(usart_v3, usart_v4))] | ||
| 497 | fn check_rx_flags(&mut self) -> Result<bool, Error> { | ||
| 498 | let r = T::regs(); | ||
| 499 | let sr = r.isr().read(); | ||
| 500 | if sr.pe() { | ||
| 501 | r.icr().write(|w| w.set_pe(true)); | ||
| 502 | return Err(Error::Parity); | ||
| 503 | } else if sr.fe() { | ||
| 504 | r.icr().write(|w| w.set_fe(true)); | ||
| 505 | return Err(Error::Framing); | ||
| 506 | } else if sr.ne() { | ||
| 507 | r.icr().write(|w| w.set_ne(true)); | ||
| 508 | return Err(Error::Noise); | ||
| 509 | } else if sr.ore() { | ||
| 510 | r.icr().write(|w| w.set_ore(true)); | ||
| 511 | return Err(Error::Overrun); | ||
| 512 | } | ||
| 513 | Ok(sr.rxne()) | ||
| 514 | } | 484 | } |
| 515 | 485 | ||
| 516 | /// Initiate an asynchronous UART read | 486 | /// Initiate an asynchronous UART read |
| 517 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> | 487 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { |
| 518 | where | ||
| 519 | RxDma: crate::usart::RxDma<T>, | ||
| 520 | { | ||
| 521 | self.inner_read(buffer, false).await?; | 488 | self.inner_read(buffer, false).await?; |
| 522 | 489 | ||
| 523 | Ok(()) | 490 | Ok(()) |
| 524 | } | 491 | } |
| 525 | 492 | ||
| 526 | /// Read a single u8 if there is one available, otherwise return WouldBlock | ||
| 527 | pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { | ||
| 528 | let r = T::regs(); | ||
| 529 | if self.check_rx_flags()? { | ||
| 530 | Ok(unsafe { rdr(r).read_volatile() }) | ||
| 531 | } else { | ||
| 532 | Err(nb::Error::WouldBlock) | ||
| 533 | } | ||
| 534 | } | ||
| 535 | |||
| 536 | /// Perform a blocking read into `buffer` | ||
| 537 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 538 | let r = T::regs(); | ||
| 539 | for b in buffer { | ||
| 540 | while !self.check_rx_flags()? {} | ||
| 541 | unsafe { *b = rdr(r).read_volatile() } | ||
| 542 | } | ||
| 543 | Ok(()) | ||
| 544 | } | ||
| 545 | |||
| 546 | /// Initiate an asynchronous read with idle line detection enabled | 493 | /// Initiate an asynchronous read with idle line detection enabled |
| 547 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> | 494 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { |
| 548 | where | ||
| 549 | RxDma: crate::usart::RxDma<T>, | ||
| 550 | { | ||
| 551 | self.inner_read(buffer, true).await | 495 | self.inner_read(buffer, true).await |
| 552 | } | 496 | } |
| 553 | 497 | ||
| @@ -555,10 +499,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 555 | &mut self, | 499 | &mut self, |
| 556 | buffer: &mut [u8], | 500 | buffer: &mut [u8], |
| 557 | enable_idle_line_detection: bool, | 501 | enable_idle_line_detection: bool, |
| 558 | ) -> Result<ReadCompletionEvent, Error> | 502 | ) -> Result<ReadCompletionEvent, Error> { |
| 559 | where | ||
| 560 | RxDma: crate::usart::RxDma<T>, | ||
| 561 | { | ||
| 562 | let r = T::regs(); | 503 | let r = T::regs(); |
| 563 | 504 | ||
| 564 | // make sure USART state is restored to neutral state when this future is dropped | 505 | // make sure USART state is restored to neutral state when this future is dropped |
| @@ -581,15 +522,14 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 581 | }); | 522 | }); |
| 582 | }); | 523 | }); |
| 583 | 524 | ||
| 584 | let ch = &mut self.rx_dma; | 525 | let ch = self.rx_dma.as_mut().unwrap(); |
| 585 | let request = ch.request(); | ||
| 586 | 526 | ||
| 587 | let buffer_len = buffer.len(); | 527 | let buffer_len = buffer.len(); |
| 588 | 528 | ||
| 589 | // Start USART DMA | 529 | // Start USART DMA |
| 590 | // will not do anything yet because DMAR is not yet set | 530 | // will not do anything yet because DMAR is not yet set |
| 591 | // future which will complete when DMA Read request completes | 531 | // future which will complete when DMA Read request completes |
| 592 | let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) }; | 532 | let transfer = unsafe { ch.read(rdr(T::regs()), buffer, Default::default()) }; |
| 593 | 533 | ||
| 594 | // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer | 534 | // clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer |
| 595 | if !self.detect_previous_overrun { | 535 | if !self.detect_previous_overrun { |
| @@ -732,10 +672,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 732 | r | 672 | r |
| 733 | } | 673 | } |
| 734 | 674 | ||
| 735 | async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result<usize, Error> | 675 | async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result<usize, Error> { |
| 736 | where | ||
| 737 | RxDma: crate::usart::RxDma<T>, | ||
| 738 | { | ||
| 739 | if buffer.is_empty() { | 676 | if buffer.is_empty() { |
| 740 | return Ok(0); | 677 | return Ok(0); |
| 741 | } else if buffer.len() > 0xFFFF { | 678 | } else if buffer.len() > 0xFFFF { |
| @@ -755,34 +692,186 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { | |||
| 755 | } | 692 | } |
| 756 | } | 693 | } |
| 757 | 694 | ||
| 758 | impl<'d, T: BasicInstance, TxDma> Drop for UartTx<'d, T, TxDma> { | 695 | impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> { |
| 696 | /// Create a new rx-only UART with no hardware flow control. | ||
| 697 | /// | ||
| 698 | /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power. | ||
| 699 | pub fn new_blocking( | ||
| 700 | peri: impl Peripheral<P = T> + 'd, | ||
| 701 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 702 | config: Config, | ||
| 703 | ) -> Result<Self, ConfigError> { | ||
| 704 | Self::new_inner(peri, new_pin!(rx, AFType::Input), None, None, config) | ||
| 705 | } | ||
| 706 | |||
| 707 | /// Create a new rx-only UART with a request-to-send pin | ||
| 708 | pub fn new_blocking_with_rts( | ||
| 709 | peri: impl Peripheral<P = T> + 'd, | ||
| 710 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 711 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, | ||
| 712 | config: Config, | ||
| 713 | ) -> Result<Self, ConfigError> { | ||
| 714 | Self::new_inner( | ||
| 715 | peri, | ||
| 716 | new_pin!(rx, AFType::Input), | ||
| 717 | new_pin!(rts, AFType::OutputPushPull), | ||
| 718 | None, | ||
| 719 | config, | ||
| 720 | ) | ||
| 721 | } | ||
| 722 | } | ||
| 723 | |||
| 724 | impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> { | ||
| 725 | fn new_inner( | ||
| 726 | _peri: impl Peripheral<P = T> + 'd, | ||
| 727 | rx: Option<PeripheralRef<'d, AnyPin>>, | ||
| 728 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 729 | rx_dma: Option<ChannelAndRequest<'d>>, | ||
| 730 | config: Config, | ||
| 731 | ) -> Result<Self, ConfigError> { | ||
| 732 | T::enable_and_reset(); | ||
| 733 | |||
| 734 | let r = T::regs(); | ||
| 735 | r.cr3().write(|w| { | ||
| 736 | w.set_rtse(rts.is_some()); | ||
| 737 | }); | ||
| 738 | configure(r, &config, T::frequency(), T::KIND, true, false)?; | ||
| 739 | |||
| 740 | T::Interrupt::unpend(); | ||
| 741 | unsafe { T::Interrupt::enable() }; | ||
| 742 | |||
| 743 | // create state once! | ||
| 744 | let _s = T::state(); | ||
| 745 | |||
| 746 | Ok(Self { | ||
| 747 | _phantom: PhantomData, | ||
| 748 | rx, | ||
| 749 | rts, | ||
| 750 | rx_dma, | ||
| 751 | detect_previous_overrun: config.detect_previous_overrun, | ||
| 752 | #[cfg(any(usart_v1, usart_v2))] | ||
| 753 | buffered_sr: stm32_metapac::usart::regs::Sr(0), | ||
| 754 | }) | ||
| 755 | } | ||
| 756 | |||
| 757 | /// Reconfigure the driver | ||
| 758 | pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> { | ||
| 759 | reconfigure::<T>(config) | ||
| 760 | } | ||
| 761 | |||
| 762 | #[cfg(any(usart_v1, usart_v2))] | ||
| 763 | fn check_rx_flags(&mut self) -> Result<bool, Error> { | ||
| 764 | let r = T::regs(); | ||
| 765 | loop { | ||
| 766 | // Handle all buffered error flags. | ||
| 767 | if self.buffered_sr.pe() { | ||
| 768 | self.buffered_sr.set_pe(false); | ||
| 769 | return Err(Error::Parity); | ||
| 770 | } else if self.buffered_sr.fe() { | ||
| 771 | self.buffered_sr.set_fe(false); | ||
| 772 | return Err(Error::Framing); | ||
| 773 | } else if self.buffered_sr.ne() { | ||
| 774 | self.buffered_sr.set_ne(false); | ||
| 775 | return Err(Error::Noise); | ||
| 776 | } else if self.buffered_sr.ore() { | ||
| 777 | self.buffered_sr.set_ore(false); | ||
| 778 | return Err(Error::Overrun); | ||
| 779 | } else if self.buffered_sr.rxne() { | ||
| 780 | self.buffered_sr.set_rxne(false); | ||
| 781 | return Ok(true); | ||
| 782 | } else { | ||
| 783 | // No error flags from previous iterations were set: Check the actual status register | ||
| 784 | let sr = r.sr().read(); | ||
| 785 | if !sr.rxne() { | ||
| 786 | return Ok(false); | ||
| 787 | } | ||
| 788 | |||
| 789 | // Buffer the status register and let the loop handle the error flags. | ||
| 790 | self.buffered_sr = sr; | ||
| 791 | } | ||
| 792 | } | ||
| 793 | } | ||
| 794 | |||
| 795 | #[cfg(any(usart_v3, usart_v4))] | ||
| 796 | fn check_rx_flags(&mut self) -> Result<bool, Error> { | ||
| 797 | let r = T::regs(); | ||
| 798 | let sr = r.isr().read(); | ||
| 799 | if sr.pe() { | ||
| 800 | r.icr().write(|w| w.set_pe(true)); | ||
| 801 | return Err(Error::Parity); | ||
| 802 | } else if sr.fe() { | ||
| 803 | r.icr().write(|w| w.set_fe(true)); | ||
| 804 | return Err(Error::Framing); | ||
| 805 | } else if sr.ne() { | ||
| 806 | r.icr().write(|w| w.set_ne(true)); | ||
| 807 | return Err(Error::Noise); | ||
| 808 | } else if sr.ore() { | ||
| 809 | r.icr().write(|w| w.set_ore(true)); | ||
| 810 | return Err(Error::Overrun); | ||
| 811 | } | ||
| 812 | Ok(sr.rxne()) | ||
| 813 | } | ||
| 814 | |||
| 815 | /// Read a single u8 if there is one available, otherwise return WouldBlock | ||
| 816 | pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { | ||
| 817 | let r = T::regs(); | ||
| 818 | if self.check_rx_flags()? { | ||
| 819 | Ok(unsafe { rdr(r).read_volatile() }) | ||
| 820 | } else { | ||
| 821 | Err(nb::Error::WouldBlock) | ||
| 822 | } | ||
| 823 | } | ||
| 824 | |||
| 825 | /// Perform a blocking read into `buffer` | ||
| 826 | pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 827 | let r = T::regs(); | ||
| 828 | for b in buffer { | ||
| 829 | while !self.check_rx_flags()? {} | ||
| 830 | unsafe { *b = rdr(r).read_volatile() } | ||
| 831 | } | ||
| 832 | Ok(()) | ||
| 833 | } | ||
| 834 | } | ||
| 835 | |||
| 836 | impl<'d, T: BasicInstance, M: Mode> Drop for UartTx<'d, T, M> { | ||
| 759 | fn drop(&mut self) { | 837 | fn drop(&mut self) { |
| 838 | self.tx.as_ref().map(|x| x.set_as_disconnected()); | ||
| 839 | self.cts.as_ref().map(|x| x.set_as_disconnected()); | ||
| 840 | self.de.as_ref().map(|x| x.set_as_disconnected()); | ||
| 760 | T::disable(); | 841 | T::disable(); |
| 761 | } | 842 | } |
| 762 | } | 843 | } |
| 763 | 844 | ||
| 764 | impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> { | 845 | impl<'d, T: BasicInstance, M: Mode> Drop for UartRx<'d, T, M> { |
| 765 | fn drop(&mut self) { | 846 | fn drop(&mut self) { |
| 847 | self.rx.as_ref().map(|x| x.set_as_disconnected()); | ||
| 848 | self.rts.as_ref().map(|x| x.set_as_disconnected()); | ||
| 766 | T::disable(); | 849 | T::disable(); |
| 767 | } | 850 | } |
| 768 | } | 851 | } |
| 769 | 852 | ||
| 770 | impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | 853 | impl<'d, T: BasicInstance> Uart<'d, T, Async> { |
| 771 | /// Create a new bidirectional UART | 854 | /// Create a new bidirectional UART |
| 772 | pub fn new( | 855 | pub fn new( |
| 773 | peri: impl Peripheral<P = T> + 'd, | 856 | peri: impl Peripheral<P = T> + 'd, |
| 774 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 857 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 775 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 858 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 776 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 859 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 777 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 860 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| 778 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 861 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
| 779 | config: Config, | 862 | config: Config, |
| 780 | ) -> Result<Self, ConfigError> { | 863 | ) -> Result<Self, ConfigError> { |
| 781 | // UartRx and UartTx have one refcount ea. | 864 | Self::new_inner( |
| 782 | T::enable_and_reset(); | 865 | peri, |
| 783 | T::enable_and_reset(); | 866 | new_pin!(rx, config.rx_af()), |
| 784 | 867 | new_pin!(tx, config.tx_af()), | |
| 785 | Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config) | 868 | None, |
| 869 | None, | ||
| 870 | None, | ||
| 871 | new_dma!(tx_dma), | ||
| 872 | new_dma!(rx_dma), | ||
| 873 | config, | ||
| 874 | ) | ||
| 786 | } | 875 | } |
| 787 | 876 | ||
| 788 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins | 877 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins |
| @@ -793,23 +882,21 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 793 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 882 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 794 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, | 883 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, |
| 795 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, | 884 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, |
| 796 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 885 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| 797 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 886 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
| 798 | config: Config, | 887 | config: Config, |
| 799 | ) -> Result<Self, ConfigError> { | 888 | ) -> Result<Self, ConfigError> { |
| 800 | into_ref!(cts, rts); | 889 | Self::new_inner( |
| 801 | 890 | peri, | |
| 802 | // UartRx and UartTx have one refcount ea. | 891 | new_pin!(rx, config.rx_af()), |
| 803 | T::enable_and_reset(); | 892 | new_pin!(tx, config.tx_af()), |
| 804 | T::enable_and_reset(); | 893 | new_pin!(rts, AFType::OutputPushPull), |
| 805 | 894 | new_pin!(cts, AFType::Input), | |
| 806 | rts.set_as_af(rts.af_num(), AFType::OutputPushPull); | 895 | None, |
| 807 | cts.set_as_af(cts.af_num(), AFType::Input); | 896 | new_dma!(tx_dma), |
| 808 | T::regs().cr3().write(|w| { | 897 | new_dma!(rx_dma), |
| 809 | w.set_rtse(true); | 898 | config, |
| 810 | w.set_ctse(true); | 899 | ) |
| 811 | }); | ||
| 812 | Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config) | ||
| 813 | } | 900 | } |
| 814 | 901 | ||
| 815 | #[cfg(not(any(usart_v1, usart_v2)))] | 902 | #[cfg(not(any(usart_v1, usart_v2)))] |
| @@ -820,21 +907,21 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 820 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 907 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 821 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 908 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 822 | de: impl Peripheral<P = impl DePin<T>> + 'd, | 909 | de: impl Peripheral<P = impl DePin<T>> + 'd, |
| 823 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 910 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| 824 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 911 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
| 825 | config: Config, | 912 | config: Config, |
| 826 | ) -> Result<Self, ConfigError> { | 913 | ) -> Result<Self, ConfigError> { |
| 827 | into_ref!(de); | 914 | Self::new_inner( |
| 828 | 915 | peri, | |
| 829 | // UartRx and UartTx have one refcount ea. | 916 | new_pin!(rx, config.rx_af()), |
| 830 | T::enable_and_reset(); | 917 | new_pin!(tx, config.tx_af()), |
| 831 | T::enable_and_reset(); | 918 | None, |
| 832 | 919 | None, | |
| 833 | de.set_as_af(de.af_num(), AFType::OutputPushPull); | 920 | new_pin!(de, AFType::OutputPushPull), |
| 834 | T::regs().cr3().write(|w| { | 921 | new_dma!(tx_dma), |
| 835 | w.set_dem(true); | 922 | new_dma!(rx_dma), |
| 836 | }); | 923 | config, |
| 837 | Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config) | 924 | ) |
| 838 | } | 925 | } |
| 839 | 926 | ||
| 840 | /// Create a single-wire half-duplex Uart transceiver on a single Tx pin. | 927 | /// Create a single-wire half-duplex Uart transceiver on a single Tx pin. |
| @@ -852,22 +939,24 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 852 | peri: impl Peripheral<P = T> + 'd, | 939 | peri: impl Peripheral<P = T> + 'd, |
| 853 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 940 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 854 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 941 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 855 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 942 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| 856 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 943 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
| 857 | mut config: Config, | 944 | mut config: Config, |
| 858 | ) -> Result<Self, ConfigError> { | 945 | ) -> Result<Self, ConfigError> { |
| 859 | // UartRx and UartTx have one refcount ea. | ||
| 860 | T::enable_and_reset(); | ||
| 861 | T::enable_and_reset(); | ||
| 862 | |||
| 863 | config.swap_rx_tx = false; | 946 | config.swap_rx_tx = false; |
| 947 | config.half_duplex = true; | ||
| 864 | 948 | ||
| 865 | into_ref!(peri, tx, tx_dma, rx_dma); | 949 | Self::new_inner( |
| 866 | 950 | peri, | |
| 867 | T::regs().cr3().write(|w| w.set_hdsel(true)); | 951 | None, |
| 868 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | 952 | new_pin!(tx, AFType::OutputPushPull), |
| 869 | 953 | None, | |
| 870 | Self::new_inner(peri, tx_dma, rx_dma, config) | 954 | None, |
| 955 | None, | ||
| 956 | new_dma!(tx_dma), | ||
| 957 | new_dma!(rx_dma), | ||
| 958 | config, | ||
| 959 | ) | ||
| 871 | } | 960 | } |
| 872 | 961 | ||
| 873 | /// Create a single-wire half-duplex Uart transceiver on a single Rx pin. | 962 | /// Create a single-wire half-duplex Uart transceiver on a single Rx pin. |
| @@ -885,62 +974,196 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 885 | peri: impl Peripheral<P = T> + 'd, | 974 | peri: impl Peripheral<P = T> + 'd, |
| 886 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 975 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 887 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 976 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 888 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 977 | tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, |
| 889 | rx_dma: impl Peripheral<P = RxDma> + 'd, | 978 | rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, |
| 890 | mut config: Config, | 979 | mut config: Config, |
| 891 | ) -> Result<Self, ConfigError> { | 980 | ) -> Result<Self, ConfigError> { |
| 892 | // UartRx and UartTx have one refcount ea. | ||
| 893 | T::enable_and_reset(); | ||
| 894 | T::enable_and_reset(); | ||
| 895 | |||
| 896 | config.swap_rx_tx = true; | 981 | config.swap_rx_tx = true; |
| 982 | config.half_duplex = true; | ||
| 983 | |||
| 984 | Self::new_inner( | ||
| 985 | peri, | ||
| 986 | None, | ||
| 987 | None, | ||
| 988 | new_pin!(rx, AFType::OutputPushPull), | ||
| 989 | None, | ||
| 990 | None, | ||
| 991 | new_dma!(tx_dma), | ||
| 992 | new_dma!(rx_dma), | ||
| 993 | config, | ||
| 994 | ) | ||
| 995 | } | ||
| 996 | |||
| 997 | /// Perform an asynchronous write | ||
| 998 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> { | ||
| 999 | self.tx.write(buffer).await | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /// Perform an asynchronous read into `buffer` | ||
| 1003 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> { | ||
| 1004 | self.rx.read(buffer).await | ||
| 1005 | } | ||
| 897 | 1006 | ||
| 898 | into_ref!(peri, rx, tx_dma, rx_dma); | 1007 | /// Perform an an asynchronous read with idle line detection enabled |
| 1008 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> { | ||
| 1009 | self.rx.read_until_idle(buffer).await | ||
| 1010 | } | ||
| 1011 | } | ||
| 899 | 1012 | ||
| 900 | T::regs().cr3().write(|w| w.set_hdsel(true)); | 1013 | impl<'d, T: BasicInstance> Uart<'d, T, Blocking> { |
| 901 | rx.set_as_af(rx.af_num(), AFType::OutputPushPull); | 1014 | /// Create a new blocking bidirectional UART. |
| 1015 | pub fn new_blocking( | ||
| 1016 | peri: impl Peripheral<P = T> + 'd, | ||
| 1017 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 1018 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | ||
| 1019 | config: Config, | ||
| 1020 | ) -> Result<Self, ConfigError> { | ||
| 1021 | Self::new_inner( | ||
| 1022 | peri, | ||
| 1023 | new_pin!(rx, config.rx_af()), | ||
| 1024 | new_pin!(tx, config.tx_af()), | ||
| 1025 | None, | ||
| 1026 | None, | ||
| 1027 | None, | ||
| 1028 | None, | ||
| 1029 | None, | ||
| 1030 | config, | ||
| 1031 | ) | ||
| 1032 | } | ||
| 902 | 1033 | ||
| 903 | Self::new_inner(peri, tx_dma, rx_dma, config) | 1034 | /// Create a new bidirectional UART with request-to-send and clear-to-send pins |
| 1035 | pub fn new_blocking_with_rtscts( | ||
| 1036 | peri: impl Peripheral<P = T> + 'd, | ||
| 1037 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 1038 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | ||
| 1039 | rts: impl Peripheral<P = impl RtsPin<T>> + 'd, | ||
| 1040 | cts: impl Peripheral<P = impl CtsPin<T>> + 'd, | ||
| 1041 | config: Config, | ||
| 1042 | ) -> Result<Self, ConfigError> { | ||
| 1043 | Self::new_inner( | ||
| 1044 | peri, | ||
| 1045 | new_pin!(rx, config.rx_af()), | ||
| 1046 | new_pin!(tx, config.tx_af()), | ||
| 1047 | new_pin!(rts, AFType::OutputPushPull), | ||
| 1048 | new_pin!(cts, AFType::Input), | ||
| 1049 | None, | ||
| 1050 | None, | ||
| 1051 | None, | ||
| 1052 | config, | ||
| 1053 | ) | ||
| 904 | } | 1054 | } |
| 905 | 1055 | ||
| 906 | fn new_inner_configure( | 1056 | #[cfg(not(any(usart_v1, usart_v2)))] |
| 1057 | /// Create a new bidirectional UART with a driver-enable pin | ||
| 1058 | pub fn new_blocking_with_de( | ||
| 907 | peri: impl Peripheral<P = T> + 'd, | 1059 | peri: impl Peripheral<P = T> + 'd, |
| 908 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | 1060 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, |
| 909 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | 1061 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, |
| 910 | tx_dma: impl Peripheral<P = TxDma> + 'd, | 1062 | de: impl Peripheral<P = impl DePin<T>> + 'd, |
| 911 | rx_dma: impl Peripheral<P = RxDma> + 'd, | ||
| 912 | config: Config, | 1063 | config: Config, |
| 913 | ) -> Result<Self, ConfigError> { | 1064 | ) -> Result<Self, ConfigError> { |
| 914 | into_ref!(peri, rx, tx, tx_dma, rx_dma); | 1065 | Self::new_inner( |
| 915 | 1066 | peri, | |
| 916 | // Some chips do not have swap_rx_tx bit | 1067 | new_pin!(rx, config.rx_af()), |
| 917 | cfg_if::cfg_if! { | 1068 | new_pin!(tx, config.tx_af()), |
| 918 | if #[cfg(any(usart_v3, usart_v4))] { | 1069 | None, |
| 919 | if config.swap_rx_tx { | 1070 | None, |
| 920 | let (rx, tx) = (tx, rx); | 1071 | new_pin!(de, AFType::OutputPushPull), |
| 921 | rx.set_as_af(rx.af_num(), AFType::Input); | 1072 | None, |
| 922 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | 1073 | None, |
| 923 | } else { | 1074 | config, |
| 924 | rx.set_as_af(rx.af_num(), AFType::Input); | 1075 | ) |
| 925 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | 1076 | } |
| 926 | } | 1077 | |
| 927 | } else { | 1078 | /// Create a single-wire half-duplex Uart transceiver on a single Tx pin. |
| 928 | rx.set_as_af(rx.af_num(), AFType::Input); | 1079 | /// |
| 929 | tx.set_as_af(tx.af_num(), AFType::OutputPushPull); | 1080 | /// See [`new_half_duplex_on_rx`][`Self::new_half_duplex_on_rx`] if you would prefer to use an Rx pin. |
| 930 | } | 1081 | /// There is no functional difference between these methods, as both allow bidirectional communication. |
| 931 | } | 1082 | /// |
| 1083 | /// The pin is always released when no data is transmitted. Thus, it acts as a standard | ||
| 1084 | /// I/O in idle or in reception. | ||
| 1085 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict | ||
| 1086 | /// on the line must be managed by software (for instance by using a centralized arbiter). | ||
| 1087 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 1088 | #[doc(alias("HDSEL"))] | ||
| 1089 | pub fn new_blocking_half_duplex( | ||
| 1090 | peri: impl Peripheral<P = T> + 'd, | ||
| 1091 | tx: impl Peripheral<P = impl TxPin<T>> + 'd, | ||
| 1092 | mut config: Config, | ||
| 1093 | ) -> Result<Self, ConfigError> { | ||
| 1094 | config.swap_rx_tx = false; | ||
| 1095 | config.half_duplex = true; | ||
| 1096 | |||
| 1097 | Self::new_inner( | ||
| 1098 | peri, | ||
| 1099 | None, | ||
| 1100 | new_pin!(tx, AFType::OutputPushPull), | ||
| 1101 | None, | ||
| 1102 | None, | ||
| 1103 | None, | ||
| 1104 | None, | ||
| 1105 | None, | ||
| 1106 | config, | ||
| 1107 | ) | ||
| 1108 | } | ||
| 932 | 1109 | ||
| 933 | Self::new_inner(peri, tx_dma, rx_dma, config) | 1110 | /// Create a single-wire half-duplex Uart transceiver on a single Rx pin. |
| 1111 | /// | ||
| 1112 | /// See [`new_half_duplex`][`Self::new_half_duplex`] if you would prefer to use an Tx pin. | ||
| 1113 | /// There is no functional difference between these methods, as both allow bidirectional communication. | ||
| 1114 | /// | ||
| 1115 | /// The pin is always released when no data is transmitted. Thus, it acts as a standard | ||
| 1116 | /// I/O in idle or in reception. | ||
| 1117 | /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict | ||
| 1118 | /// on the line must be managed by software (for instance by using a centralized arbiter). | ||
| 1119 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 1120 | #[doc(alias("HDSEL"))] | ||
| 1121 | pub fn new_blocking_half_duplex_on_rx( | ||
| 1122 | peri: impl Peripheral<P = T> + 'd, | ||
| 1123 | rx: impl Peripheral<P = impl RxPin<T>> + 'd, | ||
| 1124 | mut config: Config, | ||
| 1125 | ) -> Result<Self, ConfigError> { | ||
| 1126 | config.swap_rx_tx = true; | ||
| 1127 | config.half_duplex = true; | ||
| 1128 | |||
| 1129 | Self::new_inner( | ||
| 1130 | peri, | ||
| 1131 | None, | ||
| 1132 | None, | ||
| 1133 | new_pin!(rx, AFType::OutputPushPull), | ||
| 1134 | None, | ||
| 1135 | None, | ||
| 1136 | None, | ||
| 1137 | None, | ||
| 1138 | config, | ||
| 1139 | ) | ||
| 934 | } | 1140 | } |
| 1141 | } | ||
| 935 | 1142 | ||
| 1143 | impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> { | ||
| 936 | fn new_inner( | 1144 | fn new_inner( |
| 937 | peri: PeripheralRef<'d, T>, | 1145 | _peri: impl Peripheral<P = T> + 'd, |
| 938 | tx_dma: PeripheralRef<'d, TxDma>, | 1146 | rx: Option<PeripheralRef<'d, AnyPin>>, |
| 939 | rx_dma: PeripheralRef<'d, RxDma>, | 1147 | tx: Option<PeripheralRef<'d, AnyPin>>, |
| 1148 | rts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 1149 | cts: Option<PeripheralRef<'d, AnyPin>>, | ||
| 1150 | de: Option<PeripheralRef<'d, AnyPin>>, | ||
| 1151 | tx_dma: Option<ChannelAndRequest<'d>>, | ||
| 1152 | rx_dma: Option<ChannelAndRequest<'d>>, | ||
| 940 | config: Config, | 1153 | config: Config, |
| 941 | ) -> Result<Self, ConfigError> { | 1154 | ) -> Result<Self, ConfigError> { |
| 1155 | // UartRx and UartTx have one refcount each. | ||
| 1156 | T::enable_and_reset(); | ||
| 1157 | T::enable_and_reset(); | ||
| 1158 | |||
| 942 | let r = T::regs(); | 1159 | let r = T::regs(); |
| 943 | 1160 | ||
| 1161 | r.cr3().write(|w| { | ||
| 1162 | w.set_rtse(rts.is_some()); | ||
| 1163 | w.set_ctse(cts.is_some()); | ||
| 1164 | #[cfg(not(any(usart_v1, usart_v2)))] | ||
| 1165 | w.set_dem(de.is_some()); | ||
| 1166 | }); | ||
| 944 | configure(r, &config, T::frequency(), T::KIND, true, true)?; | 1167 | configure(r, &config, T::frequency(), T::KIND, true, true)?; |
| 945 | 1168 | ||
| 946 | T::Interrupt::unpend(); | 1169 | T::Interrupt::unpend(); |
| @@ -951,11 +1174,16 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 951 | 1174 | ||
| 952 | Ok(Self { | 1175 | Ok(Self { |
| 953 | tx: UartTx { | 1176 | tx: UartTx { |
| 1177 | _phantom: PhantomData, | ||
| 1178 | tx, | ||
| 1179 | cts, | ||
| 1180 | de, | ||
| 954 | tx_dma, | 1181 | tx_dma, |
| 955 | phantom: PhantomData, | ||
| 956 | }, | 1182 | }, |
| 957 | rx: UartRx { | 1183 | rx: UartRx { |
| 958 | _peri: peri, | 1184 | _phantom: PhantomData, |
| 1185 | rx, | ||
| 1186 | rts, | ||
| 959 | rx_dma, | 1187 | rx_dma, |
| 960 | detect_previous_overrun: config.detect_previous_overrun, | 1188 | detect_previous_overrun: config.detect_previous_overrun, |
| 961 | #[cfg(any(usart_v1, usart_v2))] | 1189 | #[cfg(any(usart_v1, usart_v2))] |
| @@ -964,14 +1192,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 964 | }) | 1192 | }) |
| 965 | } | 1193 | } |
| 966 | 1194 | ||
| 967 | /// Initiate an asynchronous write | ||
| 968 | pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> | ||
| 969 | where | ||
| 970 | TxDma: crate::usart::TxDma<T>, | ||
| 971 | { | ||
| 972 | self.tx.write(buffer).await | ||
| 973 | } | ||
| 974 | |||
| 975 | /// Perform a blocking write | 1195 | /// Perform a blocking write |
| 976 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 1196 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 977 | self.tx.blocking_write(buffer) | 1197 | self.tx.blocking_write(buffer) |
| @@ -982,16 +1202,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 982 | self.tx.blocking_flush() | 1202 | self.tx.blocking_flush() |
| 983 | } | 1203 | } |
| 984 | 1204 | ||
| 985 | /// Initiate an asynchronous read into `buffer` | ||
| 986 | pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> | ||
| 987 | where | ||
| 988 | RxDma: crate::usart::RxDma<T>, | ||
| 989 | { | ||
| 990 | self.rx.read(buffer).await | ||
| 991 | } | ||
| 992 | |||
| 993 | /// Read a single `u8` or return `WouldBlock` | 1205 | /// Read a single `u8` or return `WouldBlock` |
| 994 | pub fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { | 1206 | pub(crate) fn nb_read(&mut self) -> Result<u8, nb::Error<Error>> { |
| 995 | self.rx.nb_read() | 1207 | self.rx.nb_read() |
| 996 | } | 1208 | } |
| 997 | 1209 | ||
| @@ -1000,18 +1212,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { | |||
| 1000 | self.rx.blocking_read(buffer) | 1212 | self.rx.blocking_read(buffer) |
| 1001 | } | 1213 | } |
| 1002 | 1214 | ||
| 1003 | /// Initiate an an asynchronous read with idle line detection enabled | ||
| 1004 | pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result<usize, Error> | ||
| 1005 | where | ||
| 1006 | RxDma: crate::usart::RxDma<T>, | ||
| 1007 | { | ||
| 1008 | self.rx.read_until_idle(buffer).await | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | /// Split the Uart into a transmitter and receiver, which is | 1215 | /// Split the Uart into a transmitter and receiver, which is |
| 1012 | /// particularly useful when having two tasks correlating to | 1216 | /// particularly useful when having two tasks correlating to |
| 1013 | /// transmitting and receiving. | 1217 | /// transmitting and receiving. |
| 1014 | pub fn split(self) -> (UartTx<'d, T, TxDma>, UartRx<'d, T, RxDma>) { | 1218 | pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) { |
| 1015 | (self.tx, self.rx) | 1219 | (self.tx, self.rx) |
| 1016 | } | 1220 | } |
| 1017 | } | 1221 | } |
| @@ -1153,6 +1357,8 @@ fn configure( | |||
| 1153 | #[cfg(not(usart_v1))] | 1357 | #[cfg(not(usart_v1))] |
| 1154 | r.cr3().modify(|w| { | 1358 | r.cr3().modify(|w| { |
| 1155 | w.set_onebit(config.assume_noise_free); | 1359 | w.set_onebit(config.assume_noise_free); |
| 1360 | #[cfg(any(usart_v3, usart_v4))] | ||
| 1361 | w.set_hdsel(config.half_duplex); | ||
| 1156 | }); | 1362 | }); |
| 1157 | 1363 | ||
| 1158 | r.cr1().write(|w| { | 1364 | r.cr1().write(|w| { |
| @@ -1185,14 +1391,14 @@ fn configure( | |||
| 1185 | Ok(()) | 1391 | Ok(()) |
| 1186 | } | 1392 | } |
| 1187 | 1393 | ||
| 1188 | impl<'d, T: BasicInstance, RxDma> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, RxDma> { | 1394 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, M> { |
| 1189 | type Error = Error; | 1395 | type Error = Error; |
| 1190 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 1396 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 1191 | self.nb_read() | 1397 | self.nb_read() |
| 1192 | } | 1398 | } |
| 1193 | } | 1399 | } |
| 1194 | 1400 | ||
| 1195 | impl<'d, T: BasicInstance, TxDma> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, TxDma> { | 1401 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, M> { |
| 1196 | type Error = Error; | 1402 | type Error = Error; |
| 1197 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 1403 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| 1198 | self.blocking_write(buffer) | 1404 | self.blocking_write(buffer) |
| @@ -1202,14 +1408,14 @@ impl<'d, T: BasicInstance, TxDma> embedded_hal_02::blocking::serial::Write<u8> f | |||
| 1202 | } | 1408 | } |
| 1203 | } | 1409 | } |
| 1204 | 1410 | ||
| 1205 | impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::serial::Read<u8> for Uart<'d, T, TxDma, RxDma> { | 1411 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read<u8> for Uart<'d, T, M> { |
| 1206 | type Error = Error; | 1412 | type Error = Error; |
| 1207 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 1413 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 1208 | self.nb_read() | 1414 | self.nb_read() |
| 1209 | } | 1415 | } |
| 1210 | } | 1416 | } |
| 1211 | 1417 | ||
| 1212 | impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, TxDma, RxDma> { | 1418 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, M> { |
| 1213 | type Error = Error; | 1419 | type Error = Error; |
| 1214 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 1420 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| 1215 | self.blocking_write(buffer) | 1421 | self.blocking_write(buffer) |
| @@ -1231,25 +1437,25 @@ impl embedded_hal_nb::serial::Error for Error { | |||
| 1231 | } | 1437 | } |
| 1232 | } | 1438 | } |
| 1233 | 1439 | ||
| 1234 | impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::ErrorType for Uart<'d, T, TxDma, RxDma> { | 1440 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, T, M> { |
| 1235 | type Error = Error; | 1441 | type Error = Error; |
| 1236 | } | 1442 | } |
| 1237 | 1443 | ||
| 1238 | impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, TxDma> { | 1444 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, M> { |
| 1239 | type Error = Error; | 1445 | type Error = Error; |
| 1240 | } | 1446 | } |
| 1241 | 1447 | ||
| 1242 | impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, RxDma> { | 1448 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, M> { |
| 1243 | type Error = Error; | 1449 | type Error = Error; |
| 1244 | } | 1450 | } |
| 1245 | 1451 | ||
| 1246 | impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::Read for UartRx<'d, T, RxDma> { | 1452 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> { |
| 1247 | fn read(&mut self) -> nb::Result<u8, Self::Error> { | 1453 | fn read(&mut self) -> nb::Result<u8, Self::Error> { |
| 1248 | self.nb_read() | 1454 | self.nb_read() |
| 1249 | } | 1455 | } |
| 1250 | } | 1456 | } |
| 1251 | 1457 | ||
| 1252 | impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::Write for UartTx<'d, T, TxDma> { | 1458 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T, M> { |
| 1253 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | 1459 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
| 1254 | self.blocking_write(&[char]).map_err(nb::Error::Other) | 1460 | self.blocking_write(&[char]).map_err(nb::Error::Other) |
| 1255 | } | 1461 | } |
| @@ -1259,13 +1465,13 @@ impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::Write for UartTx<'d, | |||
| 1259 | } | 1465 | } |
| 1260 | } | 1466 | } |
| 1261 | 1467 | ||
| 1262 | impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Read for Uart<'d, T, TxDma, RxDma> { | 1468 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, T, M> { |
| 1263 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { | 1469 | fn read(&mut self) -> Result<u8, nb::Error<Self::Error>> { |
| 1264 | self.nb_read() | 1470 | self.nb_read() |
| 1265 | } | 1471 | } |
| 1266 | } | 1472 | } |
| 1267 | 1473 | ||
| 1268 | impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Write for Uart<'d, T, TxDma, RxDma> { | 1474 | impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M> { |
| 1269 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { | 1475 | fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> { |
| 1270 | self.blocking_write(&[char]).map_err(nb::Error::Other) | 1476 | self.blocking_write(&[char]).map_err(nb::Error::Other) |
| 1271 | } | 1477 | } |
| @@ -1281,21 +1487,21 @@ impl embedded_io::Error for Error { | |||
| 1281 | } | 1487 | } |
| 1282 | } | 1488 | } |
| 1283 | 1489 | ||
| 1284 | impl<T, TxDma, RxDma> embedded_io::ErrorType for Uart<'_, T, TxDma, RxDma> | 1490 | impl<T, M: Mode> embedded_io::ErrorType for Uart<'_, T, M> |
| 1285 | where | 1491 | where |
| 1286 | T: BasicInstance, | 1492 | T: BasicInstance, |
| 1287 | { | 1493 | { |
| 1288 | type Error = Error; | 1494 | type Error = Error; |
| 1289 | } | 1495 | } |
| 1290 | 1496 | ||
| 1291 | impl<T, TxDma> embedded_io::ErrorType for UartTx<'_, T, TxDma> | 1497 | impl<T, M: Mode> embedded_io::ErrorType for UartTx<'_, T, M> |
| 1292 | where | 1498 | where |
| 1293 | T: BasicInstance, | 1499 | T: BasicInstance, |
| 1294 | { | 1500 | { |
| 1295 | type Error = Error; | 1501 | type Error = Error; |
| 1296 | } | 1502 | } |
| 1297 | 1503 | ||
| 1298 | impl<T, TxDma, RxDma> embedded_io::Write for Uart<'_, T, TxDma, RxDma> | 1504 | impl<T, M: Mode> embedded_io::Write for Uart<'_, T, M> |
| 1299 | where | 1505 | where |
| 1300 | T: BasicInstance, | 1506 | T: BasicInstance, |
| 1301 | { | 1507 | { |
| @@ -1309,7 +1515,7 @@ where | |||
| 1309 | } | 1515 | } |
| 1310 | } | 1516 | } |
| 1311 | 1517 | ||
| 1312 | impl<T, TxDma> embedded_io::Write for UartTx<'_, T, TxDma> | 1518 | impl<T, M: Mode> embedded_io::Write for UartTx<'_, T, M> |
| 1313 | where | 1519 | where |
| 1314 | T: BasicInstance, | 1520 | T: BasicInstance, |
| 1315 | { | 1521 | { |
| @@ -1323,10 +1529,9 @@ where | |||
| 1323 | } | 1529 | } |
| 1324 | } | 1530 | } |
| 1325 | 1531 | ||
| 1326 | impl<T, TxDma, RxDma> embedded_io_async::Write for Uart<'_, T, TxDma, RxDma> | 1532 | impl<T> embedded_io_async::Write for Uart<'_, T, Async> |
| 1327 | where | 1533 | where |
| 1328 | T: BasicInstance, | 1534 | T: BasicInstance, |
| 1329 | TxDma: self::TxDma<T>, | ||
| 1330 | { | 1535 | { |
| 1331 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1536 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1332 | self.write(buf).await?; | 1537 | self.write(buf).await?; |
| @@ -1338,10 +1543,9 @@ where | |||
| 1338 | } | 1543 | } |
| 1339 | } | 1544 | } |
| 1340 | 1545 | ||
| 1341 | impl<T, TxDma> embedded_io_async::Write for UartTx<'_, T, TxDma> | 1546 | impl<T> embedded_io_async::Write for UartTx<'_, T, Async> |
| 1342 | where | 1547 | where |
| 1343 | T: BasicInstance, | 1548 | T: BasicInstance, |
| 1344 | TxDma: self::TxDma<T>, | ||
| 1345 | { | 1549 | { |
| 1346 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 1550 | async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 1347 | self.write(buf).await?; | 1551 | self.write(buf).await?; |
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index b852f0176..8eb18fe5b 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -1,21 +1,22 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::marker::PhantomData; | ||
| 2 | use core::mem; | 3 | use core::mem; |
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 4 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 4 | use core::task::Poll; | 5 | use core::task::Poll; |
| 5 | 6 | ||
| 6 | use embassy_embedded_hal::SetConfig; | 7 | use embassy_embedded_hal::SetConfig; |
| 7 | use embassy_hal_internal::PeripheralRef; | ||
| 8 | use futures::future::{select, Either}; | 8 | use futures::future::{select, Either}; |
| 9 | 9 | ||
| 10 | use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx}; | 10 | use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx}; |
| 11 | use crate::dma::ReadableRingBuffer; | 11 | use crate::dma::ReadableRingBuffer; |
| 12 | use crate::mode::Async; | ||
| 12 | use crate::usart::{Regs, Sr}; | 13 | use crate::usart::{Regs, Sr}; |
| 13 | 14 | ||
| 14 | /// Rx-only Ring-buffered UART Driver | 15 | /// Rx-only Ring-buffered UART Driver |
| 15 | /// | 16 | /// |
| 16 | /// Created with [UartRx::into_ring_buffered] | 17 | /// Created with [UartRx::into_ring_buffered] |
| 17 | pub struct RingBufferedUartRx<'d, T: BasicInstance> { | 18 | pub struct RingBufferedUartRx<'d, T: BasicInstance> { |
| 18 | _peri: PeripheralRef<'d, T>, | 19 | _phantom: PhantomData<T>, |
| 19 | ring_buf: ReadableRingBuffer<'d, u8>, | 20 | ring_buf: ReadableRingBuffer<'d, u8>, |
| 20 | } | 21 | } |
| 21 | 22 | ||
| @@ -28,26 +29,29 @@ impl<'d, T: BasicInstance> SetConfig for RingBufferedUartRx<'d, T> { | |||
| 28 | } | 29 | } |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { | 32 | impl<'d, T: BasicInstance> UartRx<'d, T, Async> { |
| 32 | /// Turn the `UartRx` into a buffered uart which can continously receive in the background | 33 | /// Turn the `UartRx` into a buffered uart which can continously receive in the background |
| 33 | /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the | 34 | /// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the |
| 34 | /// DMA controller, and must be large enough to prevent overflows. | 35 | /// DMA controller, and must be large enough to prevent overflows. |
| 35 | pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T> { | 36 | pub fn into_ring_buffered(mut self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T> { |
| 36 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); | 37 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); |
| 37 | 38 | ||
| 38 | let request = self.rx_dma.request(); | ||
| 39 | let opts = Default::default(); | 39 | let opts = Default::default(); |
| 40 | 40 | ||
| 41 | // Safety: we forget the struct before this function returns. | 41 | // Safety: we forget the struct before this function returns. |
| 42 | let rx_dma = unsafe { self.rx_dma.clone_unchecked() }; | 42 | let rx_dma = self.rx_dma.as_mut().unwrap(); |
| 43 | let _peri = unsafe { self._peri.clone_unchecked() }; | 43 | let request = rx_dma.request; |
| 44 | let rx_dma = unsafe { rx_dma.channel.clone_unchecked() }; | ||
| 44 | 45 | ||
| 45 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; | 46 | let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) }; |
| 46 | 47 | ||
| 47 | // Don't disable the clock | 48 | // Don't disable the clock |
| 48 | mem::forget(self); | 49 | mem::forget(self); |
| 49 | 50 | ||
| 50 | RingBufferedUartRx { _peri, ring_buf } | 51 | RingBufferedUartRx { |
| 52 | _phantom: PhantomData, | ||
| 53 | ring_buf, | ||
| 54 | } | ||
| 51 | } | 55 | } |
| 52 | } | 56 | } |
| 53 | 57 | ||
diff --git a/examples/stm32f3/src/bin/usart_dma.rs b/examples/stm32f3/src/bin/usart_dma.rs index 5234e53b9..573a49f19 100644 --- a/examples/stm32f3/src/bin/usart_dma.rs +++ b/examples/stm32f3/src/bin/usart_dma.rs | |||
| @@ -5,7 +5,6 @@ use core::fmt::Write; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::dma::NoDma; | ||
| 9 | use embassy_stm32::usart::{Config, Uart}; | 8 | use embassy_stm32::usart::{Config, Uart}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 11 | use heapless::String; | 10 | use heapless::String; |
| @@ -21,7 +20,7 @@ async fn main(_spawner: Spawner) { | |||
| 21 | info!("Hello World!"); | 20 | info!("Hello World!"); |
| 22 | 21 | ||
| 23 | let config = Config::default(); | 22 | let config = Config::default(); |
| 24 | let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, Irqs, p.DMA1_CH4, NoDma, config).unwrap(); | 23 | let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, Irqs, p.DMA1_CH4, p.DMA1_CH5, config).unwrap(); |
| 25 | 24 | ||
| 26 | for n in 0u32.. { | 25 | for n in 0u32.. { |
| 27 | let mut s: String<128> = String::new(); | 26 | let mut s: String<128> = String::new(); |
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs index 40d9d70f1..991bf6673 100644 --- a/examples/stm32f4/src/bin/usart.rs +++ b/examples/stm32f4/src/bin/usart.rs | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_stm32::dma::NoDma; | ||
| 7 | use embassy_stm32::usart::{Config, Uart}; | 6 | use embassy_stm32::usart::{Config, Uart}; |
| 8 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 7 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -19,7 +18,7 @@ fn main() -> ! { | |||
| 19 | let p = embassy_stm32::init(Default::default()); | 18 | let p = embassy_stm32::init(Default::default()); |
| 20 | 19 | ||
| 21 | let config = Config::default(); | 20 | let config = Config::default(); |
| 22 | let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, NoDma, NoDma, config).unwrap(); | 21 | let mut usart = Uart::new_blocking(p.USART3, p.PD9, p.PD8, config).unwrap(); |
| 23 | 22 | ||
| 24 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); | 23 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); |
| 25 | info!("wrote Hello, starting echo"); | 24 | info!("wrote Hello, starting echo"); |
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs index dd6de599c..aaf8d6c4f 100644 --- a/examples/stm32f4/src/bin/usart_dma.rs +++ b/examples/stm32f4/src/bin/usart_dma.rs | |||
| @@ -5,7 +5,6 @@ use core::fmt::Write; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::dma::NoDma; | ||
| 9 | use embassy_stm32::usart::{Config, Uart}; | 8 | use embassy_stm32::usart::{Config, Uart}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 11 | use heapless::String; | 10 | use heapless::String; |
| @@ -21,7 +20,7 @@ async fn main(_spawner: Spawner) { | |||
| 21 | info!("Hello World!"); | 20 | info!("Hello World!"); |
| 22 | 21 | ||
| 23 | let config = Config::default(); | 22 | let config = Config::default(); |
| 24 | let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, p.DMA1_CH3, NoDma, config).unwrap(); | 23 | let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, p.DMA1_CH3, p.DMA1_CH1, config).unwrap(); |
| 25 | 24 | ||
| 26 | for n in 0u32.. { | 25 | for n in 0u32.. { |
| 27 | let mut s: String<128> = String::new(); | 26 | let mut s: String<128> = String::new(); |
diff --git a/examples/stm32f7/src/bin/usart_dma.rs b/examples/stm32f7/src/bin/usart_dma.rs index fb604b34f..47456adf2 100644 --- a/examples/stm32f7/src/bin/usart_dma.rs +++ b/examples/stm32f7/src/bin/usart_dma.rs | |||
| @@ -5,7 +5,6 @@ use core::fmt::Write; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::dma::NoDma; | ||
| 9 | use embassy_stm32::usart::{Config, Uart}; | 8 | use embassy_stm32::usart::{Config, Uart}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 11 | use heapless::String; | 10 | use heapless::String; |
| @@ -19,7 +18,7 @@ bind_interrupts!(struct Irqs { | |||
| 19 | async fn main(_spawner: Spawner) { | 18 | async fn main(_spawner: Spawner) { |
| 20 | let p = embassy_stm32::init(Default::default()); | 19 | let p = embassy_stm32::init(Default::default()); |
| 21 | let config = Config::default(); | 20 | let config = Config::default(); |
| 22 | let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, Irqs, p.DMA1_CH1, NoDma, config).unwrap(); | 21 | let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, Irqs, p.DMA1_CH1, p.DMA1_CH3, config).unwrap(); |
| 23 | 22 | ||
| 24 | for n in 0u32.. { | 23 | for n in 0u32.. { |
| 25 | let mut s: String<128> = String::new(); | 24 | let mut s: String<128> = String::new(); |
diff --git a/examples/stm32h5/src/bin/usart.rs b/examples/stm32h5/src/bin/usart.rs index f9cbad6af..cc49c2fdb 100644 --- a/examples/stm32h5/src/bin/usart.rs +++ b/examples/stm32h5/src/bin/usart.rs | |||
| @@ -4,22 +4,16 @@ | |||
| 4 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Executor; | 6 | use embassy_executor::Executor; |
| 7 | use embassy_stm32::dma::NoDma; | ||
| 8 | use embassy_stm32::usart::{Config, Uart}; | 7 | use embassy_stm32::usart::{Config, Uart}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 10 | use static_cell::StaticCell; | 8 | use static_cell::StaticCell; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 10 | ||
| 13 | bind_interrupts!(struct Irqs { | ||
| 14 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 15 | }); | ||
| 16 | |||
| 17 | #[embassy_executor::task] | 11 | #[embassy_executor::task] |
| 18 | async fn main_task() { | 12 | async fn main_task() { |
| 19 | let p = embassy_stm32::init(Default::default()); | 13 | let p = embassy_stm32::init(Default::default()); |
| 20 | 14 | ||
| 21 | let config = Config::default(); | 15 | let config = Config::default(); |
| 22 | let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config).unwrap(); | 16 | let mut usart = Uart::new_blocking(p.UART7, p.PF6, p.PF7, config).unwrap(); |
| 23 | 17 | ||
| 24 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); | 18 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); |
| 25 | info!("wrote Hello, starting echo"); | 19 | info!("wrote Hello, starting echo"); |
diff --git a/examples/stm32h5/src/bin/usart_dma.rs b/examples/stm32h5/src/bin/usart_dma.rs index caae0dd18..c644e84bd 100644 --- a/examples/stm32h5/src/bin/usart_dma.rs +++ b/examples/stm32h5/src/bin/usart_dma.rs | |||
| @@ -6,7 +6,6 @@ use core::fmt::Write; | |||
| 6 | use cortex_m_rt::entry; | 6 | use cortex_m_rt::entry; |
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Executor; | 8 | use embassy_executor::Executor; |
| 9 | use embassy_stm32::dma::NoDma; | ||
| 10 | use embassy_stm32::usart::{Config, Uart}; | 9 | use embassy_stm32::usart::{Config, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 12 | use heapless::String; | 11 | use heapless::String; |
| @@ -22,7 +21,7 @@ async fn main_task() { | |||
| 22 | let p = embassy_stm32::init(Default::default()); | 21 | let p = embassy_stm32::init(Default::default()); |
| 23 | 22 | ||
| 24 | let config = Config::default(); | 23 | let config = Config::default(); |
| 25 | let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, NoDma, config).unwrap(); | 24 | let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1, config).unwrap(); |
| 26 | 25 | ||
| 27 | for n in 0u32.. { | 26 | for n in 0u32.. { |
| 28 | let mut s: String<128> = String::new(); | 27 | let mut s: String<128> = String::new(); |
diff --git a/examples/stm32h5/src/bin/usart_split.rs b/examples/stm32h5/src/bin/usart_split.rs index 92047de8d..77b4caa9e 100644 --- a/examples/stm32h5/src/bin/usart_split.rs +++ b/examples/stm32h5/src/bin/usart_split.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dma::NoDma; | 6 | use embassy_stm32::mode::Async; |
| 7 | use embassy_stm32::peripherals::{GPDMA1_CH1, UART7}; | 7 | use embassy_stm32::peripherals::UART7; |
| 8 | use embassy_stm32::usart::{Config, Uart, UartRx}; | 8 | use embassy_stm32::usart::{Config, Uart, UartRx}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| @@ -15,18 +15,6 @@ bind_interrupts!(struct Irqs { | |||
| 15 | UART7 => usart::InterruptHandler<peripherals::UART7>; | 15 | UART7 => usart::InterruptHandler<peripherals::UART7>; |
| 16 | }); | 16 | }); |
| 17 | 17 | ||
| 18 | #[embassy_executor::task] | ||
| 19 | async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) { | ||
| 20 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); | ||
| 21 | info!("wrote Hello, starting echo"); | ||
| 22 | |||
| 23 | let mut buf = [0u8; 1]; | ||
| 24 | loop { | ||
| 25 | unwrap!(usart.blocking_read(&mut buf)); | ||
| 26 | unwrap!(usart.blocking_write(&buf)); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); | 18 | static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); |
| 31 | 19 | ||
| 32 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| @@ -50,7 +38,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 50 | } | 38 | } |
| 51 | 39 | ||
| 52 | #[embassy_executor::task] | 40 | #[embassy_executor::task] |
| 53 | async fn reader(mut rx: UartRx<'static, UART7, GPDMA1_CH1>) { | 41 | async fn reader(mut rx: UartRx<'static, UART7, Async>) { |
| 54 | let mut buf = [0; 8]; | 42 | let mut buf = [0; 8]; |
| 55 | loop { | 43 | loop { |
| 56 | info!("reading..."); | 44 | info!("reading..."); |
diff --git a/examples/stm32h7/src/bin/usart.rs b/examples/stm32h7/src/bin/usart.rs index f9cbad6af..cc49c2fdb 100644 --- a/examples/stm32h7/src/bin/usart.rs +++ b/examples/stm32h7/src/bin/usart.rs | |||
| @@ -4,22 +4,16 @@ | |||
| 4 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Executor; | 6 | use embassy_executor::Executor; |
| 7 | use embassy_stm32::dma::NoDma; | ||
| 8 | use embassy_stm32::usart::{Config, Uart}; | 7 | use embassy_stm32::usart::{Config, Uart}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | ||
| 10 | use static_cell::StaticCell; | 8 | use static_cell::StaticCell; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 10 | ||
| 13 | bind_interrupts!(struct Irqs { | ||
| 14 | UART7 => usart::InterruptHandler<peripherals::UART7>; | ||
| 15 | }); | ||
| 16 | |||
| 17 | #[embassy_executor::task] | 11 | #[embassy_executor::task] |
| 18 | async fn main_task() { | 12 | async fn main_task() { |
| 19 | let p = embassy_stm32::init(Default::default()); | 13 | let p = embassy_stm32::init(Default::default()); |
| 20 | 14 | ||
| 21 | let config = Config::default(); | 15 | let config = Config::default(); |
| 22 | let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config).unwrap(); | 16 | let mut usart = Uart::new_blocking(p.UART7, p.PF6, p.PF7, config).unwrap(); |
| 23 | 17 | ||
| 24 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); | 18 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); |
| 25 | info!("wrote Hello, starting echo"); | 19 | info!("wrote Hello, starting echo"); |
diff --git a/examples/stm32h7/src/bin/usart_dma.rs b/examples/stm32h7/src/bin/usart_dma.rs index ae1f3a2e9..6f340d40a 100644 --- a/examples/stm32h7/src/bin/usart_dma.rs +++ b/examples/stm32h7/src/bin/usart_dma.rs | |||
| @@ -6,7 +6,6 @@ use core::fmt::Write; | |||
| 6 | use cortex_m_rt::entry; | 6 | use cortex_m_rt::entry; |
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Executor; | 8 | use embassy_executor::Executor; |
| 9 | use embassy_stm32::dma::NoDma; | ||
| 10 | use embassy_stm32::usart::{Config, Uart}; | 9 | use embassy_stm32::usart::{Config, Uart}; |
| 11 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 12 | use heapless::String; | 11 | use heapless::String; |
| @@ -22,7 +21,7 @@ async fn main_task() { | |||
| 22 | let p = embassy_stm32::init(Default::default()); | 21 | let p = embassy_stm32::init(Default::default()); |
| 23 | 22 | ||
| 24 | let config = Config::default(); | 23 | let config = Config::default(); |
| 25 | let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, NoDma, config).unwrap(); | 24 | let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, p.DMA1_CH1, config).unwrap(); |
| 26 | 25 | ||
| 27 | for n in 0u32.. { | 26 | for n in 0u32.. { |
| 28 | let mut s: String<128> = String::new(); | 27 | let mut s: String<128> = String::new(); |
diff --git a/examples/stm32h7/src/bin/usart_split.rs b/examples/stm32h7/src/bin/usart_split.rs index b98c40877..4ad8e77ce 100644 --- a/examples/stm32h7/src/bin/usart_split.rs +++ b/examples/stm32h7/src/bin/usart_split.rs | |||
| @@ -3,8 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dma::NoDma; | 6 | use embassy_stm32::mode::Async; |
| 7 | use embassy_stm32::peripherals::{DMA1_CH1, UART7}; | 7 | use embassy_stm32::peripherals::UART7; |
| 8 | use embassy_stm32::usart::{Config, Uart, UartRx}; | 8 | use embassy_stm32::usart::{Config, Uart, UartRx}; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; | 10 | use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; |
| @@ -15,18 +15,6 @@ bind_interrupts!(struct Irqs { | |||
| 15 | UART7 => usart::InterruptHandler<peripherals::UART7>; | 15 | UART7 => usart::InterruptHandler<peripherals::UART7>; |
| 16 | }); | 16 | }); |
| 17 | 17 | ||
| 18 | #[embassy_executor::task] | ||
| 19 | async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) { | ||
| 20 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); | ||
| 21 | info!("wrote Hello, starting echo"); | ||
| 22 | |||
| 23 | let mut buf = [0u8; 1]; | ||
| 24 | loop { | ||
| 25 | unwrap!(usart.blocking_read(&mut buf)); | ||
| 26 | unwrap!(usart.blocking_write(&buf)); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); | 18 | static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); |
| 31 | 19 | ||
| 32 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| @@ -50,7 +38,7 @@ async fn main(spawner: Spawner) -> ! { | |||
| 50 | } | 38 | } |
| 51 | 39 | ||
| 52 | #[embassy_executor::task] | 40 | #[embassy_executor::task] |
| 53 | async fn reader(mut rx: UartRx<'static, UART7, DMA1_CH1>) { | 41 | async fn reader(mut rx: UartRx<'static, UART7, Async>) { |
| 54 | let mut buf = [0; 8]; | 42 | let mut buf = [0; 8]; |
| 55 | loop { | 43 | loop { |
| 56 | info!("reading..."); | 44 | info!("reading..."); |
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs index 7bab23950..d9b388026 100644 --- a/examples/stm32l4/src/bin/usart.rs +++ b/examples/stm32l4/src/bin/usart.rs | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::dma::NoDma; | ||
| 6 | use embassy_stm32::usart::{Config, Uart}; | 5 | use embassy_stm32::usart::{Config, Uart}; |
| 7 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 6 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -18,7 +17,7 @@ fn main() -> ! { | |||
| 18 | let p = embassy_stm32::init(Default::default()); | 17 | let p = embassy_stm32::init(Default::default()); |
| 19 | 18 | ||
| 20 | let config = Config::default(); | 19 | let config = Config::default(); |
| 21 | let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, NoDma, NoDma, config).unwrap(); | 20 | let mut usart = Uart::new_blocking(p.UART4, p.PA1, p.PA0, config).unwrap(); |
| 22 | 21 | ||
| 23 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); | 22 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); |
| 24 | info!("wrote Hello, starting echo"); | 23 | info!("wrote Hello, starting echo"); |
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs index 031888f70..b4f7a1643 100644 --- a/examples/stm32l4/src/bin/usart_dma.rs +++ b/examples/stm32l4/src/bin/usart_dma.rs | |||
| @@ -5,7 +5,6 @@ use core::fmt::Write; | |||
| 5 | 5 | ||
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::dma::NoDma; | ||
| 9 | use embassy_stm32::usart::{Config, Uart}; | 8 | use embassy_stm32::usart::{Config, Uart}; |
| 10 | use embassy_stm32::{bind_interrupts, peripherals, usart}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, usart}; |
| 11 | use heapless::String; | 10 | use heapless::String; |
| @@ -21,7 +20,7 @@ async fn main(_spawner: Spawner) { | |||
| 21 | info!("Hello World!"); | 20 | info!("Hello World!"); |
| 22 | 21 | ||
| 23 | let config = Config::default(); | 22 | let config = Config::default(); |
| 24 | let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, NoDma, config).unwrap(); | 23 | let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, p.DMA1_CH4, config).unwrap(); |
| 25 | 24 | ||
| 26 | for n in 0u32.. { | 25 | for n in 0u32.. { |
| 27 | let mut s: String<128> = String::new(); | 26 | let mut s: String<128> = String::new(); |
diff --git a/tests/stm32/src/bin/usart.rs b/tests/stm32/src/bin/usart.rs index 9b20eb784..a6e34674d 100644 --- a/tests/stm32/src/bin/usart.rs +++ b/tests/stm32/src/bin/usart.rs | |||
| @@ -6,7 +6,6 @@ mod common; | |||
| 6 | use common::*; | 6 | use common::*; |
| 7 | use defmt::{assert, assert_eq, unreachable}; | 7 | use defmt::{assert, assert_eq, unreachable}; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::dma::NoDma; | ||
| 10 | use embassy_stm32::usart::{Config, ConfigError, Error, Uart}; | 9 | use embassy_stm32::usart::{Config, ConfigError, Error, Uart}; |
| 11 | use embassy_time::{block_for, Duration, Instant}; | 10 | use embassy_time::{block_for, Duration, Instant}; |
| 12 | 11 | ||
| @@ -20,11 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 20 | let mut usart = peri!(p, UART); | 19 | let mut usart = peri!(p, UART); |
| 21 | let mut rx = peri!(p, UART_RX); | 20 | let mut rx = peri!(p, UART_RX); |
| 22 | let mut tx = peri!(p, UART_TX); | 21 | let mut tx = peri!(p, UART_TX); |
| 23 | let irq = irqs!(UART); | ||
| 24 | 22 | ||
| 25 | { | 23 | { |
| 26 | let config = Config::default(); | 24 | let config = Config::default(); |
| 27 | let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, irq, NoDma, NoDma, config).unwrap(); | 25 | let mut usart = Uart::new_blocking(&mut usart, &mut rx, &mut tx, config).unwrap(); |
| 28 | 26 | ||
| 29 | // We can't send too many bytes, they have to fit in the FIFO. | 27 | // We can't send too many bytes, they have to fit in the FIFO. |
| 30 | // This is because we aren't sending+receiving at the same time. | 28 | // This is because we aren't sending+receiving at the same time. |
| @@ -40,7 +38,7 @@ async fn main(_spawner: Spawner) { | |||
| 40 | // Test error handling with with an overflow error | 38 | // Test error handling with with an overflow error |
| 41 | { | 39 | { |
| 42 | let config = Config::default(); | 40 | let config = Config::default(); |
| 43 | let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, irq, NoDma, NoDma, config).unwrap(); | 41 | let mut usart = Uart::new_blocking(&mut usart, &mut rx, &mut tx, config).unwrap(); |
| 44 | 42 | ||
| 45 | // Send enough bytes to fill the RX FIFOs off all USART versions. | 43 | // Send enough bytes to fill the RX FIFOs off all USART versions. |
| 46 | let data = [0; 64]; | 44 | let data = [0; 64]; |
| @@ -70,7 +68,7 @@ async fn main(_spawner: Spawner) { | |||
| 70 | 68 | ||
| 71 | let mut config = Config::default(); | 69 | let mut config = Config::default(); |
| 72 | config.baudrate = baudrate; | 70 | config.baudrate = baudrate; |
| 73 | let mut usart = match Uart::new(&mut usart, &mut rx, &mut tx, irq, NoDma, NoDma, config) { | 71 | let mut usart = match Uart::new_blocking(&mut usart, &mut rx, &mut tx, config) { |
| 74 | Ok(x) => x, | 72 | Ok(x) => x, |
| 75 | Err(ConfigError::BaudrateTooHigh) => { | 73 | Err(ConfigError::BaudrateTooHigh) => { |
| 76 | info!("baudrate too high"); | 74 | info!("baudrate too high"); |
diff --git a/tests/stm32/src/bin/usart_rx_ringbuffered.rs b/tests/stm32/src/bin/usart_rx_ringbuffered.rs index 0c110421d..908452eaf 100644 --- a/tests/stm32/src/bin/usart_rx_ringbuffered.rs +++ b/tests/stm32/src/bin/usart_rx_ringbuffered.rs | |||
| @@ -8,6 +8,7 @@ mod common; | |||
| 8 | use common::*; | 8 | use common::*; |
| 9 | use defmt::{assert_eq, panic}; | 9 | use defmt::{assert_eq, panic}; |
| 10 | use embassy_executor::Spawner; | 10 | use embassy_executor::Spawner; |
| 11 | use embassy_stm32::mode::Async; | ||
| 11 | use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx}; | 12 | use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx}; |
| 12 | use embassy_time::Timer; | 13 | use embassy_time::Timer; |
| 13 | use rand_chacha::ChaCha8Rng; | 14 | use rand_chacha::ChaCha8Rng; |
| @@ -51,7 +52,7 @@ async fn main(spawner: Spawner) { | |||
| 51 | } | 52 | } |
| 52 | 53 | ||
| 53 | #[embassy_executor::task] | 54 | #[embassy_executor::task] |
| 54 | async fn transmit_task(mut tx: UartTx<'static, peris::UART, peris::UART_TX_DMA>) { | 55 | async fn transmit_task(mut tx: UartTx<'static, peris::UART, Async>) { |
| 55 | // workaround https://github.com/embassy-rs/embassy/issues/1426 | 56 | // workaround https://github.com/embassy-rs/embassy/issues/1426 |
| 56 | Timer::after_millis(100).await; | 57 | Timer::after_millis(100).await; |
| 57 | 58 | ||
