stm32/buffered-usart: use new_pin! and disconnect pins on drop

This commit is contained in:
Jan Špaček 2024-05-26 16:37:26 +02:00
parent ade27b7f21
commit 44e4a2c9e9
2 changed files with 65 additions and 42 deletions

View File

@ -6,7 +6,7 @@ use core::task::Poll;
use embassy_embedded_hal::SetConfig; use embassy_embedded_hal::SetConfig;
use embassy_hal_internal::atomic_ring_buffer::RingBuffer; 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; use embassy_sync::waitqueue::AtomicWaker;
#[cfg(not(any(usart_v1, usart_v2)))] #[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, clear_interrupt_flags, configure, rdr, reconfigure, sr, tdr, Config, ConfigError, CtsPin, Error, Info, Instance,
Regs, RtsPin, RxPin, TxPin, Regs, RtsPin, RxPin, TxPin,
}; };
use crate::gpio::AFType; use crate::gpio::{AFType, AnyPin, SealedPin as _};
use crate::interrupt::typelevel::Interrupt as _; use crate::interrupt::typelevel::Interrupt as _;
use crate::interrupt::{self, InterruptExt}; use crate::interrupt::{self, InterruptExt};
use crate::rcc; use crate::rcc;
@ -156,7 +156,9 @@ pub struct BufferedUartTx<'d> {
info: &'static Info, info: &'static Info,
state: &'static State, state: &'static State,
kernel_clock: Hertz, kernel_clock: Hertz,
_phantom: PhantomData<&'d mut ()>, tx: Option<PeripheralRef<'d, AnyPin>>,
cts: Option<PeripheralRef<'d, AnyPin>>,
de: Option<PeripheralRef<'d, AnyPin>>,
} }
/// Rx-only buffered UART /// Rx-only buffered UART
@ -166,7 +168,8 @@ pub struct BufferedUartRx<'d> {
info: &'static Info, info: &'static Info,
state: &'static State, state: &'static State,
kernel_clock: Hertz, kernel_clock: Hertz,
_phantom: PhantomData<&'d mut ()>, rx: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>,
} }
impl<'d> SetConfig for BufferedUart<'d> { impl<'d> SetConfig for BufferedUart<'d> {
@ -207,9 +210,17 @@ 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>(); Self::new_inner(
peri,
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) 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 /// 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], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
into_ref!(cts, rts); Self::new_inner(
peri,
rcc::enable_and_reset::<T>(); new_pin!(rx, AFType::Input),
new_pin!(tx, AFType::OutputPushPull),
rts.set_as_af(rts.af_num(), AFType::OutputPushPull); new_pin!(rts, AFType::OutputPushPull),
cts.set_as_af(cts.af_num(), AFType::Input); new_pin!(cts, AFType::Input),
T::info().regs.cr3().write(|w| { None,
w.set_rtse(true); tx_buffer,
w.set_ctse(true); rx_buffer,
}); config,
)
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config)
} }
/// Create a new bidirectional buffered UART driver with a driver-enable pin /// 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], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
into_ref!(de); Self::new_inner(
peri,
rcc::enable_and_reset::<T>(); new_pin!(rx, AFType::Input),
new_pin!(tx, AFType::OutputPushPull),
de.set_as_af(de.af_num(), AFType::OutputPushPull); None,
T::info().regs.cr3().write(|w| { None,
w.set_dem(true); new_pin!(de, AFType::OutputPushPull),
}); tx_buffer,
rx_buffer,
Self::new_inner(peri, rx, tx, tx_buffer, rx_buffer, config) config,
)
} }
fn new_inner<T: Instance>( fn new_inner<T: Instance>(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: Option<PeripheralRef<'d, AnyPin>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>,
cts: Option<PeripheralRef<'d, AnyPin>>,
de: Option<PeripheralRef<'d, AnyPin>>,
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Result<Self, ConfigError> { ) -> Result<Self, ConfigError> {
into_ref!(_peri, rx, tx); rcc::enable_and_reset::<T>();
let info = T::info(); let info = T::info();
let state = T::buffered_state(); let state = T::buffered_state();
@ -280,13 +294,15 @@ impl<'d> BufferedUart<'d> {
let len = rx_buffer.len(); let len = rx_buffer.len();
unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) }; unsafe { state.rx_buf.init(rx_buffer.as_mut_ptr(), len) };
let r = info.regs; info.regs.cr3().write(|w| {
rx.set_as_af(rx.af_num(), AFType::Input); w.set_rtse(rts.is_some());
tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 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)?; configure(info, kernel_clock, &config, true, true)?;
r.cr1().modify(|w| { info.regs.cr1().modify(|w| {
w.set_rxneie(true); w.set_rxneie(true);
w.set_idleie(true); w.set_idleie(true);
}); });
@ -301,13 +317,16 @@ impl<'d> BufferedUart<'d> {
info, info,
state, state,
kernel_clock, kernel_clock,
_phantom: PhantomData, rx,
rts,
}, },
tx: BufferedUartTx { tx: BufferedUartTx {
info, info,
state, state,
kernel_clock, 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); 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); drop_tx_rx(self.info, state);
} }
} }

View File

@ -14,7 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker;
use futures_util::future::{select, Either}; use futures_util::future::{select, Either};
use crate::dma::ChannelAndRequest; 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::typelevel::Interrupt as _;
use crate::interrupt::{self, Interrupt, InterruptExt}; use crate::interrupt::{self, Interrupt, InterruptExt};
use crate::mode::{Async, Blocking, Mode}; use crate::mode::{Async, Blocking, Mode};
@ -1233,9 +1233,8 @@ impl<'d, M: Mode> Uart<'d, M> {
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();
let r = info.regs;
r.cr3().write(|w| { info.regs.cr3().write(|w| {
w.set_rtse(rts.is_some()); w.set_rtse(rts.is_some());
w.set_ctse(cts.is_some()); w.set_ctse(cts.is_some());
#[cfg(not(any(usart_v1, usart_v2)))] #[cfg(not(any(usart_v1, usart_v2)))]