aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/adc/f3.rs65
-rw-r--r--embassy-stm32/src/adc/mod.rs39
-rw-r--r--examples/stm32f334/src/bin/adc.rs23
3 files changed, 109 insertions, 18 deletions
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
index b39d6ac8e..5d2ea1daa 100644
--- a/embassy-stm32/src/adc/f3.rs
+++ b/embassy-stm32/src/adc/f3.rs
@@ -1,14 +1,36 @@
1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::task::Poll;
4
1use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 6use embedded_hal_02::blocking::delay::DelayUs;
3 7
4use crate::adc::{Adc, AdcPin, Instance, SampleTime}; 8use crate::adc::{Adc, AdcPin, Instance, SampleTime};
9use crate::interrupt::typelevel::Interrupt;
5use crate::time::Hertz; 10use crate::time::Hertz;
6use crate::Peripheral; 11use crate::{interrupt, Peripheral};
7 12
8pub const VDDA_CALIB_MV: u32 = 3300; 13pub const VDDA_CALIB_MV: u32 = 3300;
9pub const ADC_MAX: u32 = (1 << 12) - 1; 14pub const ADC_MAX: u32 = (1 << 12) - 1;
10pub const VREF_INT: u32 = 1230; 15pub const VREF_INT: u32 = 1230;
11 16
17/// Interrupt handler.
18pub struct InterruptHandler<T: Instance> {
19 _phantom: PhantomData<T>,
20}
21
22impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
23 unsafe fn on_interrupt() {
24 if T::regs().isr().read().eoc() {
25 T::regs().ier().modify(|w| w.set_eocie(false));
26 } else {
27 return;
28 }
29
30 T::state().waker.wake();
31 }
32}
33
12pub struct Vref; 34pub struct Vref;
13impl<T: Instance> AdcPin<T> for Vref {} 35impl<T: Instance> AdcPin<T> for Vref {}
14impl<T: Instance> super::sealed::AdcPin<T> for Vref { 36impl<T: Instance> super::sealed::AdcPin<T> for Vref {
@@ -17,6 +39,13 @@ impl<T: Instance> super::sealed::AdcPin<T> for Vref {
17 } 39 }
18} 40}
19 41
42impl Vref {
43 /// The value that vref would be if vdda was at 3300mv
44 pub fn value(&self) -> u16 {
45 crate::pac::VREFINTCAL.data().read().value()
46 }
47}
48
20pub struct Temperature; 49pub struct Temperature;
21impl<T: Instance> AdcPin<T> for Temperature {} 50impl<T: Instance> AdcPin<T> for Temperature {}
22impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 51impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
@@ -26,7 +55,11 @@ impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
26} 55}
27 56
28impl<'d, T: Instance> Adc<'d, T> { 57impl<'d, T: Instance> Adc<'d, T> {
29 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 58 pub fn new(
59 adc: impl Peripheral<P = T> + 'd,
60 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
61 delay: &mut impl DelayUs<u32>,
62 ) -> Self {
30 use crate::pac::adc::vals; 63 use crate::pac::adc::vals;
31 64
32 into_ref!(adc); 65 into_ref!(adc);
@@ -58,6 +91,11 @@ impl<'d, T: Instance> Adc<'d, T> {
58 // Wait until the adc is ready 91 // Wait until the adc is ready
59 while !T::regs().isr().read().adrdy() {} 92 while !T::regs().isr().read().adrdy() {}
60 93
94 T::Interrupt::unpend();
95 unsafe {
96 T::Interrupt::enable();
97 }
98
61 Self { 99 Self {
62 adc, 100 adc,
63 sample_time: Default::default(), 101 sample_time: Default::default(),
@@ -97,30 +135,41 @@ impl<'d, T: Instance> Adc<'d, T> {
97 } 135 }
98 136
99 /// Perform a single conversion. 137 /// Perform a single conversion.
100 fn convert(&mut self) -> u16 { 138 async fn convert(&mut self) -> u16 {
101 T::regs().isr().write(|_| {}); 139 T::regs().isr().write(|_| {});
140 T::regs().ier().modify(|w| w.set_eocie(true));
102 T::regs().cr().modify(|w| w.set_adstart(true)); 141 T::regs().cr().modify(|w| w.set_adstart(true));
103 142
104 while !T::regs().isr().read().eoc() && !T::regs().isr().read().eos() {} 143 poll_fn(|cx| {
144 T::state().waker.register(cx.waker());
145
146 if T::regs().isr().read().eoc() {
147 Poll::Ready(())
148 } else {
149 Poll::Pending
150 }
151 })
152 .await;
153
105 T::regs().isr().write(|_| {}); 154 T::regs().isr().write(|_| {});
106 155
107 T::regs().dr().read().rdata() 156 T::regs().dr().read().rdata()
108 } 157 }
109 158
110 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { 159 pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
111 Self::set_channel_sample_time(pin.channel(), self.sample_time); 160 Self::set_channel_sample_time(pin.channel(), self.sample_time);
112 161
113 // Configure the channel to sample 162 // Configure the channel to sample
114 T::regs().sqr1().write(|w| w.set_sq(0, pin.channel())); 163 T::regs().sqr1().write(|w| w.set_sq(0, pin.channel()));
115 self.convert() 164 self.convert().await
116 } 165 }
117 166
118 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 167 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
119 let sample_time = sample_time.into(); 168 let sample_time = sample_time.into();
120 if ch <= 9 { 169 if ch <= 9 {
121 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); 170 T::regs().smpr1().modify(|reg| reg.set_smp(ch as _, sample_time));
122 } else { 171 } else {
123 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); 172 T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
124 } 173 }
125 } 174 }
126} 175}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 9334deac4..e74913da8 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -31,12 +31,35 @@ pub struct Adc<'d, T: Instance> {
31} 31}
32 32
33pub(crate) mod sealed { 33pub(crate) mod sealed {
34 pub trait Instance { 34 #[cfg(adc_f3)]
35 use embassy_sync::waitqueue::AtomicWaker;
36
37 #[cfg(adc_f3)]
38 pub struct State {
39 pub waker: AtomicWaker,
40 }
41
42 #[cfg(adc_f3)]
43 impl State {
44 pub const fn new() -> Self {
45 Self {
46 waker: AtomicWaker::new(),
47 }
48 }
49 }
50
51 pub trait InterruptableInstance {
52 type Interrupt: crate::interrupt::typelevel::Interrupt;
53 }
54
55 pub trait Instance: InterruptableInstance {
35 fn regs() -> crate::pac::adc::Adc; 56 fn regs() -> crate::pac::adc::Adc;
36 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))] 57 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))]
37 fn common_regs() -> crate::pac::adccommon::AdcCommon; 58 fn common_regs() -> crate::pac::adccommon::AdcCommon;
38 #[cfg(adc_f3)] 59 #[cfg(adc_f3)]
39 fn frequency() -> crate::time::Hertz; 60 fn frequency() -> crate::time::Hertz;
61 #[cfg(adc_f3)]
62 fn state() -> &'static State;
40 } 63 }
41 64
42 pub trait AdcPin<T: Instance> { 65 pub trait AdcPin<T: Instance> {
@@ -72,8 +95,22 @@ foreach_adc!(
72 fn frequency() -> crate::time::Hertz { 95 fn frequency() -> crate::time::Hertz {
73 unsafe { crate::rcc::get_freqs() }.$clock.unwrap() 96 unsafe { crate::rcc::get_freqs() }.$clock.unwrap()
74 } 97 }
98
99 #[cfg(adc_f3)]
100 fn state() -> &'static sealed::State {
101 static STATE: sealed::State = sealed::State::new();
102 &STATE
103 }
75 } 104 }
76 105
106 foreach_interrupt!(
107 ($inst,adc,ADC,GLOBAL,$irq:ident) => {
108 impl sealed::InterruptableInstance for peripherals::$inst {
109 type Interrupt = crate::interrupt::typelevel::$irq;
110 }
111 };
112 );
113
77 impl crate::adc::Instance for peripherals::$inst {} 114 impl crate::adc::Instance for peripherals::$inst {}
78 }; 115 };
79); 116);
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index e8b2cd8a7..ed246a7db 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -4,13 +4,18 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime, VREF_INT}; 7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::peripherals::ADC1;
8use embassy_stm32::rcc::AdcClockSource; 9use embassy_stm32::rcc::AdcClockSource;
9use embassy_stm32::time::mhz; 10use embassy_stm32::time::mhz;
10use embassy_stm32::Config; 11use embassy_stm32::{adc, bind_interrupts, Config};
11use embassy_time::{Delay, Duration, Timer}; 12use embassy_time::{Delay, Duration, Timer};
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
13 14
15bind_interrupts!(struct Irqs {
16 ADC1_2 => adc::InterruptHandler<ADC1>;
17});
18
14#[embassy_executor::main] 19#[embassy_executor::main]
15async fn main(_spawner: Spawner) -> ! { 20async fn main(_spawner: Spawner) -> ! {
16 let mut config = Config::default(); 21 let mut config = Config::default();
@@ -24,7 +29,7 @@ async fn main(_spawner: Spawner) -> ! {
24 29
25 info!("create adc..."); 30 info!("create adc...");
26 31
27 let mut adc = Adc::new(p.ADC1, &mut Delay); 32 let mut adc = Adc::new(p.ADC1, Irqs, &mut Delay);
28 33
29 adc.set_sample_time(SampleTime::Cycles601_5); 34 adc.set_sample_time(SampleTime::Cycles601_5);
30 35
@@ -34,18 +39,18 @@ async fn main(_spawner: Spawner) -> ! {
34 let mut temperature = adc.enable_temperature(); 39 let mut temperature = adc.enable_temperature();
35 40
36 loop { 41 loop {
37 let vref = adc.read(&mut vrefint); 42 let vref = adc.read(&mut vrefint).await;
38 info!("read vref: {}", vref); 43 info!("read vref: {} (should be {})", vref, vrefint.value());
39 44
40 let temp = adc.read(&mut temperature); 45 let temp = adc.read(&mut temperature).await;
41 info!("read temperature: {}", temp); 46 info!("read temperature: {}", temp);
42 47
43 let pin = adc.read(&mut p.PA0); 48 let pin = adc.read(&mut p.PA0).await;
44 info!("read pin: {}", pin); 49 info!("read pin: {}", pin);
45 50
46 let pin_mv = pin as u32 * VREF_INT as u32 / vref as u32; 51 let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095;
47 info!("computed pin mv: {}", pin_mv); 52 info!("computed pin mv: {}", pin_mv);
48 53
49 Timer::after(Duration::from_secs(1)).await; 54 Timer::after(Duration::from_millis(500)).await;
50 } 55 }
51} 56}