stm32/usart: configurable readback in half-duplex mode
This commit is contained in:
parent
6789b5141f
commit
2ec81419fa
@ -125,6 +125,33 @@ pub enum StopBits {
|
|||||||
STOP1P5,
|
STOP1P5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
/// Enables or disables receiver so written data are read back in half-duplex mode
|
||||||
|
pub enum HalfDuplexReadback {
|
||||||
|
/// Disables receiver so written data are not read back
|
||||||
|
NoReadback,
|
||||||
|
/// Enables receiver so written data are read back
|
||||||
|
Readback,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
/// Duplex mode
|
||||||
|
pub enum Duplex {
|
||||||
|
/// Full duplex
|
||||||
|
Full,
|
||||||
|
/// Half duplex with possibility to read back written data
|
||||||
|
Half(HalfDuplexReadback),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Duplex {
|
||||||
|
/// Returns true if half-duplex
|
||||||
|
fn is_half(&self) -> bool {
|
||||||
|
matches!(self, Duplex::Half(_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@ -181,7 +208,7 @@ pub struct Config {
|
|||||||
pub rx_pull: Pull,
|
pub rx_pull: Pull,
|
||||||
|
|
||||||
// private: set by new_half_duplex, not by the user.
|
// private: set by new_half_duplex, not by the user.
|
||||||
half_duplex: bool,
|
duplex: Duplex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@ -220,7 +247,7 @@ impl Default for Config {
|
|||||||
#[cfg(any(usart_v3, usart_v4))]
|
#[cfg(any(usart_v3, usart_v4))]
|
||||||
invert_rx: false,
|
invert_rx: false,
|
||||||
rx_pull: Pull::None,
|
rx_pull: Pull::None,
|
||||||
half_duplex: false,
|
duplex: Duplex::Full,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,6 +335,7 @@ pub struct UartTx<'d, M: Mode> {
|
|||||||
cts: Option<PeripheralRef<'d, AnyPin>>,
|
cts: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
de: Option<PeripheralRef<'d, AnyPin>>,
|
de: Option<PeripheralRef<'d, AnyPin>>,
|
||||||
tx_dma: Option<ChannelAndRequest<'d>>,
|
tx_dma: Option<ChannelAndRequest<'d>>,
|
||||||
|
duplex: Duplex,
|
||||||
_phantom: PhantomData<M>,
|
_phantom: PhantomData<M>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,7 +441,7 @@ impl<'d> UartTx<'d, Async> {
|
|||||||
let mut cr1 = r.cr1().read();
|
let mut cr1 = r.cr1().read();
|
||||||
if r.cr3().read().hdsel() && !cr1.te() {
|
if r.cr3().read().hdsel() && !cr1.te() {
|
||||||
cr1.set_te(true);
|
cr1.set_te(true);
|
||||||
cr1.set_re(false);
|
cr1.set_re(self.duplex == Duplex::Half(HalfDuplexReadback::Readback));
|
||||||
r.cr1().write_value(cr1);
|
r.cr1().write_value(cr1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,6 +513,7 @@ impl<'d, M: Mode> UartTx<'d, M> {
|
|||||||
cts,
|
cts,
|
||||||
de: None,
|
de: None,
|
||||||
tx_dma,
|
tx_dma,
|
||||||
|
duplex: config.duplex,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
};
|
};
|
||||||
this.enable_and_configure(&config)?;
|
this.enable_and_configure(&config)?;
|
||||||
@ -519,7 +548,7 @@ impl<'d, M: Mode> UartTx<'d, M> {
|
|||||||
let mut cr1 = r.cr1().read();
|
let mut cr1 = r.cr1().read();
|
||||||
if r.cr3().read().hdsel() && !cr1.te() {
|
if r.cr3().read().hdsel() && !cr1.te() {
|
||||||
cr1.set_te(true);
|
cr1.set_te(true);
|
||||||
cr1.set_re(false);
|
cr1.set_re(self.duplex == Duplex::Half(HalfDuplexReadback::Readback));
|
||||||
r.cr1().write_value(cr1);
|
r.cr1().write_value(cr1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1149,13 +1178,14 @@ impl<'d> Uart<'d, Async> {
|
|||||||
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||||
mut config: Config,
|
mut config: Config,
|
||||||
|
readback: HalfDuplexReadback,
|
||||||
half_duplex: HalfDuplexConfig,
|
half_duplex: HalfDuplexConfig,
|
||||||
) -> Result<Self, ConfigError> {
|
) -> Result<Self, ConfigError> {
|
||||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||||
{
|
{
|
||||||
config.swap_rx_tx = false;
|
config.swap_rx_tx = false;
|
||||||
}
|
}
|
||||||
config.half_duplex = true;
|
config.duplex = Duplex::Half(readback);
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
peri,
|
peri,
|
||||||
@ -1188,10 +1218,11 @@ impl<'d> Uart<'d, Async> {
|
|||||||
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
|
||||||
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
|
||||||
mut config: Config,
|
mut config: Config,
|
||||||
|
readback: HalfDuplexReadback,
|
||||||
half_duplex: HalfDuplexConfig,
|
half_duplex: HalfDuplexConfig,
|
||||||
) -> Result<Self, ConfigError> {
|
) -> Result<Self, ConfigError> {
|
||||||
config.swap_rx_tx = true;
|
config.swap_rx_tx = true;
|
||||||
config.half_duplex = true;
|
config.duplex = Duplex::Half(readback);
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
peri,
|
peri,
|
||||||
@ -1307,13 +1338,14 @@ impl<'d> Uart<'d, Blocking> {
|
|||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
|
||||||
mut config: Config,
|
mut config: Config,
|
||||||
|
readback: HalfDuplexReadback,
|
||||||
half_duplex: HalfDuplexConfig,
|
half_duplex: HalfDuplexConfig,
|
||||||
) -> Result<Self, ConfigError> {
|
) -> Result<Self, ConfigError> {
|
||||||
#[cfg(not(any(usart_v1, usart_v2)))]
|
#[cfg(not(any(usart_v1, usart_v2)))]
|
||||||
{
|
{
|
||||||
config.swap_rx_tx = false;
|
config.swap_rx_tx = false;
|
||||||
}
|
}
|
||||||
config.half_duplex = true;
|
config.duplex = Duplex::Half(readback);
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
peri,
|
peri,
|
||||||
@ -1343,10 +1375,11 @@ impl<'d> Uart<'d, Blocking> {
|
|||||||
peri: impl Peripheral<P = T> + 'd,
|
peri: impl Peripheral<P = T> + 'd,
|
||||||
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
|
||||||
mut config: Config,
|
mut config: Config,
|
||||||
|
readback: HalfDuplexReadback,
|
||||||
half_duplex: HalfDuplexConfig,
|
half_duplex: HalfDuplexConfig,
|
||||||
) -> Result<Self, ConfigError> {
|
) -> Result<Self, ConfigError> {
|
||||||
config.swap_rx_tx = true;
|
config.swap_rx_tx = true;
|
||||||
config.half_duplex = true;
|
config.duplex = Duplex::Half(readback);
|
||||||
|
|
||||||
Self::new_inner(
|
Self::new_inner(
|
||||||
peri,
|
peri,
|
||||||
@ -1388,6 +1421,7 @@ impl<'d, M: Mode> Uart<'d, M> {
|
|||||||
cts,
|
cts,
|
||||||
de,
|
de,
|
||||||
tx_dma,
|
tx_dma,
|
||||||
|
duplex: config.duplex,
|
||||||
},
|
},
|
||||||
rx: UartRx {
|
rx: UartRx {
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
@ -1667,14 +1701,14 @@ fn configure(
|
|||||||
r.cr3().modify(|w| {
|
r.cr3().modify(|w| {
|
||||||
#[cfg(not(usart_v1))]
|
#[cfg(not(usart_v1))]
|
||||||
w.set_onebit(config.assume_noise_free);
|
w.set_onebit(config.assume_noise_free);
|
||||||
w.set_hdsel(config.half_duplex);
|
w.set_hdsel(config.duplex.is_half());
|
||||||
});
|
});
|
||||||
|
|
||||||
r.cr1().write(|w| {
|
r.cr1().write(|w| {
|
||||||
// enable uart
|
// enable uart
|
||||||
w.set_ue(true);
|
w.set_ue(true);
|
||||||
|
|
||||||
if config.half_duplex {
|
if config.duplex.is_half() {
|
||||||
// The te and re bits will be set by write, read and flush methods.
|
// The te and re bits will be set by write, read and flush methods.
|
||||||
// Receiver should be enabled by default for Half-Duplex.
|
// Receiver should be enabled by default for Half-Duplex.
|
||||||
w.set_te(false);
|
w.set_te(false);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user