diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 8a33a152c..06d5f7528 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -13,10 +13,10 @@ use embassy_sync::waitqueue::AtomicWaker; use super::DePin; use super::{ clear_interrupt_flags, configure, half_duplex_set_rx_tx_before_write, rdr, reconfigure, send_break, set_baudrate, - sr, tdr, Config, ConfigError, CtsPin, Duplex, Error, HalfDuplexConfig, HalfDuplexReadback, Info, Instance, Regs, - RtsPin, RxPin, TxPin, + sr, tdr, Config, ConfigError, CtsPin, Duplex, Error, HalfDuplexReadback, Info, Instance, Regs, RtsPin, RxPin, + TxPin, }; -use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; +use crate::gpio::{AfType, AnyPin, Pull, SealedPin as _}; use crate::interrupt::{self, InterruptExt}; use crate::time::Hertz; @@ -217,8 +217,8 @@ impl<'d> BufferedUart<'d> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(config.rx_pull)), - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(rx, config.rx_af()), + new_pin!(tx, config.tx_af()), None, None, None, @@ -242,10 +242,10 @@ impl<'d> BufferedUart<'d> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(Pull::None)), - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), - new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), - new_pin!(cts, AfType::input(Pull::None)), + new_pin!(rx, config.rx_af()), + new_pin!(tx, config.tx_af()), + new_pin!(rts, config.rts_config.af_type()), + new_pin!(cts, AfType::input(config.cts_pull)), None, tx_buffer, rx_buffer, @@ -266,8 +266,8 @@ impl<'d> BufferedUart<'d> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(Pull::None)), - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(rx, config.rx_af()), + new_pin!(tx, config.tx_af()), None, None, new_pin!(rts, AfType::input(Pull::None)), // RTS mapped used as DE @@ -290,8 +290,8 @@ impl<'d> BufferedUart<'d> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(Pull::None)), - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(rx, config.rx_af()), + new_pin!(tx, config.tx_af()), new_pin!(rts, AfType::input(Pull::None)), None, // no CTS None, // no DE @@ -315,11 +315,11 @@ impl<'d> BufferedUart<'d> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(config.rx_pull)), - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(rx, config.rx_af()), + new_pin!(tx, config.tx_af()), None, None, - new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(de, config.de_config.af_type()), tx_buffer, rx_buffer, config, @@ -346,7 +346,6 @@ impl<'d> BufferedUart<'d> { rx_buffer: &'d mut [u8], mut config: Config, readback: HalfDuplexReadback, - half_duplex: HalfDuplexConfig, ) -> Result { #[cfg(not(any(usart_v1, usart_v2)))] { @@ -357,7 +356,7 @@ impl<'d> BufferedUart<'d> { Self::new_inner( peri, None, - new_pin!(tx, half_duplex.af_type()), + new_pin!(tx, config.tx_af()), None, None, None, @@ -386,14 +385,13 @@ impl<'d> BufferedUart<'d> { rx_buffer: &'d mut [u8], mut config: Config, readback: HalfDuplexReadback, - half_duplex: HalfDuplexConfig, ) -> Result { config.swap_rx_tx = true; config.duplex = Duplex::Half(readback); Self::new_inner( peri, - new_pin!(rx, half_duplex.af_type()), + new_pin!(rx, config.rx_af()), None, None, None, diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 10e3ea88b..b3f8bc00c 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -14,7 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker; use futures_util::future::{select, Either}; use crate::dma::ChannelAndRequest; -use crate::gpio::{self, AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; +use crate::gpio::{AfType, AnyPin, OutputType, Pull, SealedPin as _, Speed}; use crate::interrupt::typelevel::Interrupt as _; use crate::interrupt::{self, Interrupt, InterruptExt}; use crate::mode::{Async, Blocking, Mode}; @@ -131,6 +131,30 @@ pub enum HalfDuplexReadback { Readback, } +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +/// Half duplex IO mode +pub enum OutputConfig { + /// Push pull allows for faster baudrates, no internal pullup + PushPull, + /// Open drain output (external pull up needed) + OpenDrain, + #[cfg(not(gpio_v1))] + /// Open drain output with internal pull up resistor + OpenDrainPullUp, +} + +impl OutputConfig { + const fn af_type(self) -> AfType { + match self { + OutputConfig::PushPull => AfType::output(OutputType::PushPull, Speed::Medium), + OutputConfig::OpenDrain => AfType::output(OutputType::OpenDrain, Speed::Medium), + #[cfg(not(gpio_v1))] + OutputConfig::OpenDrainPullUp => AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Up), + } + } +} + #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// Duplex mode @@ -203,6 +227,18 @@ pub struct Config { /// Set the pull configuration for the RX pin. pub rx_pull: Pull, + /// Set the pull configuration for the CTS pin. + pub cts_pull: Pull, + + /// Set the pin configuration for the TX pin. + pub tx_config: OutputConfig, + + /// Set the pin configuration for the RTS pin. + pub rts_config: OutputConfig, + + /// Set the pin configuration for the DE pin. + pub de_config: OutputConfig, + // private: set by new_half_duplex, not by the user. duplex: Duplex, } @@ -213,13 +249,13 @@ impl Config { if self.swap_rx_tx { return AfType::input(self.rx_pull); }; - AfType::output(OutputType::PushPull, Speed::Medium) + self.tx_config.af_type() } fn rx_af(&self) -> AfType { #[cfg(any(usart_v3, usart_v4))] if self.swap_rx_tx { - return AfType::output(OutputType::PushPull, Speed::Medium); + return self.tx_config.af_type(); }; AfType::input(self.rx_pull) } @@ -243,35 +279,15 @@ impl Default for Config { #[cfg(any(usart_v3, usart_v4))] invert_rx: false, rx_pull: Pull::None, + cts_pull: Pull::None, + tx_config: OutputConfig::PushPull, + rts_config: OutputConfig::PushPull, + de_config: OutputConfig::PushPull, duplex: Duplex::Full, } } } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Half duplex IO mode -pub enum HalfDuplexConfig { - /// Push pull allows for faster baudrates, may require series resistor - PushPull, - /// Open drain output using external pull up resistor - OpenDrainExternal, - #[cfg(not(gpio_v1))] - /// Open drain output using internal pull up resistor - OpenDrainInternal, -} - -impl HalfDuplexConfig { - fn af_type(self) -> gpio::AfType { - match self { - HalfDuplexConfig::PushPull => AfType::output(OutputType::PushPull, Speed::Medium), - HalfDuplexConfig::OpenDrainExternal => AfType::output(OutputType::OpenDrain, Speed::Medium), - #[cfg(not(gpio_v1))] - HalfDuplexConfig::OpenDrainInternal => AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Up), - } - } -} - /// Serial error #[derive(Debug, Eq, PartialEq, Copy, Clone)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -419,13 +435,7 @@ impl<'d> UartTx<'d, Async> { tx_dma: Peri<'d, impl TxDma>, config: Config, ) -> Result { - Self::new_inner( - peri, - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), - None, - new_dma!(tx_dma), - config, - ) + Self::new_inner(peri, new_pin!(tx, config.tx_af()), None, new_dma!(tx_dma), config) } /// Create a new tx-only UART with a clear-to-send pin @@ -438,8 +448,8 @@ impl<'d> UartTx<'d, Async> { ) -> Result { Self::new_inner( peri, - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), - new_pin!(cts, AfType::input(Pull::None)), + new_pin!(tx, config.tx_af()), + new_pin!(cts, AfType::input(config.cts_pull)), new_dma!(tx_dma), config, ) @@ -477,13 +487,7 @@ impl<'d> UartTx<'d, Blocking> { tx: Peri<'d, impl TxPin>, config: Config, ) -> Result { - Self::new_inner( - peri, - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), - None, - None, - config, - ) + Self::new_inner(peri, new_pin!(tx, config.tx_af()), None, None, config) } /// Create a new blocking tx-only UART with a clear-to-send pin @@ -495,8 +499,8 @@ impl<'d> UartTx<'d, Blocking> { ) -> Result { Self::new_inner( peri, - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), - new_pin!(cts, AfType::input(config.rx_pull)), + new_pin!(tx, config.tx_af()), + new_pin!(cts, AfType::input(config.cts_pull)), None, config, ) @@ -651,13 +655,7 @@ impl<'d> UartRx<'d, Async> { rx_dma: Peri<'d, impl RxDma>, config: Config, ) -> Result { - Self::new_inner( - peri, - new_pin!(rx, AfType::input(config.rx_pull)), - None, - new_dma!(rx_dma), - config, - ) + Self::new_inner(peri, new_pin!(rx, config.rx_af()), None, new_dma!(rx_dma), config) } /// Create a new rx-only UART with a request-to-send pin @@ -671,8 +669,8 @@ impl<'d> UartRx<'d, Async> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(config.rx_pull)), - new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(rx, config.rx_af()), + new_pin!(rts, config.rts_config.af_type()), new_dma!(rx_dma), config, ) @@ -906,7 +904,7 @@ impl<'d> UartRx<'d, Blocking> { rx: Peri<'d, impl RxPin>, config: Config, ) -> Result { - Self::new_inner(peri, new_pin!(rx, AfType::input(config.rx_pull)), None, None, config) + Self::new_inner(peri, new_pin!(rx, config.rx_af()), None, None, config) } /// Create a new rx-only UART with a request-to-send pin @@ -918,8 +916,8 @@ impl<'d> UartRx<'d, Blocking> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(config.rx_pull)), - new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(rx, config.rx_af()), + new_pin!(rts, config.rts_config.af_type()), None, config, ) @@ -1135,8 +1133,8 @@ impl<'d> Uart<'d, Async> { peri, new_pin!(rx, config.rx_af()), new_pin!(tx, config.tx_af()), - new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), - new_pin!(cts, AfType::input(Pull::None)), + new_pin!(rts, config.rts_config.af_type()), + new_pin!(cts, AfType::input(config.cts_pull)), None, new_dma!(tx_dma), new_dma!(rx_dma), @@ -1162,7 +1160,7 @@ impl<'d> Uart<'d, Async> { new_pin!(tx, config.tx_af()), None, None, - new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(de, config.de_config.af_type()), new_dma!(tx_dma), new_dma!(rx_dma), config, @@ -1189,7 +1187,6 @@ impl<'d> Uart<'d, Async> { rx_dma: Peri<'d, impl RxDma>, mut config: Config, readback: HalfDuplexReadback, - half_duplex: HalfDuplexConfig, ) -> Result { #[cfg(not(any(usart_v1, usart_v2)))] { @@ -1200,7 +1197,7 @@ impl<'d> Uart<'d, Async> { Self::new_inner( peri, None, - new_pin!(tx, half_duplex.af_type()), + new_pin!(tx, config.tx_af()), None, None, None, @@ -1229,7 +1226,6 @@ impl<'d> Uart<'d, Async> { rx_dma: Peri<'d, impl RxDma>, mut config: Config, readback: HalfDuplexReadback, - half_duplex: HalfDuplexConfig, ) -> Result { config.swap_rx_tx = true; config.duplex = Duplex::Half(readback); @@ -1238,7 +1234,7 @@ impl<'d> Uart<'d, Async> { peri, None, None, - new_pin!(rx, half_duplex.af_type()), + new_pin!(rx, config.rx_af()), None, None, new_dma!(tx_dma), @@ -1302,8 +1298,8 @@ impl<'d> Uart<'d, Blocking> { peri, new_pin!(rx, config.rx_af()), new_pin!(tx, config.tx_af()), - new_pin!(rts, AfType::output(OutputType::PushPull, Speed::Medium)), - new_pin!(cts, AfType::input(Pull::None)), + new_pin!(rts, config.rts_config.af_type()), + new_pin!(cts, AfType::input(config.cts_pull)), None, None, None, @@ -1326,7 +1322,7 @@ impl<'d> Uart<'d, Blocking> { new_pin!(tx, config.tx_af()), None, None, - new_pin!(de, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(de, config.de_config.af_type()), None, None, config, @@ -1349,7 +1345,6 @@ impl<'d> Uart<'d, Blocking> { tx: Peri<'d, impl TxPin>, mut config: Config, readback: HalfDuplexReadback, - half_duplex: HalfDuplexConfig, ) -> Result { #[cfg(not(any(usart_v1, usart_v2)))] { @@ -1360,7 +1355,7 @@ impl<'d> Uart<'d, Blocking> { Self::new_inner( peri, None, - new_pin!(tx, half_duplex.af_type()), + new_pin!(tx, config.tx_af()), None, None, None, @@ -1386,7 +1381,6 @@ impl<'d> Uart<'d, Blocking> { rx: Peri<'d, impl RxPin>, mut config: Config, readback: HalfDuplexReadback, - half_duplex: HalfDuplexConfig, ) -> Result { config.swap_rx_tx = true; config.duplex = Duplex::Half(readback); @@ -1395,7 +1389,7 @@ impl<'d> Uart<'d, Blocking> { peri, None, None, - new_pin!(rx, half_duplex.af_type()), + new_pin!(rx, config.rx_af()), None, None, None, diff --git a/examples/stm32g0/src/bin/onewire_ds18b20.rs b/examples/stm32g0/src/bin/onewire_ds18b20.rs index f85cc4ff8..62f8711a6 100644 --- a/examples/stm32g0/src/bin/onewire_ds18b20.rs +++ b/examples/stm32g0/src/bin/onewire_ds18b20.rs @@ -8,7 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::mode::Async; use embassy_stm32::usart::{ - BufferedUartRx, BufferedUartTx, Config, ConfigError, HalfDuplexConfig, RingBufferedUartRx, UartTx, + BufferedUartRx, BufferedUartTx, Config, ConfigError, OutputConfig, RingBufferedUartRx, UartTx, }; use embassy_stm32::{bind_interrupts, peripherals, usart}; use embassy_time::{Duration, Timer}; @@ -21,16 +21,18 @@ fn create_onewire(p: embassy_stm32::Peripherals) -> OneWire usart::InterruptHandler; }); + let mut config = Config::default(); + config.tx_config = OutputConfig::OpenDrain; + let usart = Uart::new_half_duplex( p.USART1, p.PA9, Irqs, p.DMA1_CH1, p.DMA1_CH2, - Config::default(), + config, // Enable readback so we can read sensor pulling data low while transmission is in progress usart::HalfDuplexReadback::Readback, - HalfDuplexConfig::OpenDrainExternal, ) .unwrap(); @@ -50,6 +52,8 @@ fn create_onewire(p: embassy_stm32::Peripherals) -> OneWire OneWire