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 <zoey@dos.cafe>
This commit is contained in:
commit
eeb1515e9f
@ -26,7 +26,7 @@ use embassy_sync::waitqueue::WakerRegistration;
|
|||||||
// Re-export SVD variants to allow user to directly set values
|
// Re-export SVD variants to allow user to directly set values
|
||||||
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
|
pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity};
|
||||||
|
|
||||||
use crate::gpio::Pin as GpioPin;
|
use crate::gpio::{self, Pin as GpioPin};
|
||||||
use crate::interrupt::InterruptExt;
|
use crate::interrupt::InterruptExt;
|
||||||
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
|
||||||
use crate::timer::{Frequency, Instance as TimerInstance, Timer};
|
use crate::timer::{Frequency, Instance as TimerInstance, Timer};
|
||||||
@ -428,21 +428,23 @@ impl<'a, U: UarteInstance, T: TimerInstance> Drop for StateInner<'a, U, T> {
|
|||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let r = U::regs();
|
let r = U::regs();
|
||||||
|
|
||||||
// TODO this probably deadlocks. do like Uarte instead.
|
|
||||||
|
|
||||||
self.timer.stop();
|
self.timer.stop();
|
||||||
if let RxState::Receiving = self.rx_state {
|
|
||||||
r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
|
r.inten.reset();
|
||||||
}
|
r.events_rxto.reset();
|
||||||
if let TxState::Transmitting(_) = self.tx_state {
|
r.tasks_stoprx.write(|w| unsafe { w.bits(1) });
|
||||||
r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
|
r.events_txstopped.reset();
|
||||||
}
|
r.tasks_stoptx.write(|w| unsafe { w.bits(1) });
|
||||||
if let RxState::Receiving = self.rx_state {
|
|
||||||
low_power_wait_until(|| r.events_endrx.read().bits() == 1);
|
while r.events_txstopped.read().bits() == 0 {}
|
||||||
}
|
while r.events_rxto.read().bits() == 0 {}
|
||||||
if let TxState::Transmitting(_) = self.tx_state {
|
|
||||||
low_power_wait_until(|| r.events_endtx.read().bits() == 1);
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,13 +550,3 @@ impl<'a, U: UarteInstance, T: TimerInstance> PeripheralState for StateInner<'a,
|
|||||||
trace!("irq: end");
|
trace!("irq: end");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Low power blocking wait loop using WFE/SEV.
|
|
||||||
fn low_power_wait_until(mut condition: impl FnMut() -> bool) {
|
|
||||||
while !condition() {
|
|
||||||
// WFE might "eat" an event that would have otherwise woken the executor.
|
|
||||||
cortex_m::asm::wfe();
|
|
||||||
}
|
|
||||||
// Retrigger an event to be transparent to the executor.
|
|
||||||
cortex_m::asm::sev();
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user