From f6cac6944cb636f15d9fd5baa4c19120f819edf9 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 21 May 2021 13:06:28 +0200 Subject: [PATCH 1/3] Makes it possible to use the ADC with different analog pins --- embassy-nrf/src/saadc.rs | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index c1afd00d..660096b4 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -30,9 +30,9 @@ pub use saadc::{ pub enum Error {} /// One-shot saadc. Continuous sample mode TODO. -pub struct OneShot<'d, T: PositivePin> { +pub struct OneShot<'d> { irq: interrupt::SAADC, - phantom: PhantomData<(&'d mut peripherals::SAADC, &'d mut T)>, + phantom: PhantomData<(&'d mut peripherals::SAADC)>, } /// Used to configure the SAADC peripheral. @@ -66,14 +66,13 @@ impl Default for Config { } } -impl<'d, T: PositivePin> OneShot<'d, T> { +impl<'d> OneShot<'d> { pub fn new( _saadc: impl Unborrow + 'd, irq: impl Unborrow + 'd, - positive_pin: impl Unborrow + 'd, config: Config, ) -> Self { - unborrow!(irq, positive_pin); + unborrow!(irq); let r = unsafe { &*SAADC::ptr() }; @@ -106,11 +105,6 @@ impl<'d, T: PositivePin> OneShot<'d, T> { w }); - // Set positive channel - r.ch[0] - .pselp - .write(|w| w.pselp().variant(positive_pin.channel())); - // Disable all events interrupts r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); @@ -125,7 +119,7 @@ impl<'d, T: PositivePin> OneShot<'d, T> { } } -impl<'d, T: PositivePin> Drop for OneShot<'d, T> { +impl<'d> Drop for OneShot<'d> { fn drop(&mut self) { let r = self.regs(); r.enable.write(|w| w.enable().disabled()); @@ -133,21 +127,25 @@ impl<'d, T: PositivePin> Drop for OneShot<'d, T> { } pub trait Sample { - type SampleFuture<'a>: Future + 'a + type SampleFuture<'a, T>: Future + 'a where + T: PositivePin + 'a, Self: 'a; - fn sample<'a>(&'a mut self) -> Self::SampleFuture<'a>; + fn sample<'a, T: PositivePin>(&'a mut self, pin: &'a T) -> Self::SampleFuture<'a, T>; } -impl<'d, T: PositivePin> Sample for OneShot<'d, T> { +impl<'d> Sample for OneShot<'d> { #[rustfmt::skip] - type SampleFuture<'a> where Self: 'a = impl Future + 'a; + type SampleFuture<'a, T> where Self: 'a, T: PositivePin + 'a = impl Future + 'a; - fn sample<'a>(&'a mut self) -> Self::SampleFuture<'a> { + fn sample<'a, T: PositivePin>(&'a mut self, pin: &'a T) -> Self::SampleFuture<'a, T> { async move { let r = self.regs(); + // Set positive channel + r.ch[0].pselp.write(|w| w.pselp().variant(pin.channel())); + // Set up the DMA let mut val: i16 = 0; r.result From 13524080d337d0b767c6c3e7df18af02919c1155 Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Sat, 22 May 2021 13:23:09 +0200 Subject: [PATCH 2/3] Avoid using full GAT --- embassy-nrf/src/saadc.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 660096b4..03f21d82 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -127,24 +127,24 @@ impl<'d> Drop for OneShot<'d> { } pub trait Sample { - type SampleFuture<'a, T>: Future + 'a + type SampleFuture<'a>: Future + 'a where - T: PositivePin + 'a, Self: 'a; - fn sample<'a, T: PositivePin>(&'a mut self, pin: &'a T) -> Self::SampleFuture<'a, T>; + fn sample<'a>(&'a mut self, pin: &mut dyn PositivePin) -> Self::SampleFuture<'a>; } impl<'d> Sample for OneShot<'d> { #[rustfmt::skip] - type SampleFuture<'a, T> where Self: 'a, T: PositivePin + 'a = impl Future + 'a; + type SampleFuture<'a> where Self: 'a = impl Future + 'a; - fn sample<'a, T: PositivePin>(&'a mut self, pin: &'a T) -> Self::SampleFuture<'a, T> { + fn sample<'a>(&'a mut self, pin: &mut dyn PositivePin) -> Self::SampleFuture<'a> { + let channel = pin.channel(); async move { let r = self.regs(); // Set positive channel - r.ch[0].pselp.write(|w| w.pselp().variant(pin.channel())); + r.ch[0].pselp.write(|w| w.pselp().variant(channel)); // Set up the DMA let mut val: i16 = 0; @@ -188,7 +188,7 @@ impl<'d> Sample for OneShot<'d> { /// A pin that can be used as the positive end of a ADC differential in the SAADC periperhal. /// /// Currently negative is always shorted to ground (0V). -pub trait PositivePin: Unborrow { +pub trait PositivePin { fn channel(&self) -> PositiveChannel; } From 55c3ba2a5fb2ffddca187c0b04ad353433508426 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 22 May 2021 15:42:14 +0200 Subject: [PATCH 3/3] nrf/saadc: do not use dyn --- embassy-nrf/src/saadc.rs | 93 ++++++++++++++++++++-------------------- 1 file changed, 47 insertions(+), 46 deletions(-) diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 03f21d82..edb8aa21 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -32,7 +32,7 @@ pub enum Error {} /// One-shot saadc. Continuous sample mode TODO. pub struct OneShot<'d> { irq: interrupt::SAADC, - phantom: PhantomData<(&'d mut peripherals::SAADC)>, + phantom: PhantomData<&'d mut peripherals::SAADC>, } /// Used to configure the SAADC peripheral. @@ -117,6 +117,49 @@ impl<'d> OneShot<'d> { fn regs(&self) -> &saadc::RegisterBlock { unsafe { &*SAADC::ptr() } } + + async fn sample_inner(&mut self, pin: PositiveChannel) -> i16 { + let r = self.regs(); + + // Set positive channel + r.ch[0].pselp.write(|w| w.pselp().variant(pin)); + + // Set up the DMA + let mut val: i16 = 0; + r.result + .ptr + .write(|w| unsafe { w.ptr().bits(((&mut val) as *mut _) as u32) }); + r.result.maxcnt.write(|w| unsafe { w.maxcnt().bits(1) }); + + // Reset and enable the end event + r.events_end.reset(); + r.intenset.write(|w| w.end().set()); + + // Don't reorder the ADC start event before the previous writes. Hopefully self + // wouldn't happen anyway. + compiler_fence(Ordering::SeqCst); + + r.tasks_start.write(|w| unsafe { w.bits(1) }); + r.tasks_sample.write(|w| unsafe { w.bits(1) }); + + // Wait for 'end' event. + poll_fn(|cx| { + let r = self.regs(); + + if r.events_end.read().bits() != 0 { + r.events_end.reset(); + return Poll::Ready(()); + } + + wake_on_interrupt(&mut self.irq, cx.waker()); + + Poll::Pending + }) + .await; + + // The DMA wrote the sampled value to `val`. + val + } } impl<'d> Drop for OneShot<'d> { @@ -131,57 +174,15 @@ pub trait Sample { where Self: 'a; - fn sample<'a>(&'a mut self, pin: &mut dyn PositivePin) -> Self::SampleFuture<'a>; + fn sample<'a, T: PositivePin>(&'a mut self, pin: &mut T) -> Self::SampleFuture<'a>; } impl<'d> Sample for OneShot<'d> { #[rustfmt::skip] type SampleFuture<'a> where Self: 'a = impl Future + 'a; - fn sample<'a>(&'a mut self, pin: &mut dyn PositivePin) -> Self::SampleFuture<'a> { - let channel = pin.channel(); - async move { - let r = self.regs(); - - // Set positive channel - r.ch[0].pselp.write(|w| w.pselp().variant(channel)); - - // Set up the DMA - let mut val: i16 = 0; - r.result - .ptr - .write(|w| unsafe { w.ptr().bits(((&mut val) as *mut _) as u32) }); - r.result.maxcnt.write(|w| unsafe { w.maxcnt().bits(1) }); - - // Reset and enable the end event - r.events_end.reset(); - r.intenset.write(|w| w.end().set()); - - // Don't reorder the ADC start event before the previous writes. Hopefully self - // wouldn't happen anyway. - compiler_fence(Ordering::SeqCst); - - r.tasks_start.write(|w| unsafe { w.bits(1) }); - r.tasks_sample.write(|w| unsafe { w.bits(1) }); - - // Wait for 'end' event. - poll_fn(|cx| { - let r = self.regs(); - - if r.events_end.read().bits() != 0 { - r.events_end.reset(); - return Poll::Ready(()); - } - - wake_on_interrupt(&mut self.irq, cx.waker()); - - Poll::Pending - }) - .await; - - // The DMA wrote the sampled value to `val`. - val - } + fn sample<'a, T: PositivePin>(&'a mut self, pin: &mut T) -> Self::SampleFuture<'a> { + self.sample_inner(pin.channel()) } }