diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-08-31 00:31:38 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-08-31 00:31:38 +0000 |
| commit | 38900a7fb0723e5a6bef8a8cd201b11c1f095ac9 (patch) | |
| tree | 8910d03d9f3d5b8d19f4e0dc4e1088d6cf2b349b | |
| parent | fe08bdf0d81e784c3af642128b91a53514b79a63 (diff) | |
| parent | 30641d05640a7a3cd4d71c70c09694a3eef825e0 (diff) | |
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 <[email protected]>
| -rw-r--r-- | embassy-nrf/src/saadc.rs | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 7dc66349e..9bc89eb38 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | 3 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 4 | use core::task::Poll; | 4 | use core::task::Poll; |
| 5 | 5 | ||
| 6 | use embassy_hal_common::drop::OnDrop; | ||
| 6 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; | 7 | use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; |
| 7 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 8 | use futures::future::poll_fn; | 9 | use futures::future::poll_fn; |
| @@ -219,7 +220,13 @@ impl<'d, const N: usize> Saadc<'d, N> { | |||
| 219 | } | 220 | } |
| 220 | 221 | ||
| 221 | /// One shot sampling. The buffer must be the same size as the number of channels configured. | 222 | /// One shot sampling. The buffer must be the same size as the number of channels configured. |
| 223 | /// The sampling is stopped prior to returning in order to reduce power consumption (power | ||
| 224 | /// consumption remains higher if sampling is not stopped explicitly). Cancellation will | ||
| 225 | /// also cause the sampling to be stopped. | ||
| 222 | pub async fn sample(&mut self, buf: &mut [i16; N]) { | 226 | pub async fn sample(&mut self, buf: &mut [i16; N]) { |
| 227 | // In case the future is dropped, stop the task and wait for it to end. | ||
| 228 | OnDrop::new(Self::stop_sampling_immediately); | ||
| 229 | |||
| 223 | let r = Self::regs(); | 230 | let r = Self::regs(); |
| 224 | 231 | ||
| 225 | // Set up the DMA | 232 | // Set up the DMA |
| @@ -270,6 +277,12 @@ impl<'d, const N: usize> Saadc<'d, N> { | |||
| 270 | /// taken to acquire the samples into a single buffer. You should measure the | 277 | /// taken to acquire the samples into a single buffer. You should measure the |
| 271 | /// time taken by the callback and set the sample buffer size accordingly. | 278 | /// time taken by the callback and set the sample buffer size accordingly. |
| 272 | /// Exceeding this time can lead to samples becoming dropped. | 279 | /// Exceeding this time can lead to samples becoming dropped. |
| 280 | /// | ||
| 281 | /// The sampling is stopped prior to returning in order to reduce power consumption (power | ||
| 282 | /// consumption remains higher if sampling is not stopped explicitly), and to | ||
| 283 | /// free the buffers from being used by the peripheral. Cancellation will | ||
| 284 | /// also cause the sampling to be stopped. | ||
| 285 | |||
| 273 | pub async fn run_task_sampler<S, T: TimerInstance, const N0: usize>( | 286 | pub async fn run_task_sampler<S, T: TimerInstance, const N0: usize>( |
| 274 | &mut self, | 287 | &mut self, |
| 275 | timer: &mut T, | 288 | timer: &mut T, |
| @@ -321,6 +334,9 @@ impl<'d, const N: usize> Saadc<'d, N> { | |||
| 321 | I: FnMut(), | 334 | I: FnMut(), |
| 322 | S: FnMut(&[[i16; N]]) -> SamplerState, | 335 | S: FnMut(&[[i16; N]]) -> SamplerState, |
| 323 | { | 336 | { |
| 337 | // In case the future is dropped, stop the task and wait for it to end. | ||
| 338 | OnDrop::new(Self::stop_sampling_immediately); | ||
| 339 | |||
| 324 | let r = Self::regs(); | 340 | let r = Self::regs(); |
| 325 | 341 | ||
| 326 | // Establish mode and sample rate | 342 | // Establish mode and sample rate |
| @@ -404,6 +420,19 @@ impl<'d, const N: usize> Saadc<'d, N> { | |||
| 404 | }) | 420 | }) |
| 405 | .await; | 421 | .await; |
| 406 | } | 422 | } |
| 423 | |||
| 424 | // Stop sampling and wait for it to stop in a blocking fashion | ||
| 425 | fn stop_sampling_immediately() { | ||
| 426 | let r = Self::regs(); | ||
| 427 | |||
| 428 | compiler_fence(Ordering::SeqCst); | ||
| 429 | |||
| 430 | r.events_stopped.reset(); | ||
| 431 | r.tasks_stop.write(|w| unsafe { w.bits(1) }); | ||
| 432 | |||
| 433 | while r.events_stopped.read().bits() == 0 {} | ||
| 434 | r.events_stopped.reset(); | ||
| 435 | } | ||
| 407 | } | 436 | } |
| 408 | 437 | ||
| 409 | impl<'d> Saadc<'d, 1> { | 438 | impl<'d> Saadc<'d, 1> { |
