From e3cec4a246a0e3cbaae60c91f946f608f6637f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anton=20P=C3=B6hl?= Date: Thu, 13 Mar 2025 10:52:41 +0100 Subject: [PATCH] Stm32 usart: make pin modes of cts, tx, rts and de configurable --- embassy-stm32/src/usart/buffered.rs | 28 ++++----- embassy-stm32/src/usart/mod.rs | 90 ++++++++++++++++++++++------- 2 files changed, 84 insertions(+), 34 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index b1640b6dc..2dfb99dbc 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -16,7 +16,7 @@ use super::{ sr, tdr, Config, ConfigError, CtsPin, Duplex, Error, HalfDuplexConfig, 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, diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 675e90c7f..80a391d41 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -136,6 +136,40 @@ 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, + #[cfg(not(gpio_v1))] + /// Push pull with internal pull up resistor + PushPullPullUp, + #[cfg(not(gpio_v1))] + /// Push pull with internal pull down resistor + PushPullPullDown, + /// Open drain output using external pull down resistor + OpenDrainExternal, + #[cfg(not(gpio_v1))] + /// Open drain output using internal pull up resistor + OpenDrainInternal, +} + +impl OutputConfig { + const fn af_type(self) -> AfType { + match self { + OutputConfig::PushPull => AfType::output(OutputType::PushPull, Speed::Medium), + #[cfg(not(gpio_v1))] + OutputConfig::PushPullPullUp => AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Up), + #[cfg(not(gpio_v1))] + OutputConfig::PushPullPullDown => AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Down), + OutputConfig::OpenDrainExternal => AfType::output(OutputType::OpenDrain, Speed::Medium), + #[cfg(not(gpio_v1))] + OutputConfig::OpenDrainInternal => AfType::output_pull(OutputType::OpenDrain, Speed::Medium, Pull::Up), + } + } +} + #[derive(Clone, Copy, PartialEq, Eq, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] /// Duplex mode @@ -208,6 +242,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, } @@ -218,13 +264,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) } @@ -248,6 +294,10 @@ 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, } } @@ -426,7 +476,7 @@ impl<'d> UartTx<'d, Async> { ) -> Result { Self::new_inner( peri, - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(tx, config.tx_af()), None, new_dma!(tx_dma), config, @@ -443,8 +493,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, ) @@ -484,7 +534,7 @@ impl<'d> UartTx<'d, Blocking> { ) -> Result { Self::new_inner( peri, - new_pin!(tx, AfType::output(OutputType::PushPull, Speed::Medium)), + new_pin!(tx, config.tx_af()), None, None, config, @@ -500,8 +550,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, ) @@ -658,7 +708,7 @@ impl<'d> UartRx<'d, Async> { ) -> Result { Self::new_inner( peri, - new_pin!(rx, AfType::input(config.rx_pull)), + new_pin!(rx, config.rx_af()), None, new_dma!(rx_dma), config, @@ -676,8 +726,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, ) @@ -912,7 +962,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 @@ -924,8 +974,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, ) @@ -1141,8 +1191,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), @@ -1168,7 +1218,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, @@ -1308,8 +1358,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, @@ -1332,7 +1382,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,