stm32/usart: move init code to function that's not generic in T
This commit is contained in:
parent
44e4a2c9e9
commit
664e4a5c03
@ -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)
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user