aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-04-16 00:05:43 +0000
committerGitHub <[email protected]>2024-04-16 00:05:43 +0000
commite38f1011d6234fbc51fbbbb2d93365517705e3ac (patch)
tree1bda1d6cd4316c24dc5f7c2cc362d3513167c860
parent524c24c8b3ee3693c3bacd20deede29eb1107159 (diff)
parentd6b1233f16407e3501efcd1885460645a75ed57b (diff)
Merge pull request #2821 from embassy-rs/usart-nodma
stm32/usart: remove DMA generic params.
-rw-r--r--embassy-stm32/src/macros.rs10
-rw-r--r--embassy-stm32/src/usart/mod.rs854
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs20
-rw-r--r--examples/stm32f3/src/bin/usart_dma.rs3
-rw-r--r--examples/stm32f4/src/bin/usart.rs3
-rw-r--r--examples/stm32f4/src/bin/usart_dma.rs3
-rw-r--r--examples/stm32f7/src/bin/usart_dma.rs3
-rw-r--r--examples/stm32h5/src/bin/usart.rs8
-rw-r--r--examples/stm32h5/src/bin/usart_dma.rs3
-rw-r--r--examples/stm32h5/src/bin/usart_split.rs18
-rw-r--r--examples/stm32h7/src/bin/usart.rs8
-rw-r--r--examples/stm32h7/src/bin/usart_dma.rs3
-rw-r--r--examples/stm32h7/src/bin/usart_split.rs18
-rw-r--r--examples/stm32l4/src/bin/usart.rs3
-rw-r--r--examples/stm32l4/src/bin/usart_dma.rs3
-rw-r--r--tests/stm32/src/bin/usart.rs8
-rw-r--r--tests/stm32/src/bin/usart_rx_ringbuffered.rs3
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
84macro_rules! new_pin { 84macro_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};
13use embassy_sync::waitqueue::AtomicWaker; 13use embassy_sync::waitqueue::AtomicWaker;
14use futures::future::{select, Either}; 14use futures::future::{select, Either};
15 15
16use crate::dma::{NoDma, Transfer}; 16use crate::dma::ChannelAndRequest;
17use crate::gpio::AFType; 17use crate::gpio::{AFType, AnyPin, SealedPin};
18use crate::interrupt::typelevel::Interrupt; 18use crate::interrupt::typelevel::Interrupt;
19use 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)))]
21use crate::pac::usart::regs::Isr as Sr; 22use 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
171impl 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
167impl Default for Config { 188impl 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`.
220pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> { 242pub 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
225impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> { 247impl<'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.
239pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { 261pub 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
244impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> { 269impl<'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).
282pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { 307pub 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
290impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> { 317impl<'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
299impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { 326impl<'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( 374impl<'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); 403impl<'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
394impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> { 454impl<'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
758impl<'d, T: BasicInstance, TxDma> Drop for UartTx<'d, T, TxDma> { 695impl<'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
724impl<'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
836impl<'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
764impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> { 845impl<'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
770impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 853impl<'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)); 1013impl<'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
1143impl<'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
1188impl<'d, T: BasicInstance, RxDma> embedded_hal_02::serial::Read<u8> for UartRx<'d, T, RxDma> { 1394impl<'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
1195impl<'d, T: BasicInstance, TxDma> embedded_hal_02::blocking::serial::Write<u8> for UartTx<'d, T, TxDma> { 1401impl<'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
1205impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::serial::Read<u8> for Uart<'d, T, TxDma, RxDma> { 1411impl<'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
1212impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write<u8> for Uart<'d, T, TxDma, RxDma> { 1418impl<'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
1234impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::ErrorType for Uart<'d, T, TxDma, RxDma> { 1440impl<'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
1238impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, TxDma> { 1444impl<'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
1242impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, RxDma> { 1448impl<'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
1246impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::Read for UartRx<'d, T, RxDma> { 1452impl<'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
1252impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::Write for UartTx<'d, T, TxDma> { 1458impl<'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
1262impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Read for Uart<'d, T, TxDma, RxDma> { 1468impl<'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
1268impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Write for Uart<'d, T, TxDma, RxDma> { 1474impl<'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
1284impl<T, TxDma, RxDma> embedded_io::ErrorType for Uart<'_, T, TxDma, RxDma> 1490impl<T, M: Mode> embedded_io::ErrorType for Uart<'_, T, M>
1285where 1491where
1286 T: BasicInstance, 1492 T: BasicInstance,
1287{ 1493{
1288 type Error = Error; 1494 type Error = Error;
1289} 1495}
1290 1496
1291impl<T, TxDma> embedded_io::ErrorType for UartTx<'_, T, TxDma> 1497impl<T, M: Mode> embedded_io::ErrorType for UartTx<'_, T, M>
1292where 1498where
1293 T: BasicInstance, 1499 T: BasicInstance,
1294{ 1500{
1295 type Error = Error; 1501 type Error = Error;
1296} 1502}
1297 1503
1298impl<T, TxDma, RxDma> embedded_io::Write for Uart<'_, T, TxDma, RxDma> 1504impl<T, M: Mode> embedded_io::Write for Uart<'_, T, M>
1299where 1505where
1300 T: BasicInstance, 1506 T: BasicInstance,
1301{ 1507{
@@ -1309,7 +1515,7 @@ where
1309 } 1515 }
1310} 1516}
1311 1517
1312impl<T, TxDma> embedded_io::Write for UartTx<'_, T, TxDma> 1518impl<T, M: Mode> embedded_io::Write for UartTx<'_, T, M>
1313where 1519where
1314 T: BasicInstance, 1520 T: BasicInstance,
1315{ 1521{
@@ -1323,10 +1529,9 @@ where
1323 } 1529 }
1324} 1530}
1325 1531
1326impl<T, TxDma, RxDma> embedded_io_async::Write for Uart<'_, T, TxDma, RxDma> 1532impl<T> embedded_io_async::Write for Uart<'_, T, Async>
1327where 1533where
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
1341impl<T, TxDma> embedded_io_async::Write for UartTx<'_, T, TxDma> 1546impl<T> embedded_io_async::Write for UartTx<'_, T, Async>
1342where 1547where
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 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::marker::PhantomData;
2use core::mem; 3use core::mem;
3use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll; 5use core::task::Poll;
5 6
6use embassy_embedded_hal::SetConfig; 7use embassy_embedded_hal::SetConfig;
7use embassy_hal_internal::PeripheralRef;
8use futures::future::{select, Either}; 8use futures::future::{select, Either};
9 9
10use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx}; 10use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx};
11use crate::dma::ReadableRingBuffer; 11use crate::dma::ReadableRingBuffer;
12use crate::mode::Async;
12use crate::usart::{Regs, Sr}; 13use 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]
17pub struct RingBufferedUartRx<'d, T: BasicInstance> { 18pub 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
31impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { 32impl<'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
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::dma::NoDma;
9use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
10use embassy_stm32::{bind_interrupts, peripherals, usart}; 9use embassy_stm32::{bind_interrupts, peripherals, usart};
11use heapless::String; 10use 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
4use cortex_m_rt::entry; 4use cortex_m_rt::entry;
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dma::NoDma;
7use embassy_stm32::usart::{Config, Uart}; 6use embassy_stm32::usart::{Config, Uart};
8use embassy_stm32::{bind_interrupts, peripherals, usart}; 7use embassy_stm32::{bind_interrupts, peripherals, usart};
9use {defmt_rtt as _, panic_probe as _}; 8use {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
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::dma::NoDma;
9use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
10use embassy_stm32::{bind_interrupts, peripherals, usart}; 9use embassy_stm32::{bind_interrupts, peripherals, usart};
11use heapless::String; 10use 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
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::dma::NoDma;
9use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
10use embassy_stm32::{bind_interrupts, peripherals, usart}; 9use embassy_stm32::{bind_interrupts, peripherals, usart};
11use heapless::String; 10use heapless::String;
@@ -19,7 +18,7 @@ bind_interrupts!(struct Irqs {
19async fn main(_spawner: Spawner) { 18async 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 @@
4use cortex_m_rt::entry; 4use cortex_m_rt::entry;
5use defmt::*; 5use defmt::*;
6use embassy_executor::Executor; 6use embassy_executor::Executor;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::usart::{Config, Uart}; 7use embassy_stm32::usart::{Config, Uart};
9use embassy_stm32::{bind_interrupts, peripherals, usart};
10use static_cell::StaticCell; 8use static_cell::StaticCell;
11use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
12 10
13bind_interrupts!(struct Irqs {
14 UART7 => usart::InterruptHandler<peripherals::UART7>;
15});
16
17#[embassy_executor::task] 11#[embassy_executor::task]
18async fn main_task() { 12async 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;
6use cortex_m_rt::entry; 6use cortex_m_rt::entry;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Executor; 8use embassy_executor::Executor;
9use embassy_stm32::dma::NoDma;
10use embassy_stm32::usart::{Config, Uart}; 9use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart}; 10use embassy_stm32::{bind_interrupts, peripherals, usart};
12use heapless::String; 11use 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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dma::NoDma; 6use embassy_stm32::mode::Async;
7use embassy_stm32::peripherals::{GPDMA1_CH1, UART7}; 7use embassy_stm32::peripherals::UART7;
8use embassy_stm32::usart::{Config, Uart, UartRx}; 8use embassy_stm32::usart::{Config, Uart, UartRx};
9use embassy_stm32::{bind_interrupts, peripherals, usart}; 9use embassy_stm32::{bind_interrupts, peripherals, usart};
10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 10use 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]
19async 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
30static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); 18static 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]
53async fn reader(mut rx: UartRx<'static, UART7, GPDMA1_CH1>) { 41async 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 @@
4use cortex_m_rt::entry; 4use cortex_m_rt::entry;
5use defmt::*; 5use defmt::*;
6use embassy_executor::Executor; 6use embassy_executor::Executor;
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::usart::{Config, Uart}; 7use embassy_stm32::usart::{Config, Uart};
9use embassy_stm32::{bind_interrupts, peripherals, usart};
10use static_cell::StaticCell; 8use static_cell::StaticCell;
11use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
12 10
13bind_interrupts!(struct Irqs {
14 UART7 => usart::InterruptHandler<peripherals::UART7>;
15});
16
17#[embassy_executor::task] 11#[embassy_executor::task]
18async fn main_task() { 12async 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;
6use cortex_m_rt::entry; 6use cortex_m_rt::entry;
7use defmt::*; 7use defmt::*;
8use embassy_executor::Executor; 8use embassy_executor::Executor;
9use embassy_stm32::dma::NoDma;
10use embassy_stm32::usart::{Config, Uart}; 9use embassy_stm32::usart::{Config, Uart};
11use embassy_stm32::{bind_interrupts, peripherals, usart}; 10use embassy_stm32::{bind_interrupts, peripherals, usart};
12use heapless::String; 11use 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
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dma::NoDma; 6use embassy_stm32::mode::Async;
7use embassy_stm32::peripherals::{DMA1_CH1, UART7}; 7use embassy_stm32::peripherals::UART7;
8use embassy_stm32::usart::{Config, Uart, UartRx}; 8use embassy_stm32::usart::{Config, Uart, UartRx};
9use embassy_stm32::{bind_interrupts, peripherals, usart}; 9use embassy_stm32::{bind_interrupts, peripherals, usart};
10use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 10use 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]
19async 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
30static CHANNEL: Channel<ThreadModeRawMutex, [u8; 8], 1> = Channel::new(); 18static 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]
53async fn reader(mut rx: UartRx<'static, UART7, DMA1_CH1>) { 41async 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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::dma::NoDma;
6use embassy_stm32::usart::{Config, Uart}; 5use embassy_stm32::usart::{Config, Uart};
7use embassy_stm32::{bind_interrupts, peripherals, usart}; 6use embassy_stm32::{bind_interrupts, peripherals, usart};
8use {defmt_rtt as _, panic_probe as _}; 7use {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
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::dma::NoDma;
9use embassy_stm32::usart::{Config, Uart}; 8use embassy_stm32::usart::{Config, Uart};
10use embassy_stm32::{bind_interrupts, peripherals, usart}; 9use embassy_stm32::{bind_interrupts, peripherals, usart};
11use heapless::String; 10use 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;
6use common::*; 6use common::*;
7use defmt::{assert, assert_eq, unreachable}; 7use defmt::{assert, assert_eq, unreachable};
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma;
10use embassy_stm32::usart::{Config, ConfigError, Error, Uart}; 9use embassy_stm32::usart::{Config, ConfigError, Error, Uart};
11use embassy_time::{block_for, Duration, Instant}; 10use 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;
8use common::*; 8use common::*;
9use defmt::{assert_eq, panic}; 9use defmt::{assert_eq, panic};
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::mode::Async;
11use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx}; 12use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx};
12use embassy_time::Timer; 13use embassy_time::Timer;
13use rand_chacha::ChaCha8Rng; 14use rand_chacha::ChaCha8Rng;
@@ -51,7 +52,7 @@ async fn main(spawner: Spawner) {
51} 52}
52 53
53#[embassy_executor::task] 54#[embassy_executor::task]
54async fn transmit_task(mut tx: UartTx<'static, peris::UART, peris::UART_TX_DMA>) { 55async 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