Ref count the peripheral drop

This commit is contained in:
huntc 2021-12-16 07:09:33 +11:00
parent 1374ad2ab6
commit 2493699fb3

View File

@ -309,7 +309,9 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> {
// Wait for txstopped, if needed. // Wait for txstopped, if needed.
while did_stoptx && r.events_txstopped.read().bits() == 0 {} while did_stoptx && r.events_txstopped.read().bits() == 0 {}
info!("uarte txdrop: done"); let s = T::state();
drop_tx_rx(&r, &s);
} }
} }
@ -442,16 +444,9 @@ impl<'a, T: Instance> Drop for UarteRx<'a, T> {
// Wait for rxto, if needed. // Wait for rxto, if needed.
while did_stoprx && r.events_rxto.read().bits() == 0 {} while did_stoprx && r.events_rxto.read().bits() == 0 {}
// Finally we can disable, and we do so for the peripheral let s = T::state();
// i.e. not just rx concerns.
r.enable.write(|w| w.enable().disabled());
gpio::deconfigure_pin(r.psel.rxd.read().bits()); drop_tx_rx(&r, &s);
gpio::deconfigure_pin(r.psel.txd.read().bits());
gpio::deconfigure_pin(r.psel.rts.read().bits());
gpio::deconfigure_pin(r.psel.cts.read().bits());
info!("uarte drop: done");
} }
} }
@ -508,6 +503,21 @@ pub(in crate) fn apply_workaround_for_enable_anomaly(r: &crate::pac::uarte0::Reg
} }
} }
pub(in crate) fn drop_tx_rx(r: &pac::uarte0::RegisterBlock, s: &sealed::State) {
if s.tx_rx_refcount.fetch_sub(1, Ordering::Relaxed) == 1 {
// Finally we can disable, and we do so for the peripheral
// i.e. not just rx concerns.
r.enable.write(|w| w.enable().disabled());
gpio::deconfigure_pin(r.psel.rxd.read().bits());
gpio::deconfigure_pin(r.psel.txd.read().bits());
gpio::deconfigure_pin(r.psel.rts.read().bits());
gpio::deconfigure_pin(r.psel.cts.read().bits());
info!("uarte tx and rx drop: done");
}
}
/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels, /// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
/// allowing it to implement the ReadUntilIdle trait. /// allowing it to implement the ReadUntilIdle trait.
pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
@ -667,6 +677,8 @@ impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> {
} }
pub(crate) mod sealed { pub(crate) mod sealed {
use core::sync::atomic::AtomicU8;
use embassy::waitqueue::AtomicWaker; use embassy::waitqueue::AtomicWaker;
use super::*; use super::*;
@ -674,12 +686,14 @@ pub(crate) mod sealed {
pub struct State { pub struct State {
pub endrx_waker: AtomicWaker, pub endrx_waker: AtomicWaker,
pub endtx_waker: AtomicWaker, pub endtx_waker: AtomicWaker,
pub tx_rx_refcount: AtomicU8,
} }
impl State { impl State {
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
endrx_waker: AtomicWaker::new(), endrx_waker: AtomicWaker::new(),
endtx_waker: AtomicWaker::new(), endtx_waker: AtomicWaker::new(),
tx_rx_refcount: AtomicU8::new(2),
} }
} }
} }