From 664e4a5c032d2291beedf1ead706f5d17b8178da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C5=A0pa=C4=8Dek?= <patek.mail@gmail.com>
Date: Sun, 26 May 2024 16:55:07 +0200
Subject: [PATCH] stm32/usart: move init code to function that's not generic in
 T

---
 embassy-stm32/src/usart/buffered.rs |  68 +++++++++------
 embassy-stm32/src/usart/mod.rs      | 130 ++++++++++++++++------------
 2 files changed, 113 insertions(+), 85 deletions(-)

diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 2c19e16db..09d020a7b 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -16,9 +16,7 @@ use super::{
     Regs, RtsPin, RxPin, TxPin,
 };
 use crate::gpio::{AFType, AnyPin, SealedPin as _};
-use crate::interrupt::typelevel::Interrupt as _;
 use crate::interrupt::{self, InterruptExt};
-use crate::rcc;
 use crate::time::Hertz;
 
 /// Interrupt handler.
@@ -284,35 +282,11 @@ impl<'d> BufferedUart<'d> {
         rx_buffer: &'d mut [u8],
         config: Config,
     ) -> Result<Self, ConfigError> {
-        rcc::enable_and_reset::<T>();
-
         let info = T::info();
         let state = T::buffered_state();
         let kernel_clock = T::frequency();
-        let len = tx_buffer.len();
-        unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
-        let len = rx_buffer.len();
-        unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
 
-        info.regs.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(info, kernel_clock, &config, true, true)?;
-
-        info.regs.cr1().modify(|w| {
-            w.set_rxneie(true);
-            w.set_idleie(true);
-        });
-
-        T::Interrupt::unpend();
-        unsafe { T::Interrupt::enable() };
-
-        state.tx_rx_refcount.store(2, Ordering::Relaxed);
-
-        Ok(Self {
+        let mut this = Self {
             rx: BufferedUartRx {
                 info,
                 state,
@@ -328,7 +302,45 @@ impl<'d> BufferedUart<'d> {
                 cts,
                 de,
             },
-        })
+        };
+        this.enable_and_configure(tx_buffer, rx_buffer, &config)?;
+        Ok(this)
+    }
+
+    fn enable_and_configure(
+        &mut self,
+        tx_buffer: &'d mut [u8],
+        rx_buffer: &'d mut [u8],
+        config: &Config,
+    ) -> Result<(), ConfigError> {
+        let info = self.rx.info;
+        let state = self.rx.state;
+
+        info.rcc.enable_and_reset();
+
+        let len = tx_buffer.len();
+        unsafe { state.tx_buf.init(tx_buffer.as_mut_ptr(), len) };
+        let len = rx_buffer.len();
+        unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
+
+        info.regs.cr3().write(|w| {
+            w.set_rtse(self.rx.rts.is_some());
+            w.set_ctse(self.tx.cts.is_some());
+            #[cfg(not(any(usart_v1, usart_v2)))]
+            w.set_dem(self.tx.de.is_some());
+        });
+        configure(info, self.rx.kernel_clock, &config, true, true)?;
+
+        info.regs.cr1().modify(|w| {
+            w.set_rxneie(true);
+            w.set_idleie(true);
+        });
+
+        info.interrupt.unpend();
+        unsafe { info.interrupt.enable() };
+
+        state.tx_rx_refcount.store(2, Ordering::Relaxed);
+        Ok(())
     }
 
     /// Split the driver into a Tx and Rx part (useful for sending to separate tasks)
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 6ef80c54f..df5121f67 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -28,7 +28,7 @@ use crate::pac::usart::Lpuart as Regs;
 #[cfg(any(usart_v1, usart_v2))]
 use crate::pac::usart::Usart as Regs;
 use crate::pac::usart::{regs, vals};
-use crate::rcc::{self, RccInfo, SealedRccPeripheral};
+use crate::rcc::{RccInfo, SealedRccPeripheral};
 use crate::time::Hertz;
 use crate::Peripheral;
 
@@ -429,29 +429,33 @@ impl<'d, M: Mode> UartTx<'d, M> {
         tx_dma: Option<ChannelAndRequest<'d>>,
         config: Config,
     ) -> Result<Self, ConfigError> {
-        rcc::enable_and_reset::<T>();
-
-        let info = T::info();
-        let state = T::state();
-        let kernel_clock = T::frequency();
-        let r = info.regs;
-        r.cr3().modify(|w| {
-            w.set_ctse(cts.is_some());
-        });
-        configure(info, kernel_clock, &config, false, true)?;
-
-        state.tx_rx_refcount.store(1, Ordering::Relaxed);
-
-        Ok(Self {
-            info,
-            state,
-            kernel_clock,
+        let mut this = Self {
+            info: T::info(),
+            state: T::state(),
+            kernel_clock: T::frequency(),
             tx,
             cts,
             de: None,
             tx_dma,
             _phantom: PhantomData,
-        })
+        };
+        this.enable_and_configure(&config)?;
+        Ok(this)
+    }
+
+    fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
+        let info = self.info;
+        let state = self.state;
+
+        info.rcc.enable_and_reset();
+
+        info.regs.cr3().modify(|w| {
+            w.set_ctse(self.cts.is_some());
+        });
+        configure(info, self.kernel_clock, config, false, true)?;
+
+        state.tx_rx_refcount.store(1, Ordering::Relaxed);
+        Ok(())
     }
 
     /// Reconfigure the driver
@@ -775,34 +779,38 @@ impl<'d, M: Mode> UartRx<'d, M> {
         rx_dma: Option<ChannelAndRequest<'d>>,
         config: Config,
     ) -> Result<Self, ConfigError> {
-        rcc::enable_and_reset::<T>();
-
-        let info = T::info();
-        let state = T::state();
-        let kernel_clock = T::frequency();
-        let r = info.regs;
-        r.cr3().write(|w| {
-            w.set_rtse(rts.is_some());
-        });
-        configure(info, kernel_clock, &config, true, false)?;
-
-        T::Interrupt::unpend();
-        unsafe { T::Interrupt::enable() };
-
-        state.tx_rx_refcount.store(1, Ordering::Relaxed);
-
-        Ok(Self {
+        let mut this = Self {
             _phantom: PhantomData,
-            info,
-            state,
-            kernel_clock,
+            info: T::info(),
+            state: T::state(),
+            kernel_clock: T::frequency(),
             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),
-        })
+        };
+        this.enable_and_configure(&config)?;
+        Ok(this)
+    }
+
+    fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
+        let info = self.info;
+        let state = self.state;
+
+        info.rcc.enable_and_reset();
+
+        info.regs.cr3().write(|w| {
+            w.set_rtse(self.rts.is_some());
+        });
+        configure(info, self.kernel_clock, &config, true, false)?;
+
+        info.interrupt.unpend();
+        unsafe { info.interrupt.enable() };
+
+        state.tx_rx_refcount.store(1, Ordering::Relaxed);
+        Ok(())
     }
 
     /// Reconfigure the driver
@@ -1228,26 +1236,11 @@ impl<'d, M: Mode> Uart<'d, M> {
         rx_dma: Option<ChannelAndRequest<'d>>,
         config: Config,
     ) -> Result<Self, ConfigError> {
-        rcc::enable_and_reset::<T>();
-
         let info = T::info();
         let state = T::state();
         let kernel_clock = T::frequency();
 
-        info.regs.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(info, kernel_clock, &config, true, true)?;
-
-        T::Interrupt::unpend();
-        unsafe { T::Interrupt::enable() };
-
-        state.tx_rx_refcount.store(2, Ordering::Relaxed);
-
-        Ok(Self {
+        let mut this = Self {
             tx: UartTx {
                 _phantom: PhantomData,
                 info,
@@ -1270,7 +1263,30 @@ impl<'d, M: Mode> Uart<'d, M> {
                 #[cfg(any(usart_v1, usart_v2))]
                 buffered_sr: stm32_metapac::usart::regs::Sr(0),
             },
-        })
+        };
+        this.enable_and_configure(&config)?;
+        Ok(this)
+    }
+
+    fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> {
+        let info = self.rx.info;
+        let state = self.rx.state;
+
+        info.rcc.enable_and_reset();
+
+        info.regs.cr3().write(|w| {
+            w.set_rtse(self.rx.rts.is_some());
+            w.set_ctse(self.tx.cts.is_some());
+            #[cfg(not(any(usart_v1, usart_v2)))]
+            w.set_dem(self.tx.de.is_some());
+        });
+        configure(info, self.rx.kernel_clock, config, true, true)?;
+
+        info.interrupt.unpend();
+        unsafe { info.interrupt.enable() };
+
+        state.tx_rx_refcount.store(2, Ordering::Relaxed);
+        Ok(())
     }
 
     /// Perform a blocking write