aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhuntc <[email protected]>2021-12-16 07:09:33 +1100
committerhuntc <[email protected]>2021-12-16 07:09:33 +1100
commit2493699fb339b835ad0f8ac403355eae468b73b1 (patch)
treecdd41cca6fc90f2bdd988e7403be239eea0c665a
parent1374ad2ab6a6f86a46c7c244568718a6bf8db041 (diff)
Ref count the peripheral drop
-rw-r--r--embassy-nrf/src/uarte.rs34
1 files changed, 24 insertions, 10 deletions
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index b0a28a5d6..b836395ec 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -309,7 +309,9 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> {
309 // Wait for txstopped, if needed. 309 // Wait for txstopped, if needed.
310 while did_stoptx && r.events_txstopped.read().bits() == 0 {} 310 while did_stoptx && r.events_txstopped.read().bits() == 0 {}
311 311
312 info!("uarte txdrop: done"); 312 let s = T::state();
313
314 drop_tx_rx(&r, &s);
313 } 315 }
314} 316}
315 317
@@ -442,16 +444,9 @@ impl<'a, T: Instance> Drop for UarteRx<'a, T> {
442 // Wait for rxto, if needed. 444 // Wait for rxto, if needed.
443 while did_stoprx && r.events_rxto.read().bits() == 0 {} 445 while did_stoprx && r.events_rxto.read().bits() == 0 {}
444 446
445 // Finally we can disable, and we do so for the peripheral 447 let s = T::state();
446 // i.e. not just rx concerns.
447 r.enable.write(|w| w.enable().disabled());
448
449 gpio::deconfigure_pin(r.psel.rxd.read().bits());
450 gpio::deconfigure_pin(r.psel.txd.read().bits());
451 gpio::deconfigure_pin(r.psel.rts.read().bits());
452 gpio::deconfigure_pin(r.psel.cts.read().bits());
453 448
454 info!("uarte drop: done"); 449 drop_tx_rx(&r, &s);
455 } 450 }
456} 451}
457 452
@@ -508,6 +503,21 @@ pub(in crate) fn apply_workaround_for_enable_anomaly(r: &crate::pac::uarte0::Reg
508 } 503 }
509} 504}
510 505
506pub(in crate) fn drop_tx_rx(r: &pac::uarte0::RegisterBlock, s: &sealed::State) {
507 if s.tx_rx_refcount.fetch_sub(1, Ordering::Relaxed) == 1 {
508 // Finally we can disable, and we do so for the peripheral
509 // i.e. not just rx concerns.
510 r.enable.write(|w| w.enable().disabled());
511
512 gpio::deconfigure_pin(r.psel.rxd.read().bits());
513 gpio::deconfigure_pin(r.psel.txd.read().bits());
514 gpio::deconfigure_pin(r.psel.rts.read().bits());
515 gpio::deconfigure_pin(r.psel.cts.read().bits());
516
517 info!("uarte tx and rx drop: done");
518 }
519}
520
511/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels, 521/// Interface to an UARTE peripheral that uses an additional timer and two PPI channels,
512/// allowing it to implement the ReadUntilIdle trait. 522/// allowing it to implement the ReadUntilIdle trait.
513pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> { 523pub struct UarteWithIdle<'d, U: Instance, T: TimerInstance> {
@@ -667,6 +677,8 @@ impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> {
667} 677}
668 678
669pub(crate) mod sealed { 679pub(crate) mod sealed {
680 use core::sync::atomic::AtomicU8;
681
670 use embassy::waitqueue::AtomicWaker; 682 use embassy::waitqueue::AtomicWaker;
671 683
672 use super::*; 684 use super::*;
@@ -674,12 +686,14 @@ pub(crate) mod sealed {
674 pub struct State { 686 pub struct State {
675 pub endrx_waker: AtomicWaker, 687 pub endrx_waker: AtomicWaker,
676 pub endtx_waker: AtomicWaker, 688 pub endtx_waker: AtomicWaker,
689 pub tx_rx_refcount: AtomicU8,
677 } 690 }
678 impl State { 691 impl State {
679 pub const fn new() -> Self { 692 pub const fn new() -> Self {
680 Self { 693 Self {
681 endrx_waker: AtomicWaker::new(), 694 endrx_waker: AtomicWaker::new(),
682 endtx_waker: AtomicWaker::new(), 695 endtx_waker: AtomicWaker::new(),
696 tx_rx_refcount: AtomicU8::new(2),
683 } 697 }
684 } 698 }
685 } 699 }