diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-09-23 11:58:43 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-09-23 11:58:43 +0000 |
| commit | eeb1515e9fd093e4a9797abac25ca657e1e35dc3 (patch) | |
| tree | 88b4d15f21f883041c8bca2a62420f431af006de /embassy-nrf/src | |
| parent | dacbc9acd5969d3ef0dda8825c960e909008ce83 (diff) | |
| parent | b4f2c2a05ebe736de1faaf5541f1913ac3c4eff6 (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')
| -rw-r--r-- | embassy-nrf/src/buffered_uarte.rs | 42 |
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 |
| 27 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; | 27 | pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; |
| 28 | 28 | ||
| 29 | use crate::gpio::Pin as GpioPin; | 29 | use crate::gpio::{self, Pin as GpioPin}; |
| 30 | use crate::interrupt::InterruptExt; | 30 | use crate::interrupt::InterruptExt; |
| 31 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; | 31 | use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; |
| 32 | use crate::timer::{Frequency, Instance as TimerInstance, Timer}; | 32 | use 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. | ||
| 553 | fn 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 | } | ||
