1378: Add ability to invert UART pins, take 2 r=Dirbaio a=jakewins

Same PR as before, except this now works :) 

There was a minor hiccup in the UartRx code where the rx pin got passed as the tx argument, so the invert settings didn't get applied. With this fix, my local setup at least is happily reading inverted uart data.

Co-authored-by: Jacob Davis-Hansson <jake@davis-hansson.com>
This commit is contained in:
bors[bot] 2023-04-18 15:48:47 +00:00 committed by GitHub
commit 38c5b97df0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -5,6 +5,7 @@ use embassy_hal_common::{into_ref, PeripheralRef};
use crate::dma::{AnyChannel, Channel}; use crate::dma::{AnyChannel, Channel};
use crate::gpio::sealed::Pin; use crate::gpio::sealed::Pin;
use crate::gpio::AnyPin; use crate::gpio::AnyPin;
use crate::pac::io::vals::{Inover, Outover};
use crate::{pac, peripherals, Peripheral}; use crate::{pac, peripherals, Peripheral};
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
@ -53,6 +54,14 @@ pub struct Config {
pub data_bits: DataBits, pub data_bits: DataBits,
pub stop_bits: StopBits, pub stop_bits: StopBits,
pub parity: Parity, pub parity: Parity,
/// Invert the tx pin output
pub invert_tx: bool,
/// Invert the rx pin input
pub invert_rx: bool,
// Invert the rts pin
pub invert_rts: bool,
// Invert the cts pin
pub invert_cts: bool,
} }
impl Default for Config { impl Default for Config {
@ -62,6 +71,10 @@ impl Default for Config {
data_bits: DataBits::DataBits8, data_bits: DataBits::DataBits8,
stop_bits: StopBits::STOP1, stop_bits: StopBits::STOP1,
parity: Parity::ParityNone, parity: Parity::ParityNone,
invert_rx: false,
invert_tx: false,
invert_rts: false,
invert_cts: false,
} }
} }
} }
@ -167,7 +180,7 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
} }
impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> { impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
/// Create a new DMA-enabled UART which can only send data /// Create a new DMA-enabled UART which can only recieve data
pub fn new( pub fn new(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
@ -175,7 +188,7 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(rx, rx_dma); into_ref!(rx, rx_dma);
Uart::<T, M>::init(Some(rx.map_into()), None, None, None, config); Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config);
Self::new_inner(Some(rx_dma.map_into())) Self::new_inner(Some(rx_dma.map_into()))
} }
@ -381,19 +394,47 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
let r = T::regs(); let r = T::regs();
unsafe { unsafe {
if let Some(pin) = &tx { if let Some(pin) = &tx {
pin.io().ctrl().write(|w| w.set_funcsel(2)); pin.io().ctrl().write(|w| {
w.set_funcsel(2);
w.set_outover(if config.invert_tx {
Outover::INVERT
} else {
Outover::NORMAL
});
});
pin.pad_ctrl().write(|w| w.set_ie(true)); pin.pad_ctrl().write(|w| w.set_ie(true));
} }
if let Some(pin) = &rx { if let Some(pin) = &rx {
pin.io().ctrl().write(|w| w.set_funcsel(2)); pin.io().ctrl().write(|w| {
w.set_funcsel(2);
w.set_inover(if config.invert_rx {
Inover::INVERT
} else {
Inover::NORMAL
});
});
pin.pad_ctrl().write(|w| w.set_ie(true)); pin.pad_ctrl().write(|w| w.set_ie(true));
} }
if let Some(pin) = &cts { if let Some(pin) = &cts {
pin.io().ctrl().write(|w| w.set_funcsel(2)); pin.io().ctrl().write(|w| {
w.set_funcsel(2);
w.set_inover(if config.invert_cts {
Inover::INVERT
} else {
Inover::NORMAL
});
});
pin.pad_ctrl().write(|w| w.set_ie(true)); pin.pad_ctrl().write(|w| w.set_ie(true));
} }
if let Some(pin) = &rts { if let Some(pin) = &rts {
pin.io().ctrl().write(|w| w.set_funcsel(2)); pin.io().ctrl().write(|w| {
w.set_funcsel(2);
w.set_outover(if config.invert_rts {
Outover::INVERT
} else {
Outover::NORMAL
});
});
pin.pad_ctrl().write(|w| w.set_ie(true)); pin.pad_ctrl().write(|w| w.set_ie(true));
} }