aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-09-18 16:31:20 -0500
committerxoviat <[email protected]>2023-09-18 16:31:20 -0500
commite640933e2f0c8fb0b5a6df645002f69b55f51d8a (patch)
tree3f2d8c4e4e338c96097d2b85a93244cc74b2be5e /embassy-stm32/src
parentdaeb497045d47db3afa926b4e0e9e17973a544d5 (diff)
stm32/adc: add async conversion
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/adc/f3.rs65
-rw-r--r--embassy-stm32/src/adc/mod.rs39
2 files changed, 95 insertions, 9 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);