From ca3c15658dfb75945506c15070fd0deeb1583aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0pa=C4=8Dek?= Date: Sun, 26 May 2024 15:33:29 +0200 Subject: [PATCH 1/6] stm32/spi: move init code to function that's not generic in T --- embassy-stm32/src/spi/mod.rs | 39 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 5d6277c33..fb8e79ad8 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -13,7 +13,7 @@ use crate::dma::{slice_ptr_parts, word, ChannelAndRequest}; use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; use crate::mode::{Async, Blocking, Mode as PeriMode}; use crate::pac::spi::{regs, vals, Spi as Regs}; -use crate::rcc::{self, RccInfo, SealedRccPeripheral}; +use crate::rcc::{RccInfo, SealedRccPeripheral}; use crate::time::Hertz; use crate::Peripheral; @@ -120,17 +120,30 @@ impl<'d, M: PeriMode> Spi<'d, M> { rx_dma: Option>, config: Config, ) -> Self { - let regs = T::info().regs; - let kernel_clock = T::frequency(); - let br = compute_baud_rate(kernel_clock, config.frequency); + let mut this = Self { + info: T::info(), + kernel_clock: T::frequency(), + sck, + mosi, + miso, + tx_dma, + rx_dma, + current_word_size: ::CONFIG, + _phantom: PhantomData, + }; + this.enable_and_init(config); + this + } + fn enable_and_init(&mut self, config: Config) { + let br = compute_baud_rate(self.kernel_clock, config.frequency); let cpha = config.raw_phase(); let cpol = config.raw_polarity(); - let lsbfirst = config.raw_byte_order(); - rcc::enable_and_reset::(); + self.info.rcc.enable_and_reset(); + let regs = self.info.regs; #[cfg(any(spi_v1, spi_f1))] { regs.cr2().modify(|w| { @@ -209,18 +222,6 @@ impl<'d, M: PeriMode> Spi<'d, M> { w.set_spe(true); }); } - - Self { - info: T::info(), - kernel_clock, - sck, - mosi, - miso, - tx_dma, - rx_dma, - current_word_size: ::CONFIG, - _phantom: PhantomData, - } } /// Reconfigures it with the supplied config. @@ -578,7 +579,7 @@ impl<'d> Spi<'d, Async> { // see RM0453 rev 1 section 7.2.13 page 291 // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. - let pclk3_freq = ::frequency().0; + let pclk3_freq = ::frequency().0; let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); let mut config = Config::default(); config.mode = MODE_0; From 41711195e305e45caec3ff8316688a6b6d6af955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0pa=C4=8Dek?= Date: Sun, 26 May 2024 15:40:42 +0200 Subject: [PATCH 2/6] stm32/i2c: use new_pin! macro --- embassy-stm32/src/i2c/mod.rs | 89 +++++++++++++++++++++++------------- embassy-stm32/src/i2c/v1.rs | 6 --- embassy-stm32/src/i2c/v2.rs | 6 --- 3 files changed, 58 insertions(+), 43 deletions(-) diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 0bf57ef8a..6d12af2cc 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -9,16 +9,16 @@ use core::future::Future; use core::iter; use core::marker::PhantomData; -use embassy_hal_internal::{into_ref, Peripheral}; +use embassy_hal_internal::{Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; use crate::dma::ChannelAndRequest; -use crate::gpio::{AFType, Pull}; +use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _, Speed}; use crate::interrupt::typelevel::Interrupt; use crate::mode::{Async, Blocking, Mode}; -use crate::rcc::{self, RccInfo, SealedRccPeripheral}; +use crate::rcc::{RccInfo, SealedRccPeripheral}; use crate::time::Hertz; use crate::{interrupt, peripherals}; @@ -72,11 +72,29 @@ impl Default for Config { } } +impl Config { + fn scl_pull_mode(&self) -> Pull { + match self.scl_pullup { + true => Pull::Up, + false => Pull::Down, + } + } + + fn sda_pull_mode(&self) -> Pull { + match self.sda_pullup { + true => Pull::Up, + false => Pull::Down, + } + } +} + /// I2C driver. pub struct I2c<'d, M: Mode> { info: &'static Info, state: &'static State, kernel_clock: Hertz, + scl: Option>, + sda: Option>, tx_dma: Option>, rx_dma: Option>, #[cfg(feature = "time")] @@ -98,7 +116,15 @@ impl<'d> I2c<'d, Async> { freq: Hertz, config: Config, ) -> Self { - Self::new_inner(peri, scl, sda, new_dma!(tx_dma), new_dma!(rx_dma), freq, config) + Self::new_inner( + peri, + new_pin!(scl, AFType::OutputOpenDrain, Speed::Medium, config.scl_pull_mode()), + new_pin!(sda, AFType::OutputOpenDrain, Speed::Medium, config.sda_pull_mode()), + new_dma!(tx_dma), + new_dma!(rx_dma), + freq, + config, + ) } } @@ -111,7 +137,15 @@ impl<'d> I2c<'d, Blocking> { freq: Hertz, config: Config, ) -> Self { - Self::new_inner(peri, scl, sda, None, None, freq, config) + Self::new_inner( + peri, + new_pin!(scl, AFType::OutputOpenDrain, Speed::Medium, config.scl_pull_mode()), + new_pin!(sda, AFType::OutputOpenDrain, Speed::Medium, config.sda_pull_mode()), + None, + None, + freq, + config, + ) } } @@ -119,34 +153,13 @@ impl<'d, M: Mode> I2c<'d, M> { /// Create a new I2C driver. fn new_inner( _peri: impl Peripheral

+ 'd, - scl: impl Peripheral

> + 'd, - sda: impl Peripheral

> + 'd, + scl: Option>, + sda: Option>, tx_dma: Option>, rx_dma: Option>, freq: Hertz, config: Config, ) -> Self { - into_ref!(scl, sda); - - rcc::enable_and_reset::(); - - scl.set_as_af_pull( - scl.af_num(), - AFType::OutputOpenDrain, - match config.scl_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - sda.set_as_af_pull( - sda.af_num(), - AFType::OutputOpenDrain, - match config.sda_pullup { - true => Pull::Up, - false => Pull::None, - }, - ); - unsafe { T::EventInterrupt::enable() }; unsafe { T::ErrorInterrupt::enable() }; @@ -154,18 +167,23 @@ impl<'d, M: Mode> I2c<'d, M> { info: T::info(), state: T::state(), kernel_clock: T::frequency(), + scl, + sda, tx_dma, rx_dma, #[cfg(feature = "time")] timeout: config.timeout, _phantom: PhantomData, }; - - this.init(freq, config); - + this.enable_and_init(freq, config); this } + fn enable_and_init(&mut self, freq: Hertz, config: Config) { + self.info.rcc.enable_and_reset(); + self.init(freq, config); + } + fn timeout(&self) -> Timeout { Timeout { #[cfg(feature = "time")] @@ -174,6 +192,15 @@ impl<'d, M: Mode> I2c<'d, M> { } } +impl<'d, M: Mode> Drop for I2c<'d, M> { + fn drop(&mut self) { + self.scl.as_ref().map(|x| x.set_as_disconnected()); + self.sda.as_ref().map(|x| x.set_as_disconnected()); + + self.info.rcc.disable() + } +} + #[derive(Copy, Clone)] struct Timeout { #[cfg(feature = "time")] diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index 0e2bd2e40..28026f83c 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -700,12 +700,6 @@ impl<'d> I2c<'d, Async> { } } -impl<'d, M: PeriMode> Drop for I2c<'d, M> { - fn drop(&mut self) { - self.info.rcc.disable() - } -} - enum Mode { Fast, Standard, diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 193f29733..80163c287 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -671,12 +671,6 @@ impl<'d> I2c<'d, Async> { } } -impl<'d, M: Mode> Drop for I2c<'d, M> { - fn drop(&mut self) { - self.info.rcc.disable(); - } -} - /// I2C Stop Configuration /// /// Peripheral options for generating the STOP condition From ade27b7f212f9548816e5ae21826a230c2345574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0pa=C4=8Dek?= Date: Sun, 26 May 2024 16:21:11 +0200 Subject: [PATCH 3/6] stm32/usart: disconnect pins of RingBufferedUartRx on drop --- embassy-stm32/src/usart/ringbuffered.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index f3a88b93f..8cf75933a 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -4,10 +4,12 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; use embassy_embedded_hal::SetConfig; +use embassy_hal_internal::PeripheralRef; use futures_util::future::{select, Either}; use super::{clear_interrupt_flags, rdr, reconfigure, sr, Config, ConfigError, Error, Info, State, UartRx}; use crate::dma::ReadableRingBuffer; +use crate::gpio::{AnyPin, SealedPin as _}; use crate::mode::Async; use crate::time::Hertz; use crate::usart::{Regs, Sr}; @@ -19,6 +21,8 @@ pub struct RingBufferedUartRx<'d> { info: &'static Info, state: &'static State, kernel_clock: Hertz, + rx: Option>, + rts: Option>, ring_buf: ReadableRingBuffer<'d, u8>, } @@ -49,6 +53,8 @@ impl<'d> UartRx<'d, Async> { let state = self.state; let kernel_clock = self.kernel_clock; let ring_buf = unsafe { ReadableRingBuffer::new(rx_dma, request, rdr(info.regs), dma_buf, opts) }; + let rx = unsafe { self.rx.as_ref().map(|x| x.clone_unchecked()) }; + let rts = unsafe { self.rts.as_ref().map(|x| x.clone_unchecked()) }; // Don't disable the clock mem::forget(self); @@ -57,6 +63,8 @@ impl<'d> UartRx<'d, Async> { info, state, kernel_clock, + rx, + rts, ring_buf, } } @@ -221,6 +229,8 @@ impl<'d> RingBufferedUartRx<'d> { impl Drop for RingBufferedUartRx<'_> { fn drop(&mut self) { self.teardown_uart(); + self.rx.as_ref().map(|x| x.set_as_disconnected()); + self.rts.as_ref().map(|x| x.set_as_disconnected()); super::drop_tx_rx(self.info, self.state); } } From 44e4a2c9e9c1e5824acb68673c8f6b4b98d1ea07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0pa=C4=8Dek?= Date: Sun, 26 May 2024 16:37:26 +0200 Subject: [PATCH 4/6] stm32/buffered-usart: use new_pin! and disconnect pins on drop --- embassy-stm32/src/usart/buffered.rs | 102 +++++++++++++++++----------- embassy-stm32/src/usart/mod.rs | 5 +- 2 files changed, 65 insertions(+), 42 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index eacf95002..2c19e16db 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -6,7 +6,7 @@ use core::task::Poll; use embassy_embedded_hal::SetConfig; use embassy_hal_internal::atomic_ring_buffer::RingBuffer; -use embassy_hal_internal::{into_ref, Peripheral}; +use embassy_hal_internal::{Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(not(any(usart_v1, usart_v2)))] @@ -15,7 +15,7 @@ use super::{ clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance, Regs, RtsPin, RxPin, TxPin, }; -use crate::gpio::AFType; +use crate::gpio::{AFType, AnyPin, SealedPin as _}; use crate::interrupt::typelevel::Interrupt as _; use crate::interrupt::{self, InterruptExt}; use crate::rcc; @@ -156,7 +156,9 @@ pub struct BufferedUartTx<'d> { info: &'static Info, state: &'static State, kernel_clock: Hertz, - _phantom: PhantomData<&'d mut ()>, + tx: Option>, + cts: Option>, + de: Option>, } /// Rx-only buffered UART @@ -166,7 +168,8 @@ pub struct BufferedUartRx<'d> { info: &'static Info, state: &'static State, kernel_clock: Hertz, - _phantom: PhantomData<&'d mut ()>, + rx: Option>, + rts: Option>, } impl<'d> SetConfig for BufferedUart<'d> { @@ -207,9 +210,17 @@ impl<'d> BufferedUart<'d> { rx_buffer: &'d mut [u8], config: Config, ) -> Result { - rcc::enable_and_reset::(); - - Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) + Self::new_inner( + peri, + new_pin!(rx, AFType::Input), + new_pin!(tx, AFType::OutputPushPull), + None, + None, + None, + tx_buffer, + rx_buffer, + config, + ) } /// Create a new bidirectional buffered UART driver with request-to-send and clear-to-send pins @@ -224,18 +235,17 @@ impl<'d> BufferedUart<'d> { rx_buffer: &'d mut [u8], config: Config, ) -> Result { - into_ref!(cts, rts); - - rcc::enable_and_reset::(); - - rts.set_as_af(rts.af_num(), AFType::OutputPushPull); - cts.set_as_af(cts.af_num(), AFType::Input); - T::info().regs.cr3().write(|w| { - w.set_rtse(true); - w.set_ctse(true); - }); - - Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) + Self::new_inner( + peri, + new_pin!(rx, AFType::Input), + new_pin!(tx, AFType::OutputPushPull), + new_pin!(rts, AFType::OutputPushPull), + new_pin!(cts, AFType::Input), + None, + tx_buffer, + rx_buffer, + config, + ) } /// Create a new bidirectional buffered UART driver with a driver-enable pin @@ -250,27 +260,31 @@ impl<'d> BufferedUart<'d> { rx_buffer: &'d mut [u8], config: Config, ) -> Result { - into_ref!(de); - - rcc::enable_and_reset::(); - - de.set_as_af(de.af_num(), AFType::OutputPushPull); - T::info().regs.cr3().write(|w| { - w.set_dem(true); - }); - - Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) + Self::new_inner( + peri, + new_pin!(rx, AFType::Input), + new_pin!(tx, AFType::OutputPushPull), + None, + None, + new_pin!(de, AFType::OutputPushPull), + tx_buffer, + rx_buffer, + config, + ) } fn new_inner( _peri: impl Peripheral

+ 'd, - rx: impl Peripheral

> + 'd, - tx: impl Peripheral

> + 'd, + rx: Option>, + tx: Option>, + rts: Option>, + cts: Option>, + de: Option>, tx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8], config: Config, ) -> Result { - into_ref!(_peri, rx, tx); + rcc::enable_and_reset::(); let info = T::info(); let state = T::buffered_state(); @@ -280,13 +294,15 @@ impl<'d> BufferedUart<'d> { let len = rx_buffer.len(); unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; - let r = info.regs; - rx.set_as_af(rx.af_num(), AFType::Input); - tx.set_as_af(tx.af_num(), AFType::OutputPushPull); - + 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)?; - r.cr1().modify(|w| { + info.regs.cr1().modify(|w| { w.set_rxneie(true); w.set_idleie(true); }); @@ -301,13 +317,16 @@ impl<'d> BufferedUart<'d> { info, state, kernel_clock, - _phantom: PhantomData, + rx, + rts, }, tx: BufferedUartTx { info, state, kernel_clock, - _phantom: PhantomData, + tx, + cts, + de, }, }) } @@ -516,6 +535,8 @@ impl<'d> Drop for BufferedUartRx<'d> { } } + self.rx.as_ref().map(|x| x.set_as_disconnected()); + self.rts.as_ref().map(|x| x.set_as_disconnected()); drop_tx_rx(self.info, state); } } @@ -533,6 +554,9 @@ impl<'d> Drop for BufferedUartTx<'d> { } } + 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()); drop_tx_rx(self.info, state); } } diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 2a39c6301..6ef80c54f 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::{AFType, AnyPin, SealedPin}; +use crate::gpio::{AFType, AnyPin, SealedPin as _}; use crate::interrupt::typelevel::Interrupt as _; use crate::interrupt::{self, Interrupt, InterruptExt}; use crate::mode::{Async, Blocking, Mode}; @@ -1233,9 +1233,8 @@ impl<'d, M: Mode> Uart<'d, M> { let info = T::info(); let state = T::state(); let kernel_clock = T::frequency(); - let r = info.regs; - r.cr3().write(|w| { + info.regs.cr3().write(|w| { w.set_rtse(rts.is_some()); w.set_ctse(cts.is_some()); #[cfg(not(any(usart_v1, usart_v2)))] From 664e4a5c032d2291beedf1ead706f5d17b8178da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0pa=C4=8Dek?= Date: Sun, 26 May 2024 16:55:07 +0200 Subject: [PATCH 5/6] 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 { - rcc::enable_and_reset::(); - 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>, config: Config, ) -> Result { - rcc::enable_and_reset::(); - - 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>, config: Config, ) -> Result { - rcc::enable_and_reset::(); - - 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>, config: Config, ) -> Result { - rcc::enable_and_reset::(); - 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 From f3703ff6bfed6f8342b49cfd9a65d543d1c99c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0pa=C4=8Dek?= Date: Mon, 3 Jun 2024 20:12:33 +0200 Subject: [PATCH 6/6] stm32/usart: set refcount even if initialization failed --- embassy-stm32/src/usart/buffered.rs | 2 +- embassy-stm32/src/usart/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 09d020a7b..fd79e035e 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -315,6 +315,7 @@ impl<'d> BufferedUart<'d> { ) -> Result<(), ConfigError> { let info = self.rx.info; let state = self.rx.state; + state.tx_rx_refcount.store(2, Ordering::Relaxed); info.rcc.enable_and_reset(); @@ -339,7 +340,6 @@ impl<'d> BufferedUart<'d> { info.interrupt.unpend(); unsafe { info.interrupt.enable() }; - state.tx_rx_refcount.store(2, Ordering::Relaxed); Ok(()) } diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index df5121f67..53321391a 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -446,6 +446,7 @@ impl<'d, M: Mode> UartTx<'d, M> { fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { let info = self.info; let state = self.state; + state.tx_rx_refcount.store(1, Ordering::Relaxed); info.rcc.enable_and_reset(); @@ -454,7 +455,6 @@ impl<'d, M: Mode> UartTx<'d, M> { }); configure(info, self.kernel_clock, config, false, true)?; - state.tx_rx_refcount.store(1, Ordering::Relaxed); Ok(()) } @@ -798,6 +798,7 @@ impl<'d, M: Mode> UartRx<'d, M> { fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { let info = self.info; let state = self.state; + state.tx_rx_refcount.store(1, Ordering::Relaxed); info.rcc.enable_and_reset(); @@ -809,7 +810,6 @@ impl<'d, M: Mode> UartRx<'d, M> { info.interrupt.unpend(); unsafe { info.interrupt.enable() }; - state.tx_rx_refcount.store(1, Ordering::Relaxed); Ok(()) } @@ -1271,6 +1271,7 @@ impl<'d, M: Mode> Uart<'d, M> { fn enable_and_configure(&mut self, config: &Config) -> Result<(), ConfigError> { let info = self.rx.info; let state = self.rx.state; + state.tx_rx_refcount.store(2, Ordering::Relaxed); info.rcc.enable_and_reset(); @@ -1285,7 +1286,6 @@ impl<'d, M: Mode> Uart<'d, M> { info.interrupt.unpend(); unsafe { info.interrupt.enable() }; - state.tx_rx_refcount.store(2, Ordering::Relaxed); Ok(()) }