stm32/usart: move init code to function that's not generic in T

This commit is contained in:
Jan Špaček 2024-05-26 16:55:07 +02:00
parent 44e4a2c9e9
commit 664e4a5c03
2 changed files with 113 additions and 85 deletions

View File

@ -16,9 +16,7 @@ use super::{
Regs, RtsPin, RxPin, TxPin, Regs, RtsPin, RxPin, TxPin,
}; };
use crate::gpio::{AFType, AnyPin, SealedPin as _}; use crate::gpio::{AFType, AnyPin, SealedPin as _};
use crate::interrupt::typelevel::Interrupt as _;
use crate::interrupt::{self, InterruptExt}; use crate::interrupt::{self, InterruptExt};
use crate::rcc;
use crate::time::Hertz; use crate::time::Hertz;
/// Interrupt handler. /// Interrupt handler.
@ -284,35 +282,11 @@ impl<'d> BufferedUart<'d> {
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
rcc::enable_and_reset::<T>();
let info = T::info(); let info = T::info();
let state = T::buffered_state(); let state = T::buffered_state();
let kernel_clock = T::frequency(); 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| { let mut this = Self {
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 {
rx: BufferedUartRx { rx: BufferedUartRx {
info, info,
state, state,
@ -328,7 +302,45 @@ impl<'d> BufferedUart<'d> {
cts, cts,
de, 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) /// Split the driver into a Tx and Rx part (useful for sending to separate tasks)

View File

@ -28,7 +28,7 @@ use crate::pac::usart::Lpuart as Regs;
#[cfg(any(usart_v1, usart_v2))] #[cfg(any(usart_v1, usart_v2))]
use crate::pac::usart::Usart as Regs; use crate::pac::usart::Usart as Regs;
use crate::pac::usart::{regs, vals}; use crate::pac::usart::{regs, vals};
use crate::rcc::{self, RccInfo, SealedRccPeripheral}; use crate::rcc::{RccInfo, SealedRccPeripheral};
use crate::time::Hertz; use crate::time::Hertz;
use crate::Peripheral; use crate::Peripheral;
@ -429,29 +429,33 @@ impl<'d, M: Mode> UartTx<'d, M> {
tx_dma: Option<ChannelAndRequest<'d>>, tx_dma: Option<ChannelAndRequest<'d>>,
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
rcc::enable_and_reset::<T>(); let mut this = Self {
info: T::info(),
let info = T::info(); state: T::state(),
let state = T::state(); kernel_clock: T::frequency(),
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,
tx, tx,
cts, cts,
de: None, de: None,
tx_dma, tx_dma,
_phantom: PhantomData, _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 /// Reconfigure the driver
@ -775,34 +779,38 @@ impl<'d, M: Mode> UartRx<'d, M> {
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
rcc::enable_and_reset::<T>(); let mut this = Self {
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 {
_phantom: PhantomData, _phantom: PhantomData,
info, info: T::info(),
state, state: T::state(),
kernel_clock, kernel_clock: T::frequency(),
rx, rx,
rts, rts,
rx_dma, rx_dma,
detect_previous_overrun: config.detect_previous_overrun, detect_previous_overrun: config.detect_previous_overrun,
#[cfg(any(usart_v1, usart_v2))] #[cfg(any(usart_v1, usart_v2))]
buffered_sr: stm32_metapac::usart::regs::Sr(0), 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 /// Reconfigure the driver
@ -1228,26 +1236,11 @@ impl<'d, M: Mode> Uart<'d, M> {
rx_dma: Option<ChannelAndRequest<'d>>, rx_dma: Option<ChannelAndRequest<'d>>,
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
rcc::enable_and_reset::<T>();
let info = T::info(); let info = T::info();
let state = T::state(); let state = T::state();
let kernel_clock = T::frequency(); let kernel_clock = T::frequency();
info.regs.cr3().write(|w| { let mut this = Self {
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 {
tx: UartTx { tx: UartTx {
_phantom: PhantomData, _phantom: PhantomData,
info, info,
@ -1270,7 +1263,30 @@ impl<'d, M: Mode> Uart<'d, M> {
#[cfg(any(usart_v1, usart_v2))] #[cfg(any(usart_v1, usart_v2))]
buffered_sr: stm32_metapac::usart::regs::Sr(0), 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 /// Perform a blocking write