{
#[allow(clippy::if_same_then_else)]
if register < Self::BACKUP_REGISTER_COUNT {
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 8a0c85d2c..ea727b010 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -743,7 +743,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
T::enable_and_reset();
T::enable_and_reset();
- Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
+ Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config)
}
/// Create a new bidirectional UART with request-to-send and clear-to-send pins
@@ -770,7 +770,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
w.set_rtse(true);
w.set_ctse(true);
});
- Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
+ Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config)
}
#[cfg(not(any(usart_v1, usart_v2)))]
@@ -795,10 +795,76 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
T::regs().cr3().write(|w| {
w.set_dem(true);
});
- Self::new_inner(peri, rx, tx, tx_dma, rx_dma, config)
+ Self::new_inner_configure(peri, rx, tx, tx_dma, rx_dma, config)
}
- fn new_inner(
+ /// 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_half_duplex(
+ peri: impl Peripheral + 'd,
+ tx: impl Peripheral
> + 'd,
+ _irq: impl interrupt::typelevel::Binding> + '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;
+
+ 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)
+ }
+
+ /// 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_half_duplex_on_rx(
+ peri: impl Peripheral + 'd,
+ rx: impl Peripheral
> + 'd,
+ _irq: impl interrupt::typelevel::Binding> + '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;
+
+ 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)
+ }
+
+ fn new_inner_configure(
peri: impl Peripheral + 'd,
rx: impl Peripheral
> + 'd,
tx: impl Peripheral
> + 'd,
@@ -808,8 +874,6 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
) -> Result {
into_ref!(peri, rx, tx, tx_dma, rx_dma);
- let r = T::regs();
-
// Some chips do not have swap_rx_tx bit
cfg_if::cfg_if! {
if #[cfg(any(usart_v3, usart_v4))] {
@@ -827,6 +891,17 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
}
}
+ Self::new_inner(peri, tx_dma, rx_dma, config)
+ }
+
+ fn new_inner(
+ peri: PeripheralRef<'d, T>,
+ tx_dma: PeripheralRef<'d, TxDma>,
+ rx_dma: PeripheralRef<'d, RxDma>,
+ config: Config,
+ ) -> Result {
+ let r = T::regs();
+
configure(r, &config, T::frequency(), T::KIND, true, true)?;
T::Interrupt::unpend();
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index a8aebfe1f..04b1b35e8 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -701,10 +701,10 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> {
}
async fn wait_enabled(&mut self) {
- trace!("wait_enabled OUT WAITING");
+ trace!("wait_enabled IN WAITING");
let index = self.info.addr.index();
poll_fn(|cx| {
- EP_OUT_WAKERS[index].register(cx.waker());
+ EP_IN_WAKERS[index].register(cx.waker());
let regs = T::regs();
if regs.epr(index).read().stat_tx() == Stat::DISABLED {
Poll::Pending
@@ -713,7 +713,7 @@ impl<'d, T: Instance> driver::Endpoint for Endpoint<'d, T, In> {
}
})
.await;
- trace!("wait_enabled OUT OK");
+ trace!("wait_enabled IN OK");
}
}
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
index e1af0b647..a6fe52ee2 100644
--- a/rust-toolchain.toml
+++ b/rust-toolchain.toml
@@ -1,5 +1,5 @@
[toolchain]
-channel = "beta-2023-12-17"
+channel = "1.75"
components = [ "rust-src", "rustfmt", "llvm-tools" ]
targets = [
"thumbv7em-none-eabi",