uarte: Low power wait for RX drop

This commit is contained in:
Timo Kröger 2021-01-03 17:05:04 +01:00
parent 93780fa31d
commit 0631623b51
3 changed files with 20 additions and 12 deletions

View File

@ -17,8 +17,8 @@ use crate::hal::gpio::Port as GpioPort;
use crate::hal::pac; use crate::hal::pac;
use crate::hal::prelude::*; use crate::hal::prelude::*;
use crate::hal::target_constants::EASY_DMA_SIZE; use crate::hal::target_constants::EASY_DMA_SIZE;
use crate::interrupt;
use crate::interrupt::OwnedInterrupt; use crate::interrupt::OwnedInterrupt;
use crate::{interrupt, util};
pub use crate::hal::uarte::Pins; pub use crate::hal::uarte::Pins;
// Re-export SVD variants to allow user to directly set values. // Re-export SVD variants to allow user to directly set values.
@ -275,7 +275,9 @@ where
.instance .instance
.tasks_stoptx .tasks_stoptx
.write(|w| unsafe { w.bits(1) }); .write(|w| unsafe { w.bits(1) });
T::state().tx_done.blocking_wait();
// TX is stopped almost instantly, spinning is fine.
while !T::state().tx_done.signaled() {}
} }
} }
} }
@ -342,7 +344,8 @@ where
.instance .instance
.tasks_stoprx .tasks_stoprx
.write(|w| unsafe { w.bits(1) }); .write(|w| unsafe { w.bits(1) });
T::state().rx_done.blocking_wait();
util::low_power_wait_until(|| T::state().rx_done.signaled())
} }
} }
} }
@ -361,7 +364,7 @@ where
let ptr = buf.as_ptr(); let ptr = buf.as_ptr();
let len = buf.len(); let len = buf.len();
assert!(len <= EASY_DMA_SIZE); assert!(len <= EASY_DMA_SIZE);
uarte.enable(); uarte.enable();
compiler_fence(Ordering::SeqCst); compiler_fence(Ordering::SeqCst);
@ -394,7 +397,7 @@ where
T: Instance, T: Instance,
{ {
/// Stops the ongoing reception and returns the number of bytes received. /// Stops the ongoing reception and returns the number of bytes received.
pub async fn stop(mut self) -> usize { pub async fn stop(self) -> usize {
let len = if self.uarte.rx_started() { let len = if self.uarte.rx_started() {
trace!("stoprx (stop)"); trace!("stoprx (stop)");

View File

@ -1,2 +1,12 @@
pub mod peripheral; pub mod peripheral;
pub mod ring_buffer; pub mod ring_buffer;
/// Low power blocking wait loop using WFE/SEV.
pub 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();
}

View File

@ -63,12 +63,7 @@ impl<T: Send> Signal<T> {
futures::future::poll_fn(move |cx| self.poll_wait(cx)) futures::future::poll_fn(move |cx| self.poll_wait(cx))
} }
/// Blocks until the signal has been received. pub fn signaled(&self) -> bool {
/// cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
/// Returns immediately when [`poll_wait()`] has not been called before.
pub fn blocking_wait(&self) {
while cortex_m::interrupt::free(|_| {
matches!(unsafe { &*self.state.get() }, State::Waiting(_))
}) {}
} }
} }