Merge #928
928: Ensure that the sampling is stopped r=Dirbaio a=huntc Ensures that nRF saadc sampling is stopped and is awaited prior to exiting the two sampling methods. Not doing so causes a potential power drain and the potential for dropped buffer writes when having finished continuous sampling. Co-authored-by: huntc <huntchr@gmail.com>
This commit is contained in:
commit
38900a7fb0
1 changed files with 29 additions and 0 deletions
|
@ -3,6 +3,7 @@
|
|||
use core::sync::atomic::{compiler_fence, Ordering};
|
||||
use core::task::Poll;
|
||||
|
||||
use embassy_hal_common::drop::OnDrop;
|
||||
use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef};
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
use futures::future::poll_fn;
|
||||
|
@ -219,7 +220,13 @@ impl<'d, const N: usize> Saadc<'d, N> {
|
|||
}
|
||||
|
||||
/// One shot sampling. The buffer must be the same size as the number of channels configured.
|
||||
/// The sampling is stopped prior to returning in order to reduce power consumption (power
|
||||
/// consumption remains higher if sampling is not stopped explicitly). Cancellation will
|
||||
/// also cause the sampling to be stopped.
|
||||
pub async fn sample(&mut self, buf: &mut [i16; N]) {
|
||||
// In case the future is dropped, stop the task and wait for it to end.
|
||||
OnDrop::new(Self::stop_sampling_immediately);
|
||||
|
||||
let r = Self::regs();
|
||||
|
||||
// Set up the DMA
|
||||
|
@ -270,6 +277,12 @@ impl<'d, const N: usize> Saadc<'d, N> {
|
|||
/// taken to acquire the samples into a single buffer. You should measure the
|
||||
/// time taken by the callback and set the sample buffer size accordingly.
|
||||
/// Exceeding this time can lead to samples becoming dropped.
|
||||
///
|
||||
/// The sampling is stopped prior to returning in order to reduce power consumption (power
|
||||
/// consumption remains higher if sampling is not stopped explicitly), and to
|
||||
/// free the buffers from being used by the peripheral. Cancellation will
|
||||
/// also cause the sampling to be stopped.
|
||||
|
||||
pub async fn run_task_sampler<S, T: TimerInstance, const N0: usize>(
|
||||
&mut self,
|
||||
timer: &mut T,
|
||||
|
@ -321,6 +334,9 @@ impl<'d, const N: usize> Saadc<'d, N> {
|
|||
I: FnMut(),
|
||||
S: FnMut(&[[i16; N]]) -> SamplerState,
|
||||
{
|
||||
// In case the future is dropped, stop the task and wait for it to end.
|
||||
OnDrop::new(Self::stop_sampling_immediately);
|
||||
|
||||
let r = Self::regs();
|
||||
|
||||
// Establish mode and sample rate
|
||||
|
@ -404,6 +420,19 @@ impl<'d, const N: usize> Saadc<'d, N> {
|
|||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
// Stop sampling and wait for it to stop in a blocking fashion
|
||||
fn stop_sampling_immediately() {
|
||||
let r = Self::regs();
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
r.events_stopped.reset();
|
||||
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||
|
||||
while r.events_stopped.read().bits() == 0 {}
|
||||
r.events_stopped.reset();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Saadc<'d, 1> {
|
||||
|
|
Loading…
Reference in a new issue