>,
detect_previous_overrun: bool,
#[cfg(any(usart_v1, usart_v2))]
buffered_sr: stm32_metapac::usart::regs::Sr,
}
-impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> SetConfig for UartRx<'d, T, M> {
type Config = Config;
type ConfigError = ConfigError;
@@ -296,17 +323,21 @@ impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> {
}
}
-impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
+impl<'d, T: BasicInstance> UartTx<'d, T, Async> {
/// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power.
pub fn new(
peri: impl Peripheral + 'd,
tx: impl Peripheral
> + 'd,
- tx_dma: impl Peripheral
+ 'd,
+ tx_dma: impl Peripheral
> + 'd,
config: Config,
) -> Result {
- T::enable_and_reset();
-
- Self::new_inner(peri, tx, tx_dma, config)
+ Self::new_inner(
+ peri,
+ new_pin!(tx, AFType::OutputPushPull),
+ None,
+ new_dma!(tx_dma),
+ config,
+ )
}
/// 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> {
peri: impl Peripheral + 'd,
tx: impl Peripheral
> + 'd,
cts: impl Peripheral
> + 'd,
- tx_dma: impl Peripheral
+ 'd,
+ tx_dma: impl Peripheral
> + 'd,
config: Config,
) -> Result {
- into_ref!(cts);
-
- T::enable_and_reset();
-
- cts.set_as_af(cts.af_num(), AFType::Input);
- T::regs().cr3().write(|w| {
- w.set_ctse(true);
- });
- Self::new_inner(peri, tx, tx_dma, config)
+ Self::new_inner(
+ peri,
+ new_pin!(tx, AFType::OutputPushPull),
+ new_pin!(cts, AFType::Input),
+ new_dma!(tx_dma),
+ config,
+ )
}
- fn new_inner(
- _peri: impl Peripheral + 'd,
+ /// Initiate an asynchronous UART write
+ pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
+ let ch = self.tx_dma.as_mut().unwrap();
+ T::regs().cr3().modify(|reg| {
+ reg.set_dmat(true);
+ });
+ // If we don't assign future to a variable, the data register pointer
+ // is held across an await and makes the future non-Send.
+ let transfer = unsafe { ch.write(buffer, tdr(T::regs()), Default::default()) };
+ transfer.await;
+ Ok(())
+ }
+}
+
+impl<'d, T: BasicInstance> UartTx<'d, T, Blocking> {
+ /// Create a new blocking tx-only UART with no hardware flow control.
+ ///
+ /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power.
+ pub fn new_blocking(
+ peri: impl Peripheral
+ 'd,
tx: impl Peripheral
> + 'd,
- tx_dma: impl Peripheral
+ 'd,
config: Config,
) -> Result {
- into_ref!(_peri, tx, tx_dma);
+ Self::new_inner(peri, new_pin!(tx, AFType::OutputPushPull), None, None, config)
+ }
+
+ /// Create a new blocking tx-only UART with a clear-to-send pin
+ pub fn new_blocking_with_cts(
+ peri: impl Peripheral + 'd,
+ tx: impl Peripheral
> + 'd,
+ cts: impl Peripheral
> + 'd,
+ config: Config,
+ ) -> Result {
+ Self::new_inner(
+ peri,
+ new_pin!(tx, AFType::OutputPushPull),
+ new_pin!(cts, AFType::Input),
+ None,
+ config,
+ )
+ }
+}
+
+impl<'d, T: BasicInstance, M: Mode> UartTx<'d, T, M> {
+ fn new_inner(
+ _peri: impl Peripheral + 'd,
+ tx: Option>,
+ cts: Option>,
+ tx_dma: Option>,
+ config: Config,
+ ) -> Result {
+ T::enable_and_reset();
let r = T::regs();
-
- tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
-
+ r.cr3().modify(|w| {
+ w.set_ctse(cts.is_some());
+ });
configure(r, &config, T::frequency(), T::KIND, false, true)?;
// create state once!
let _s = T::state();
Ok(Self {
+ tx,
+ cts,
+ de: None,
tx_dma,
- phantom: PhantomData,
+ _phantom: PhantomData,
})
}
@@ -356,23 +433,6 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
reconfigure::(config)
}
- /// Initiate an asynchronous UART write
- pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
- where
- TxDma: crate::usart::TxDma,
- {
- let ch = &mut self.tx_dma;
- let request = ch.request();
- T::regs().cr3().modify(|reg| {
- reg.set_dmat(true);
- });
- // If we don't assign future to a variable, the data register pointer
- // is held across an await and makes the future non-Send.
- let transfer = unsafe { Transfer::new_write(ch, request, buffer, tdr(T::regs()), Default::default()) };
- transfer.await;
- Ok(())
- }
-
/// Perform a blocking UART write
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let r = T::regs();
@@ -391,18 +451,18 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
}
}
-impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
+impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
+ /// Create a new rx-only UART with no hardware flow control.
+ ///
/// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
pub fn new(
peri: impl Peripheral + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
rx: impl Peripheral> + 'd,
- rx_dma: impl Peripheral
+ 'd,
+ rx_dma: impl Peripheral
> + 'd,
config: Config,
) -> Result {
- T::enable_and_reset();
-
- Self::new_inner(peri, rx, rx_dma, config)
+ Self::new_inner(peri, new_pin!(rx, AFType::Input), None, new_dma!(rx_dma), config)
}
/// 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> {
_irq: impl interrupt::typelevel::Binding> + 'd,
rx: impl Peripheral> + 'd,
rts: impl Peripheral
> + 'd,
- rx_dma: impl Peripheral
+ 'd,
+ rx_dma: impl Peripheral
> + 'd,
config: Config,
) -> Result {
- into_ref!(rts);
-
- T::enable_and_reset();
-
- rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
- T::regs().cr3().write(|w| {
- w.set_rtse(true);
- });
-
- Self::new_inner(peri, rx, rx_dma, config)
- }
-
- fn new_inner(
- peri: impl Peripheral + 'd,
- rx: impl Peripheral
> + 'd,
- rx_dma: impl Peripheral
+ 'd,
- config: Config,
- ) -> Result {
- into_ref!(peri, rx, rx_dma);
-
- let r = T::regs();
-
- rx.set_as_af(rx.af_num(), AFType::Input);
-
- configure(r, &config, T::frequency(), T::KIND, true, false)?;
-
- T::Interrupt::unpend();
- unsafe { T::Interrupt::enable() };
-
- // create state once!
- let _s = T::state();
-
- Ok(Self {
- _peri: peri,
- rx_dma,
- detect_previous_overrun: config.detect_previous_overrun,
- #[cfg(any(usart_v1, usart_v2))]
- buffered_sr: stm32_metapac::usart::regs::Sr(0),
- })
- }
-
- /// Reconfigure the driver
- pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
- reconfigure::(config)
- }
-
- #[cfg(any(usart_v1, usart_v2))]
- fn check_rx_flags(&mut self) -> Result {
- let r = T::regs();
- loop {
- // Handle all buffered error flags.
- if self.buffered_sr.pe() {
- self.buffered_sr.set_pe(false);
- return Err(Error::Parity);
- } else if self.buffered_sr.fe() {
- self.buffered_sr.set_fe(false);
- return Err(Error::Framing);
- } else if self.buffered_sr.ne() {
- self.buffered_sr.set_ne(false);
- return Err(Error::Noise);
- } else if self.buffered_sr.ore() {
- self.buffered_sr.set_ore(false);
- return Err(Error::Overrun);
- } else if self.buffered_sr.rxne() {
- self.buffered_sr.set_rxne(false);
- return Ok(true);
- } else {
- // No error flags from previous iterations were set: Check the actual status register
- let sr = r.sr().read();
- if !sr.rxne() {
- return Ok(false);
- }
-
- // Buffer the status register and let the loop handle the error flags.
- self.buffered_sr = sr;
- }
- }
- }
-
- #[cfg(any(usart_v3, usart_v4))]
- fn check_rx_flags(&mut self) -> Result {
- let r = T::regs();
- let sr = r.isr().read();
- if sr.pe() {
- r.icr().write(|w| w.set_pe(true));
- return Err(Error::Parity);
- } else if sr.fe() {
- r.icr().write(|w| w.set_fe(true));
- return Err(Error::Framing);
- } else if sr.ne() {
- r.icr().write(|w| w.set_ne(true));
- return Err(Error::Noise);
- } else if sr.ore() {
- r.icr().write(|w| w.set_ore(true));
- return Err(Error::Overrun);
- }
- Ok(sr.rxne())
+ Self::new_inner(
+ peri,
+ new_pin!(rx, AFType::Input),
+ new_pin!(rts, AFType::OutputPushPull),
+ new_dma!(rx_dma),
+ config,
+ )
}
/// Initiate an asynchronous UART read
- pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
- where
- RxDma: crate::usart::RxDma,
- {
+ pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
self.inner_read(buffer, false).await?;
Ok(())
}
- /// Read a single u8 if there is one available, otherwise return WouldBlock
- pub fn nb_read(&mut self) -> Result> {
- let r = T::regs();
- if self.check_rx_flags()? {
- Ok(unsafe { rdr(r).read_volatile() })
- } else {
- Err(nb::Error::WouldBlock)
- }
- }
-
- /// Perform a blocking read into `buffer`
- pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
- let r = T::regs();
- for b in buffer {
- while !self.check_rx_flags()? {}
- unsafe { *b = rdr(r).read_volatile() }
- }
- Ok(())
- }
-
/// Initiate an asynchronous read with idle line detection enabled
- pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result
- where
- RxDma: crate::usart::RxDma,
- {
+ pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
self.inner_read(buffer, true).await
}
@@ -555,10 +499,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
&mut self,
buffer: &mut [u8],
enable_idle_line_detection: bool,
- ) -> Result
- where
- RxDma: crate::usart::RxDma,
- {
+ ) -> Result {
let r = T::regs();
// 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> {
});
});
- let ch = &mut self.rx_dma;
- let request = ch.request();
+ let ch = self.rx_dma.as_mut().unwrap();
let buffer_len = buffer.len();
// Start USART DMA
// will not do anything yet because DMAR is not yet set
// future which will complete when DMA Read request completes
- let transfer = unsafe { Transfer::new_read(ch, request, rdr(T::regs()), buffer, Default::default()) };
+ let transfer = unsafe { ch.read(rdr(T::regs()), buffer, Default::default()) };
// clear ORE flag just before enabling DMA Rx Request: can be mandatory for the second transfer
if !self.detect_previous_overrun {
@@ -732,10 +672,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
r
}
- async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result
- where
- RxDma: crate::usart::RxDma,
- {
+ async fn inner_read(&mut self, buffer: &mut [u8], enable_idle_line_detection: bool) -> Result {
if buffer.is_empty() {
return Ok(0);
} else if buffer.len() > 0xFFFF {
@@ -755,34 +692,186 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
}
}
-impl<'d, T: BasicInstance, TxDma> Drop for UartTx<'d, T, TxDma> {
+impl<'d, T: BasicInstance> UartRx<'d, T, Blocking> {
+ /// Create a new rx-only UART with no hardware flow control.
+ ///
+ /// Useful if you only want Uart Rx. It saves 1 pin and consumes a little less power.
+ pub fn new_blocking(
+ peri: impl Peripheral + 'd,
+ rx: impl Peripheral
> + 'd,
+ config: Config,
+ ) -> Result {
+ Self::new_inner(peri, new_pin!(rx, AFType::Input), None, None, config)
+ }
+
+ /// Create a new rx-only UART with a request-to-send pin
+ pub fn new_blocking_with_rts(
+ peri: impl Peripheral + 'd,
+ rx: impl Peripheral
> + 'd,
+ rts: impl Peripheral
> + 'd,
+ config: Config,
+ ) -> Result {
+ Self::new_inner(
+ peri,
+ new_pin!(rx, AFType::Input),
+ new_pin!(rts, AFType::OutputPushPull),
+ None,
+ config,
+ )
+ }
+}
+
+impl<'d, T: BasicInstance, M: Mode> UartRx<'d, T, M> {
+ fn new_inner(
+ _peri: impl Peripheral + 'd,
+ rx: Option>,
+ rts: Option>,
+ rx_dma: Option>,
+ config: Config,
+ ) -> Result {
+ T::enable_and_reset();
+
+ let r = T::regs();
+ r.cr3().write(|w| {
+ w.set_rtse(rts.is_some());
+ });
+ configure(r, &config, T::frequency(), T::KIND, true, false)?;
+
+ T::Interrupt::unpend();
+ unsafe { T::Interrupt::enable() };
+
+ // create state once!
+ let _s = T::state();
+
+ Ok(Self {
+ _phantom: PhantomData,
+ rx,
+ rts,
+ rx_dma,
+ detect_previous_overrun: config.detect_previous_overrun,
+ #[cfg(any(usart_v1, usart_v2))]
+ buffered_sr: stm32_metapac::usart::regs::Sr(0),
+ })
+ }
+
+ /// Reconfigure the driver
+ pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
+ reconfigure::(config)
+ }
+
+ #[cfg(any(usart_v1, usart_v2))]
+ fn check_rx_flags(&mut self) -> Result {
+ let r = T::regs();
+ loop {
+ // Handle all buffered error flags.
+ if self.buffered_sr.pe() {
+ self.buffered_sr.set_pe(false);
+ return Err(Error::Parity);
+ } else if self.buffered_sr.fe() {
+ self.buffered_sr.set_fe(false);
+ return Err(Error::Framing);
+ } else if self.buffered_sr.ne() {
+ self.buffered_sr.set_ne(false);
+ return Err(Error::Noise);
+ } else if self.buffered_sr.ore() {
+ self.buffered_sr.set_ore(false);
+ return Err(Error::Overrun);
+ } else if self.buffered_sr.rxne() {
+ self.buffered_sr.set_rxne(false);
+ return Ok(true);
+ } else {
+ // No error flags from previous iterations were set: Check the actual status register
+ let sr = r.sr().read();
+ if !sr.rxne() {
+ return Ok(false);
+ }
+
+ // Buffer the status register and let the loop handle the error flags.
+ self.buffered_sr = sr;
+ }
+ }
+ }
+
+ #[cfg(any(usart_v3, usart_v4))]
+ fn check_rx_flags(&mut self) -> Result {
+ let r = T::regs();
+ let sr = r.isr().read();
+ if sr.pe() {
+ r.icr().write(|w| w.set_pe(true));
+ return Err(Error::Parity);
+ } else if sr.fe() {
+ r.icr().write(|w| w.set_fe(true));
+ return Err(Error::Framing);
+ } else if sr.ne() {
+ r.icr().write(|w| w.set_ne(true));
+ return Err(Error::Noise);
+ } else if sr.ore() {
+ r.icr().write(|w| w.set_ore(true));
+ return Err(Error::Overrun);
+ }
+ Ok(sr.rxne())
+ }
+
+ /// Read a single u8 if there is one available, otherwise return WouldBlock
+ pub(crate) fn nb_read(&mut self) -> Result> {
+ let r = T::regs();
+ if self.check_rx_flags()? {
+ Ok(unsafe { rdr(r).read_volatile() })
+ } else {
+ Err(nb::Error::WouldBlock)
+ }
+ }
+
+ /// Perform a blocking read into `buffer`
+ pub fn blocking_read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
+ let r = T::regs();
+ for b in buffer {
+ while !self.check_rx_flags()? {}
+ unsafe { *b = rdr(r).read_volatile() }
+ }
+ Ok(())
+ }
+}
+
+impl<'d, T: BasicInstance, M: Mode> Drop for UartTx<'d, T, M> {
fn drop(&mut self) {
+ self.tx.as_ref().map(|x| x.set_as_disconnected());
+ self.cts.as_ref().map(|x| x.set_as_disconnected());
+ self.de.as_ref().map(|x| x.set_as_disconnected());
T::disable();
}
}
-impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
+impl<'d, T: BasicInstance, M: Mode> Drop for UartRx<'d, T, M> {
fn drop(&mut self) {
+ self.rx.as_ref().map(|x| x.set_as_disconnected());
+ self.rts.as_ref().map(|x| x.set_as_disconnected());
T::disable();
}
}
-impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
+impl<'d, T: BasicInstance> Uart<'d, T, Async> {
/// Create a new bidirectional UART
pub fn new(
peri: impl Peripheral + 'd,
rx: impl Peripheral
> + 'd,
tx: impl Peripheral
> + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
- tx_dma: impl Peripheral + 'd,
- rx_dma: impl Peripheral
+ 'd,
+ tx_dma: impl Peripheral
> + 'd,
+ rx_dma: impl Peripheral
> + 'd,
config: Config,
) -> Result {
- // UartRx and UartTx have one refcount ea.
- T::enable_and_reset();
- T::enable_and_reset();
-
- Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config)
+ Self::new_inner(
+ peri,
+ new_pin!(rx, config.rx_af()),
+ new_pin!(tx, config.tx_af()),
+ None,
+ None,
+ None,
+ new_dma!(tx_dma),
+ new_dma!(rx_dma),
+ config,
+ )
}
/// 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> {
_irq: impl interrupt::typelevel::Binding> + 'd,
rts: impl Peripheral> + 'd,
cts: impl Peripheral
> + 'd,
- tx_dma: impl Peripheral
+ 'd,
- rx_dma: impl Peripheral
+ 'd,
+ tx_dma: impl Peripheral
> + 'd,
+ rx_dma: impl Peripheral
> + 'd,
config: Config,
) -> Result {
- into_ref!(cts, rts);
-
- // UartRx and UartTx have one refcount ea.
- T::enable_and_reset();
- T::enable_and_reset();
-
- rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
- cts.set_as_af(cts.af_num(), AFType::Input);
- T::regs().cr3().write(|w| {
- w.set_rtse(true);
- w.set_ctse(true);
- });
- Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config)
+ Self::new_inner(
+ peri,
+ new_pin!(rx, config.rx_af()),
+ new_pin!(tx, config.tx_af()),
+ new_pin!(rts, AFType::OutputPushPull),
+ new_pin!(cts, AFType::Input),
+ None,
+ new_dma!(tx_dma),
+ new_dma!(rx_dma),
+ config,
+ )
}
#[cfg(not(any(usart_v1, usart_v2)))]
@@ -820,21 +907,21 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
tx: impl Peripheral> + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
de: impl Peripheral> + 'd,
- tx_dma: impl Peripheral
+ 'd,
- rx_dma: impl Peripheral
+ 'd,
+ tx_dma: impl Peripheral
> + 'd,
+ rx_dma: impl Peripheral
> + 'd,
config: Config,
) -> Result {
- into_ref!(de);
-
- // UartRx and UartTx have one refcount ea.
- T::enable_and_reset();
- T::enable_and_reset();
-
- de.set_as_af(de.af_num(), AFType::OutputPushPull);
- T::regs().cr3().write(|w| {
- w.set_dem(true);
- });
- Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config)
+ Self::new_inner(
+ peri,
+ new_pin!(rx, config.rx_af()),
+ new_pin!(tx, config.tx_af()),
+ None,
+ None,
+ new_pin!(de, AFType::OutputPushPull),
+ new_dma!(tx_dma),
+ new_dma!(rx_dma),
+ config,
+ )
}
/// 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> {
peri: impl Peripheral + 'd,
tx: impl Peripheral
> + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
- tx_dma: impl Peripheral + 'd,
- rx_dma: impl Peripheral
+ 'd,
+ tx_dma: impl Peripheral
> + 'd,
+ rx_dma: impl Peripheral
> + 'd,
mut config: Config,
) -> Result {
- // UartRx and UartTx have one refcount ea.
- T::enable_and_reset();
- T::enable_and_reset();
-
config.swap_rx_tx = false;
+ config.half_duplex = true;
- into_ref!(peri, tx, tx_dma, rx_dma);
-
- T::regs().cr3().write(|w| w.set_hdsel(true));
- tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
-
- Self::new_inner(peri, tx_dma, rx_dma, config)
+ Self::new_inner(
+ peri,
+ None,
+ new_pin!(tx, AFType::OutputPushPull),
+ None,
+ None,
+ None,
+ new_dma!(tx_dma),
+ new_dma!(rx_dma),
+ config,
+ )
}
/// 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> {
peri: impl Peripheral + 'd,
rx: impl Peripheral
> + 'd,
_irq: impl interrupt::typelevel::Binding> + 'd,
- tx_dma: impl Peripheral + 'd,
- rx_dma: impl Peripheral
+ 'd,
+ tx_dma: impl Peripheral
> + 'd,
+ rx_dma: impl Peripheral
> + 'd,
mut config: Config,
) -> Result {
- // UartRx and UartTx have one refcount ea.
- T::enable_and_reset();
- T::enable_and_reset();
-
config.swap_rx_tx = true;
+ config.half_duplex = true;
- into_ref!(peri, rx, tx_dma, rx_dma);
-
- T::regs().cr3().write(|w| w.set_hdsel(true));
- rx.set_as_af(rx.af_num(), AFType::OutputPushPull);
-
- Self::new_inner(peri, tx_dma, rx_dma, config)
+ Self::new_inner(
+ peri,
+ None,
+ None,
+ new_pin!(rx, AFType::OutputPushPull),
+ None,
+ None,
+ new_dma!(tx_dma),
+ new_dma!(rx_dma),
+ config,
+ )
}
- fn new_inner_configure(
+ /// Perform an asynchronous write
+ pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
+ self.tx.write(buffer).await
+ }
+
+ /// Perform an asynchronous read into `buffer`
+ pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
+ self.rx.read(buffer).await
+ }
+
+ /// Perform an an asynchronous read with idle line detection enabled
+ pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result {
+ self.rx.read_until_idle(buffer).await
+ }
+}
+
+impl<'d, T: BasicInstance> Uart<'d, T, Blocking> {
+ /// Create a new blocking bidirectional UART.
+ pub fn new_blocking(
peri: impl Peripheral + 'd,
rx: impl Peripheral
> + 'd,
tx: impl Peripheral
> + 'd,
- tx_dma: impl Peripheral
+ 'd,
- rx_dma: impl Peripheral
+ 'd,
config: Config,
) -> Result {
- into_ref!(peri, rx, tx, tx_dma, rx_dma);
-
- // Some chips do not have swap_rx_tx bit
- cfg_if::cfg_if! {
- if #[cfg(any(usart_v3, usart_v4))] {
- if config.swap_rx_tx {
- let (rx, tx) = (tx, rx);
- rx.set_as_af(rx.af_num(), AFType::Input);
- tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
- } else {
- rx.set_as_af(rx.af_num(), AFType::Input);
- tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
- }
- } else {
- rx.set_as_af(rx.af_num(), AFType::Input);
- tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
- }
- }
-
- Self::new_inner(peri, tx_dma, rx_dma, config)
+ Self::new_inner(
+ peri,
+ new_pin!(rx, config.rx_af()),
+ new_pin!(tx, config.tx_af()),
+ None,
+ None,
+ None,
+ None,
+ None,
+ config,
+ )
}
- fn new_inner(
- peri: PeripheralRef<'d, T>,
- tx_dma: PeripheralRef<'d, TxDma>,
- rx_dma: PeripheralRef<'d, RxDma>,
+ /// Create a new bidirectional UART with request-to-send and clear-to-send pins
+ pub fn new_blocking_with_rtscts(
+ peri: impl Peripheral + 'd,
+ rx: impl Peripheral
> + 'd,
+ tx: impl Peripheral
> + 'd,
+ rts: impl Peripheral
> + 'd,
+ cts: impl Peripheral
> + 'd,
config: Config,
) -> Result {
+ Self::new_inner(
+ peri,
+ new_pin!(rx, config.rx_af()),
+ new_pin!(tx, config.tx_af()),
+ new_pin!(rts, AFType::OutputPushPull),
+ new_pin!(cts, AFType::Input),
+ None,
+ None,
+ None,
+ config,
+ )
+ }
+
+ #[cfg(not(any(usart_v1, usart_v2)))]
+ /// Create a new bidirectional UART with a driver-enable pin
+ pub fn new_blocking_with_de(
+ peri: impl Peripheral + 'd,
+ rx: impl Peripheral
> + 'd,
+ tx: impl Peripheral
> + 'd,
+ de: impl Peripheral
> + 'd,
+ config: Config,
+ ) -> Result {
+ Self::new_inner(
+ peri,
+ new_pin!(rx, config.rx_af()),
+ new_pin!(tx, config.tx_af()),
+ None,
+ None,
+ new_pin!(de, AFType::OutputPushPull),
+ None,
+ None,
+ config,
+ )
+ }
+
+ /// Create a single-wire half-duplex Uart transceiver on a single Tx pin.
+ ///
+ /// See [`new_half_duplex_on_rx`][`Self::new_half_duplex_on_rx`] if you would prefer to use an Rx pin.
+ /// There is no functional difference between these methods, as both allow bidirectional communication.
+ ///
+ /// The pin is always released when no data is transmitted. Thus, it acts as a standard
+ /// I/O in idle or in reception.
+ /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
+ /// on the line must be managed by software (for instance by using a centralized arbiter).
+ #[cfg(not(any(usart_v1, usart_v2)))]
+ #[doc(alias("HDSEL"))]
+ pub fn new_blocking_half_duplex(
+ peri: impl Peripheral + 'd,
+ tx: impl Peripheral
> + 'd,
+ mut config: Config,
+ ) -> Result {
+ config.swap_rx_tx = false;
+ config.half_duplex = true;
+
+ Self::new_inner(
+ peri,
+ None,
+ new_pin!(tx, AFType::OutputPushPull),
+ None,
+ None,
+ None,
+ None,
+ None,
+ config,
+ )
+ }
+
+ /// Create a single-wire half-duplex Uart transceiver on a single Rx pin.
+ ///
+ /// See [`new_half_duplex`][`Self::new_half_duplex`] if you would prefer to use an Tx pin.
+ /// There is no functional difference between these methods, as both allow bidirectional communication.
+ ///
+ /// The pin is always released when no data is transmitted. Thus, it acts as a standard
+ /// I/O in idle or in reception.
+ /// Apart from this, the communication protocol is similar to normal USART mode. Any conflict
+ /// on the line must be managed by software (for instance by using a centralized arbiter).
+ #[cfg(not(any(usart_v1, usart_v2)))]
+ #[doc(alias("HDSEL"))]
+ pub fn new_blocking_half_duplex_on_rx(
+ peri: impl Peripheral + 'd,
+ rx: impl Peripheral
> + 'd,
+ mut config: Config,
+ ) -> Result {
+ config.swap_rx_tx = true;
+ config.half_duplex = true;
+
+ Self::new_inner(
+ peri,
+ None,
+ None,
+ new_pin!(rx, AFType::OutputPushPull),
+ None,
+ None,
+ None,
+ None,
+ config,
+ )
+ }
+}
+
+impl<'d, T: BasicInstance, M: Mode> Uart<'d, T, M> {
+ fn new_inner(
+ _peri: impl Peripheral + 'd,
+ rx: Option>,
+ tx: Option>,
+ rts: Option>,
+ cts: Option>,
+ de: Option>,
+ tx_dma: Option>,
+ rx_dma: Option>,
+ config: Config,
+ ) -> Result {
+ // UartRx and UartTx have one refcount each.
+ T::enable_and_reset();
+ T::enable_and_reset();
+
let r = T::regs();
+ r.cr3().write(|w| {
+ w.set_rtse(rts.is_some());
+ w.set_ctse(cts.is_some());
+ #[cfg(not(any(usart_v1, usart_v2)))]
+ w.set_dem(de.is_some());
+ });
configure(r, &config, T::frequency(), T::KIND, true, true)?;
T::Interrupt::unpend();
@@ -951,11 +1174,16 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
Ok(Self {
tx: UartTx {
+ _phantom: PhantomData,
+ tx,
+ cts,
+ de,
tx_dma,
- phantom: PhantomData,
},
rx: UartRx {
- _peri: peri,
+ _phantom: PhantomData,
+ rx,
+ rts,
rx_dma,
detect_previous_overrun: config.detect_previous_overrun,
#[cfg(any(usart_v1, usart_v2))]
@@ -964,14 +1192,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
})
}
- /// Initiate an asynchronous write
- pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
- where
- TxDma: crate::usart::TxDma,
- {
- self.tx.write(buffer).await
- }
-
/// Perform a blocking write
pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> {
self.tx.blocking_write(buffer)
@@ -982,16 +1202,8 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
self.tx.blocking_flush()
}
- /// Initiate an asynchronous read into `buffer`
- pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error>
- where
- RxDma: crate::usart::RxDma,
- {
- self.rx.read(buffer).await
- }
-
/// Read a single `u8` or return `WouldBlock`
- pub fn nb_read(&mut self) -> Result> {
+ pub(crate) fn nb_read(&mut self) -> Result> {
self.rx.nb_read()
}
@@ -1000,18 +1212,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
self.rx.blocking_read(buffer)
}
- /// Initiate an an asynchronous read with idle line detection enabled
- pub async fn read_until_idle(&mut self, buffer: &mut [u8]) -> Result
- where
- RxDma: crate::usart::RxDma,
- {
- self.rx.read_until_idle(buffer).await
- }
-
/// Split the Uart into a transmitter and receiver, which is
/// particularly useful when having two tasks correlating to
/// transmitting and receiving.
- pub fn split(self) -> (UartTx<'d, T, TxDma>, UartRx<'d, T, RxDma>) {
+ pub fn split(self) -> (UartTx<'d, T, M>, UartRx<'d, T, M>) {
(self.tx, self.rx)
}
}
@@ -1153,6 +1357,8 @@ fn configure(
#[cfg(not(usart_v1))]
r.cr3().modify(|w| {
w.set_onebit(config.assume_noise_free);
+ #[cfg(any(usart_v3, usart_v4))]
+ w.set_hdsel(config.half_duplex);
});
r.cr1().write(|w| {
@@ -1185,14 +1391,14 @@ fn configure(
Ok(())
}
-impl<'d, T: BasicInstance, RxDma> embedded_hal_02::serial::Read for UartRx<'d, T, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read for UartRx<'d, T, M> {
type Error = Error;
fn read(&mut self) -> Result> {
self.nb_read()
}
}
-impl<'d, T: BasicInstance, TxDma> embedded_hal_02::blocking::serial::Write for UartTx<'d, T, TxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write for UartTx<'d, T, M> {
type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
@@ -1202,14 +1408,14 @@ impl<'d, T: BasicInstance, TxDma> embedded_hal_02::blocking::serial::Write f
}
}
-impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::serial::Read for Uart<'d, T, TxDma, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::serial::Read for Uart<'d, T, M> {
type Error = Error;
fn read(&mut self) -> Result> {
self.nb_read()
}
}
-impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_02::blocking::serial::Write for Uart<'d, T, TxDma, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_02::blocking::serial::Write for Uart<'d, T, M> {
type Error = Error;
fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
self.blocking_write(buffer)
@@ -1231,25 +1437,25 @@ impl embedded_hal_nb::serial::Error for Error {
}
}
-impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::ErrorType for Uart<'d, T, TxDma, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for Uart<'d, T, M> {
type Error = Error;
}
-impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, TxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartTx<'d, T, M> {
type Error = Error;
}
-impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::ErrorType for UartRx<'d, T, M> {
type Error = Error;
}
-impl<'d, T: BasicInstance, RxDma> embedded_hal_nb::serial::Read for UartRx<'d, T, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for UartRx<'d, T, M> {
fn read(&mut self) -> nb::Result {
self.nb_read()
}
}
-impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::Write for UartTx<'d, T, TxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for UartTx<'d, T, M> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map_err(nb::Error::Other)
}
@@ -1259,13 +1465,13 @@ impl<'d, T: BasicInstance, TxDma> embedded_hal_nb::serial::Write for UartTx<'d,
}
}
-impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Read for Uart<'d, T, TxDma, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Read for Uart<'d, T, M> {
fn read(&mut self) -> Result> {
self.nb_read()
}
}
-impl<'d, T: BasicInstance, TxDma, RxDma> embedded_hal_nb::serial::Write for Uart<'d, T, TxDma, RxDma> {
+impl<'d, T: BasicInstance, M: Mode> embedded_hal_nb::serial::Write for Uart<'d, T, M> {
fn write(&mut self, char: u8) -> nb::Result<(), Self::Error> {
self.blocking_write(&[char]).map_err(nb::Error::Other)
}
@@ -1281,21 +1487,21 @@ impl embedded_io::Error for Error {
}
}
-impl embedded_io::ErrorType for Uart<'_, T, TxDma, RxDma>
+impl embedded_io::ErrorType for Uart<'_, T, M>
where
T: BasicInstance,
{
type Error = Error;
}
-impl embedded_io::ErrorType for UartTx<'_, T, TxDma>
+impl embedded_io::ErrorType for UartTx<'_, T, M>
where
T: BasicInstance,
{
type Error = Error;
}
-impl embedded_io::Write for Uart<'_, T, TxDma, RxDma>
+impl embedded_io::Write for Uart<'_, T, M>
where
T: BasicInstance,
{
@@ -1309,7 +1515,7 @@ where
}
}
-impl embedded_io::Write for UartTx<'_, T, TxDma>
+impl embedded_io::Write for UartTx<'_, T, M>
where
T: BasicInstance,
{
@@ -1323,10 +1529,9 @@ where
}
}
-impl embedded_io_async::Write for Uart<'_, T, TxDma, RxDma>
+impl embedded_io_async::Write for Uart<'_, T, Async>
where
T: BasicInstance,
- TxDma: self::TxDma,
{
async fn write(&mut self, buf: &[u8]) -> Result {
self.write(buf).await?;
@@ -1338,10 +1543,9 @@ where
}
}
-impl embedded_io_async::Write for UartTx<'_, T, TxDma>
+impl embedded_io_async::Write for UartTx<'_, T, Async>
where
T: BasicInstance,
- TxDma: self::TxDma,
{
async fn write(&mut self, buf: &[u8]) -> Result {
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 @@
use core::future::poll_fn;
+use core::marker::PhantomData;
use core::mem;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_embedded_hal::SetConfig;
-use embassy_hal_internal::PeripheralRef;
use futures::future::{select, Either};
use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx};
use crate::dma::ReadableRingBuffer;
+use crate::mode::Async;
use crate::usart::{Regs, Sr};
/// Rx-only Ring-buffered UART Driver
///
/// Created with [UartRx::into_ring_buffered]
pub struct RingBufferedUartRx<'d, T: BasicInstance> {
- _peri: PeripheralRef<'d, T>,
+ _phantom: PhantomData,
ring_buf: ReadableRingBuffer<'d, u8>,
}
@@ -28,26 +29,29 @@ impl<'d, T: BasicInstance> SetConfig for RingBufferedUartRx<'d, T> {
}
}
-impl<'d, T: BasicInstance, RxDma: super::RxDma> UartRx<'d, T, RxDma> {
+impl<'d, T: BasicInstance> UartRx<'d, T, Async> {
/// Turn the `UartRx` into a buffered uart which can continously receive in the background
/// without the possibility of losing bytes. The `dma_buf` is a buffer registered to the
/// DMA controller, and must be large enough to prevent overflows.
- pub fn into_ring_buffered(self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T> {
+ pub fn into_ring_buffered(mut self, dma_buf: &'d mut [u8]) -> RingBufferedUartRx<'d, T> {
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
- let request = self.rx_dma.request();
let opts = Default::default();
// Safety: we forget the struct before this function returns.
- let rx_dma = unsafe { self.rx_dma.clone_unchecked() };
- let _peri = unsafe { self._peri.clone_unchecked() };
+ let rx_dma = self.rx_dma.as_mut().unwrap();
+ let request = rx_dma.request;
+ let rx_dma = unsafe { rx_dma.channel.clone_unchecked() };
let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(T::regs()), dma_buf, opts) };
// Don't disable the clock
mem::forget(self);
- RingBufferedUartRx { _peri, ring_buf }
+ RingBufferedUartRx {
+ _phantom: PhantomData,
+ ring_buf,
+ }
}
}
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;
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use heapless::String;
@@ -21,7 +20,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let config = Config::default();
- let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, Irqs, p.DMA1_CH4, NoDma, config).unwrap();
+ let mut usart = Uart::new(p.USART1, p.PE1, p.PE0, Irqs, p.DMA1_CH4, p.DMA1_CH5, config).unwrap();
for n in 0u32.. {
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 @@
use cortex_m_rt::entry;
use defmt::*;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use {defmt_rtt as _, panic_probe as _};
@@ -19,7 +18,7 @@ fn main() -> ! {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
- let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, NoDma, NoDma, config).unwrap();
+ let mut usart = Uart::new_blocking(p.USART3, p.PD9, p.PD8, config).unwrap();
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
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;
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use heapless::String;
@@ -21,7 +20,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let config = Config::default();
- let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, p.DMA1_CH3, NoDma, config).unwrap();
+ let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, Irqs, p.DMA1_CH3, p.DMA1_CH1, config).unwrap();
for n in 0u32.. {
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;
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use heapless::String;
@@ -19,7 +18,7 @@ bind_interrupts!(struct Irqs {
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
- let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, Irqs, p.DMA1_CH1, NoDma, config).unwrap();
+ let mut usart = Uart::new(p.UART7, p.PA8, p.PA15, Irqs, p.DMA1_CH1, p.DMA1_CH3, config).unwrap();
for n in 0u32.. {
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 @@
use cortex_m_rt::entry;
use defmt::*;
use embassy_executor::Executor;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
-use embassy_stm32::{bind_interrupts, peripherals, usart};
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};
-bind_interrupts!(struct Irqs {
- UART7 => usart::InterruptHandler;
-});
-
#[embassy_executor::task]
async fn main_task() {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
- let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config).unwrap();
+ let mut usart = Uart::new_blocking(p.UART7, p.PF6, p.PF7, config).unwrap();
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
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;
use cortex_m_rt::entry;
use defmt::*;
use embassy_executor::Executor;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use heapless::String;
@@ -22,7 +21,7 @@ async fn main_task() {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
- let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, NoDma, config).unwrap();
+ let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.GPDMA1_CH0, p.GPDMA1_CH1, config).unwrap();
for n in 0u32.. {
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 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma::NoDma;
-use embassy_stm32::peripherals::{GPDMA1_CH1, UART7};
+use embassy_stm32::mode::Async;
+use embassy_stm32::peripherals::UART7;
use embassy_stm32::usart::{Config, Uart, UartRx};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
@@ -15,18 +15,6 @@ bind_interrupts!(struct Irqs {
UART7 => usart::InterruptHandler;
});
-#[embassy_executor::task]
-async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
- unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
- info!("wrote Hello, starting echo");
-
- let mut buf = [0u8; 1];
- loop {
- unwrap!(usart.blocking_read(&mut buf));
- unwrap!(usart.blocking_write(&buf));
- }
-}
-
static CHANNEL: Channel = Channel::new();
#[embassy_executor::main]
@@ -50,7 +38,7 @@ async fn main(spawner: Spawner) -> ! {
}
#[embassy_executor::task]
-async fn reader(mut rx: UartRx<'static, UART7, GPDMA1_CH1>) {
+async fn reader(mut rx: UartRx<'static, UART7, Async>) {
let mut buf = [0; 8];
loop {
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 @@
use cortex_m_rt::entry;
use defmt::*;
use embassy_executor::Executor;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
-use embassy_stm32::{bind_interrupts, peripherals, usart};
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};
-bind_interrupts!(struct Irqs {
- UART7 => usart::InterruptHandler;
-});
-
#[embassy_executor::task]
async fn main_task() {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
- let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, NoDma, NoDma, config).unwrap();
+ let mut usart = Uart::new_blocking(p.UART7, p.PF6, p.PF7, config).unwrap();
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
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;
use cortex_m_rt::entry;
use defmt::*;
use embassy_executor::Executor;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use heapless::String;
@@ -22,7 +21,7 @@ async fn main_task() {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
- let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, NoDma, config).unwrap();
+ let mut usart = Uart::new(p.UART7, p.PF6, p.PF7, Irqs, p.DMA1_CH0, p.DMA1_CH1, config).unwrap();
for n in 0u32.. {
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 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma::NoDma;
-use embassy_stm32::peripherals::{DMA1_CH1, UART7};
+use embassy_stm32::mode::Async;
+use embassy_stm32::peripherals::UART7;
use embassy_stm32::usart::{Config, Uart, UartRx};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
@@ -15,18 +15,6 @@ bind_interrupts!(struct Irqs {
UART7 => usart::InterruptHandler;
});
-#[embassy_executor::task]
-async fn writer(mut usart: Uart<'static, UART7, NoDma, NoDma>) {
- unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
- info!("wrote Hello, starting echo");
-
- let mut buf = [0u8; 1];
- loop {
- unwrap!(usart.blocking_read(&mut buf));
- unwrap!(usart.blocking_write(&buf));
- }
-}
-
static CHANNEL: Channel = Channel::new();
#[embassy_executor::main]
@@ -50,7 +38,7 @@ async fn main(spawner: Spawner) -> ! {
}
#[embassy_executor::task]
-async fn reader(mut rx: UartRx<'static, UART7, DMA1_CH1>) {
+async fn reader(mut rx: UartRx<'static, UART7, Async>) {
let mut buf = [0; 8];
loop {
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 @@
#![no_main]
use defmt::*;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use {defmt_rtt as _, panic_probe as _};
@@ -18,7 +17,7 @@ fn main() -> ! {
let p = embassy_stm32::init(Default::default());
let config = Config::default();
- let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, NoDma, NoDma, config).unwrap();
+ let mut usart = Uart::new_blocking(p.UART4, p.PA1, p.PA0, config).unwrap();
unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n"));
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;
use defmt::*;
use embassy_executor::Spawner;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, Uart};
use embassy_stm32::{bind_interrupts, peripherals, usart};
use heapless::String;
@@ -21,7 +20,7 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
let config = Config::default();
- let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, NoDma, config).unwrap();
+ let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, p.DMA1_CH4, config).unwrap();
for n in 0u32.. {
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;
use common::*;
use defmt::{assert, assert_eq, unreachable};
use embassy_executor::Spawner;
-use embassy_stm32::dma::NoDma;
use embassy_stm32::usart::{Config, ConfigError, Error, Uart};
use embassy_time::{block_for, Duration, Instant};
@@ -20,11 +19,10 @@ async fn main(_spawner: Spawner) {
let mut usart = peri!(p, UART);
let mut rx = peri!(p, UART_RX);
let mut tx = peri!(p, UART_TX);
- let irq = irqs!(UART);
{
let config = Config::default();
- let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, irq, NoDma, NoDma, config).unwrap();
+ let mut usart = Uart::new_blocking(&mut usart, &mut rx, &mut tx, config).unwrap();
// We can't send too many bytes, they have to fit in the FIFO.
// This is because we aren't sending+receiving at the same time.
@@ -40,7 +38,7 @@ async fn main(_spawner: Spawner) {
// Test error handling with with an overflow error
{
let config = Config::default();
- let mut usart = Uart::new(&mut usart, &mut rx, &mut tx, irq, NoDma, NoDma, config).unwrap();
+ let mut usart = Uart::new_blocking(&mut usart, &mut rx, &mut tx, config).unwrap();
// Send enough bytes to fill the RX FIFOs off all USART versions.
let data = [0; 64];
@@ -70,7 +68,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
config.baudrate = baudrate;
- let mut usart = match Uart::new(&mut usart, &mut rx, &mut tx, irq, NoDma, NoDma, config) {
+ let mut usart = match Uart::new_blocking(&mut usart, &mut rx, &mut tx, config) {
Ok(x) => x,
Err(ConfigError::BaudrateTooHigh) => {
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;
use common::*;
use defmt::{assert_eq, panic};
use embassy_executor::Spawner;
+use embassy_stm32::mode::Async;
use embassy_stm32::usart::{Config, DataBits, Parity, RingBufferedUartRx, StopBits, Uart, UartTx};
use embassy_time::Timer;
use rand_chacha::ChaCha8Rng;
@@ -51,7 +52,7 @@ async fn main(spawner: Spawner) {
}
#[embassy_executor::task]
-async fn transmit_task(mut tx: UartTx<'static, peris::UART, peris::UART_TX_DMA>) {
+async fn transmit_task(mut tx: UartTx<'static, peris::UART, Async>) {
// workaround https://github.com/embassy-rs/embassy/issues/1426
Timer::after_millis(100).await;