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::prelude::*;
use crate::hal::target_constants::EASY_DMA_SIZE;
use crate::interrupt;
use crate::interrupt::OwnedInterrupt;
use crate::{interrupt, util};
pub use crate::hal::uarte::Pins;
// Re-export SVD variants to allow user to directly set values.
@ -275,7 +275,9 @@ where
.instance
.tasks_stoptx
.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
.tasks_stoprx
.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 len = buf.len();
assert!(len <= EASY_DMA_SIZE);
uarte.enable();
compiler_fence(Ordering::SeqCst);
@ -394,7 +397,7 @@ where
T: Instance,
{
/// 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() {
trace!("stoprx (stop)");

View File

@ -1,2 +1,12 @@
pub mod peripheral;
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))
}
/// Blocks until the signal has been received.
///
/// 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(_))
}) {}
pub fn signaled(&self) -> bool {
cortex_m::interrupt::free(|_| matches!(unsafe { &*self.state.get() }, State::Signaled(_)))
}
}