aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf/src/buffered_uarte.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-09-23 11:58:43 +0000
committerGitHub <[email protected]>2022-09-23 11:58:43 +0000
commiteeb1515e9fd093e4a9797abac25ca657e1e35dc3 (patch)
tree88b4d15f21f883041c8bca2a62420f431af006de /embassy-nrf/src/buffered_uarte.rs
parentdacbc9acd5969d3ef0dda8825c960e909008ce83 (diff)
parentb4f2c2a05ebe736de1faaf5541f1913ac3c4eff6 (diff)
Merge #958
958: Implement proper `Drop` for `BufferedUarte` r=lulf a=ZoeyR The drop method in `BufferedUarte` was prone to hanging indefinitely and also didn't actually disable the peripheral. I mostly copied over the drop method from `Uarte` with some modifications since `BufferedUarte` could have a transmit lasting indefinitely. Co-authored-by: Zoey Riordan <[email protected]>
Diffstat (limited to 'embassy-nrf/src/buffered_uarte.rs')
-rw-r--r--embassy-nrf/src/buffered_uarte.rs42
1 files changed, 17 insertions, 25 deletions
diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs
index fec875cb8..6e85a159f 100644
--- a/embassy-nrf/src/buffered_uarte.rs
+++ b/embassy-nrf/src/buffered_uarte.rs
@@ -26,7 +26,7 @@ use embassy_sync::waitqueue::WakerRegistration;
26// Re-export SVD variants to allow user to directly set values 26// Re-export SVD variants to allow user to directly set values
27pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; 27pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
28 28
29use crate::gpio::Pin as GpioPin; 29use crate::gpio::{self, Pin as GpioPin};
30use crate::interrupt::InterruptExt; 30use crate::interrupt::InterruptExt;
31use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; 31use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
32use crate::timer::{Frequency, Instance as TimerInstance, Timer}; 32use crate::timer::{Frequency, Instance as TimerInstance, Timer};
@@ -428,21 +428,23 @@ impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> {
428 fn drop(&mut self) { 428 fn drop(&mut self) {
429 let r = U::regs(); 429 let r = U::regs();
430 430
431 // TODO this probably deadlocks. do like Uarte instead.
432
433 self.timer.stop(); 431 self.timer.stop();
434 if let RxState::Receiving = self.rx_state { 432
435 r.tasks_stoprx.write(|w| unsafe { w.bits(1) }); 433 r.inten.reset();
436 } 434 r.events_rxto.reset();
437 if let TxState::Transmitting(_) = self.tx_state { 435 r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
438 r.tasks_stoptx.write(|w| unsafe { w.bits(1) }); 436 r.events_txstopped.reset();
439 } 437 r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
440 if let RxState::Receiving = self.rx_state { 438
441 low_power_wait_until(|| r.events_endrx.read().bits() == 1); 439 while r.events_txstopped.read().bits() == 0 {}
442 } 440 while r.events_rxto.read().bits() == 0 {}
443 if let TxState::Transmitting(_) = self.tx_state { 441
444 low_power_wait_until(|| r.events_endtx.read().bits() == 1); 442 r.enable.write(|w| w.enable().disabled());
445 } 443
444 gpio::deconfigure_pin(r.psel.rxd.read().bits());
445 gpio::deconfigure_pin(r.psel.txd.read().bits());
446 gpio::deconfigure_pin(r.psel.rts.read().bits());
447 gpio::deconfigure_pin(r.psel.cts.read().bits());
446 } 448 }
447} 449}
448 450
@@ -548,13 +550,3 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a,
548 trace!("irq: end"); 550 trace!("irq: end");
549 } 551 }
550} 552}
551
552/// Low power blocking wait loop using WFE/SEV.
553fn low_power_wait_until(mut condition: impl FnMut() -> bool) {
554 while !condition() {
555 // WFE might "eat" an event that would have otherwise woken the executor.
556 cortex_m::asm::wfe();
557 }
558 // Retrigger an event to be transparent to the executor.
559 cortex_m::asm::sev();
560}