aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/adc/ringbuffered.rs248
-rw-r--r--embassy-stm32/src/adc/v2.rs102
-rw-r--r--embassy-stm32/src/adc/v3.rs32
3 files changed, 152 insertions, 230 deletions
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs
index 931ebc2b7..790eff422 100644
--- a/embassy-stm32/src/adc/ringbuffered.rs
+++ b/embassy-stm32/src/adc/ringbuffered.rs
@@ -4,6 +4,7 @@ use core::sync::atomic::{Ordering, compiler_fence};
4#[allow(unused_imports)] 4#[allow(unused_imports)]
5use embassy_hal_internal::Peri; 5use embassy_hal_internal::Peri;
6 6
7use crate::adc::Adc;
7#[allow(unused_imports)] 8#[allow(unused_imports)]
8use crate::adc::{Instance, RxDma}; 9use crate::adc::{Instance, RxDma};
9#[allow(unused_imports)] 10#[allow(unused_imports)]
@@ -13,21 +14,12 @@ use crate::rcc;
13#[cfg_attr(feature = "defmt", derive(defmt::Format))] 14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14pub struct OverrunError; 15pub struct OverrunError;
15 16
16#[cfg(adc_v2)]
17fn clear_interrupt_flags(r: crate::pac::adc::Adc) {
18 r.sr().modify(|regs| {
19 regs.set_eoc(false);
20 regs.set_ovr(false);
21 });
22}
23
24pub struct RingBufferedAdc<'d, T: Instance> { 17pub struct RingBufferedAdc<'d, T: Instance> {
25 pub _phantom: PhantomData<T>, 18 _phantom: PhantomData<T>,
26 pub ring_buf: ReadableRingBuffer<'d, u16>, 19 ring_buf: ReadableRingBuffer<'d, u16>,
27} 20}
28 21
29impl<'d, T: Instance> RingBufferedAdc<'d, T> { 22impl<'d, T: Instance> RingBufferedAdc<'d, T> {
30 #[cfg(not(adc_v2))]
31 pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self { 23 pub(crate) fn new(dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> Self {
32 //dma side setup 24 //dma side setup
33 let opts = TransferOptions { 25 let opts = TransferOptions {
@@ -48,161 +40,24 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
48 } 40 }
49 } 41 }
50 42
51 #[cfg(adc_v2)]
52 fn is_on() -> bool {
53 T::regs().cr2().read().adon()
54 }
55
56 #[cfg(adc_v2)]
57 /// Turns on ADC if it is not already turned on and starts continuous DMA transfer. 43 /// Turns on ADC if it is not already turned on and starts continuous DMA transfer.
58 pub fn start(&mut self) -> Result<(), OverrunError> { 44 pub fn start(&mut self) {
59 self.setup_adc(); 45 compiler_fence(Ordering::SeqCst);
60 self.ring_buf.clear(); 46 self.ring_buf.start();
61
62 Ok(())
63 }
64 47
65 #[cfg(adc_v2)] 48 Adc::<T>::start();
66 fn stop(&mut self, err: OverrunError) -> Result<usize, OverrunError> {
67 self.teardown_adc();
68 Err(err)
69 } 49 }
70 50
71 #[cfg(adc_v2)] 51 pub fn stop(&mut self) {
72 /// Stops DMA transfer.
73 /// It does not turn off ADC.
74 /// Calling `start` restarts continuous DMA transfer.
75 ///
76 /// [`start`]: #method.start
77 pub fn teardown_adc(&mut self) {
78 // Stop the DMA transfer
79 self.ring_buf.request_pause(); 52 self.ring_buf.request_pause();
80 53
81 let r = T::regs(); 54 Adc::<T>::stop();
82
83 // Stop ADC
84 r.cr2().modify(|reg| {
85 // Stop ADC
86 reg.set_swstart(false);
87 // Stop DMA
88 reg.set_dma(false);
89 });
90
91 r.cr1().modify(|w| {
92 // Disable interrupt for end of conversion
93 w.set_eocie(false);
94 // Disable interrupt for overrun
95 w.set_ovrie(false);
96 });
97
98 clear_interrupt_flags(r);
99 55
100 compiler_fence(Ordering::SeqCst); 56 compiler_fence(Ordering::SeqCst);
101 } 57 }
102 58
103 #[cfg(adc_v2)] 59 pub fn clear(&mut self) {
104 fn setup_adc(&mut self) {
105 use crate::pac::adc::vals;
106
107 compiler_fence(Ordering::SeqCst);
108
109 self.ring_buf.start();
110
111 let r = T::regs();
112
113 // Enable ADC
114 let was_on = Self::is_on();
115 if !was_on {
116 r.cr2().modify(|reg| {
117 reg.set_adon(false);
118 reg.set_swstart(false);
119 });
120 }
121
122 // Clear all interrupts
123 r.sr().modify(|regs| {
124 regs.set_eoc(false);
125 regs.set_ovr(false);
126 regs.set_strt(false);
127 });
128
129 r.cr1().modify(|w| {
130 // Enable interrupt for end of conversion
131 w.set_eocie(true);
132 // Enable interrupt for overrun
133 w.set_ovrie(true);
134 // Scanning converisons of multiple channels
135 w.set_scan(true);
136 // Continuous conversion mode
137 w.set_discen(false);
138 });
139
140 r.cr2().modify(|w| {
141 // Enable DMA mode
142 w.set_dma(true);
143 // Enable continuous conversions
144 w.set_cont(true);
145 // DMA requests are issues as long as DMA=1 and data are converted.
146 w.set_dds(vals::Dds::CONTINUOUS);
147 // EOC flag is set at the end of each conversion.
148 w.set_eocs(vals::Eocs::EACH_CONVERSION);
149 });
150
151 // Begin ADC conversions
152 T::regs().cr2().modify(|reg| {
153 reg.set_adon(true);
154 reg.set_swstart(true);
155 });
156
157 super::blocking_delay_us(3);
158 }
159
160 #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))]
161 #[inline]
162 fn start_continuous_sampling(&mut self) {
163 // Start adc conversion
164 T::regs().cr().modify(|reg| {
165 reg.set_adstart(true);
166 });
167 self.ring_buf.start();
168 }
169
170 #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))]
171 #[inline]
172 pub fn stop_continuous_sampling(&mut self) {
173 // Stop adc conversion
174 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
175 T::regs().cr().modify(|reg| {
176 reg.set_adstp(true);
177 });
178 while T::regs().cr().read().adstart() {}
179 }
180 }
181
182 #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))]
183 pub fn disable_adc(&mut self) {
184 self.stop_continuous_sampling();
185 self.ring_buf.clear(); 60 self.ring_buf.clear();
186 self.ring_buf.request_pause();
187 }
188
189 #[cfg(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0))]
190 pub fn teardown_adc(&mut self) {
191 self.disable_adc();
192
193 //disable dma control
194 #[cfg(not(any(adc_g0, adc_u0)))]
195 T::regs().cfgr().modify(|reg| {
196 reg.set_dmaen(false);
197 });
198 #[cfg(any(adc_g0, adc_u0))]
199 T::regs().cfgr1().modify(|reg| {
200 reg.set_dmaen(false);
201 });
202
203 //TODO: do we need to cleanup the DMA request here?
204
205 compiler_fence(Ordering::SeqCst);
206 } 61 }
207 62
208 /// Reads measurements from the DMA ring buffer. 63 /// Reads measurements from the DMA ring buffer.
@@ -257,31 +112,17 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
257 "Buffer size must be half the size of the ring buffer" 112 "Buffer size must be half the size of the ring buffer"
258 ); 113 );
259 114
260 let r = T::regs(); 115 if !self.ring_buf.is_running() {
116 self.start();
117 }
261 118
262 #[cfg(adc_v2)] 119 #[cfg(adc_v2)]
263 { 120 {
264 // Start background receive if it was not already started
265 if !r.cr2().read().dma() {
266 self.start()?;
267 }
268
269 // Clear overrun flag if set. 121 // Clear overrun flag if set.
270 if r.sr().read().ovr() { 122 if T::regs().sr().read().ovr() {
271 return self.stop(OverrunError); 123 self.stop();
272 }
273
274 // Start background receive if it was not already started
275 if !r.cr().read().adstart() {
276 self.start_continuous_sampling();
277 }
278 }
279 124
280 #[cfg(not(adc_v2))] 125 return Err(OverrunError);
281 {
282 // Start background receive if it was not already started
283 if !r.cr().read().adstart() {
284 self.start_continuous_sampling();
285 } 126 }
286 } 127 }
287 128
@@ -297,50 +138,29 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
297 /// Receive in the background is terminated if an error is returned. 138 /// Receive in the background is terminated if an error is returned.
298 /// It must then manually be started again by calling `start_continuous_sampling()` or by re-calling `blocking_read()`. 139 /// It must then manually be started again by calling `start_continuous_sampling()` or by re-calling `blocking_read()`.
299 pub fn blocking_read(&mut self, buf: &mut [u16]) -> Result<usize, OverrunError> { 140 pub fn blocking_read(&mut self, buf: &mut [u16]) -> Result<usize, OverrunError> {
300 let r = T::regs(); 141 if !self.ring_buf.is_running() {
142 self.start();
143 }
301 144
302 #[cfg(adc_v2)] 145 #[cfg(adc_v2)]
303 { 146 {
304 // Start background receive if it was not already started
305 if !r.cr2().read().dma() {
306 self.start()?;
307 }
308
309 // Clear overrun flag if set. 147 // Clear overrun flag if set.
310 if r.sr().read().ovr() { 148 if T::regs().sr().read().ovr() {
311 return self.stop(OverrunError); 149 self.stop();
312 }
313 150
314 loop { 151 return Err(OverrunError);
315 match self.ring_buf.read(buf) {
316 Ok((0, _)) => {}
317 Ok((len, _)) => {
318 return Ok(len);
319 }
320 Err(_) => {
321 return self.stop(OverrunError);
322 }
323 }
324 } 152 }
325 } 153 }
154 loop {
155 match self.ring_buf.read(buf) {
156 Ok((0, _)) => {}
157 Ok((len, _)) => {
158 return Ok(len);
159 }
160 Err(_) => {
161 self.stop();
326 162
327 #[cfg(not(adc_v2))] 163 return Err(OverrunError);
328 {
329 // Start background receive if it was not already started
330 if !r.cr().read().adstart() {
331 self.start_continuous_sampling();
332 }
333
334 loop {
335 match self.ring_buf.read(buf) {
336 Ok((0, _)) => {}
337 Ok((len, _)) => {
338 return Ok(len);
339 }
340 Err(_) => {
341 self.stop_continuous_sampling();
342 return Err(OverrunError);
343 }
344 } 164 }
345 } 165 }
346 } 166 }
@@ -349,7 +169,11 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
349 169
350impl<T: Instance> Drop for RingBufferedAdc<'_, T> { 170impl<T: Instance> Drop for RingBufferedAdc<'_, T> {
351 fn drop(&mut self) { 171 fn drop(&mut self) {
352 self.teardown_adc(); 172 Adc::<T>::teardown_adc();
173
174 compiler_fence(Ordering::SeqCst);
175
176 self.ring_buf.request_pause();
353 rcc::disable::<T>(); 177 rcc::disable::<T>();
354 } 178 }
355} 179}
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index e57cd19b3..90c6294d2 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -1,9 +1,9 @@
1use core::marker::PhantomData;
2use core::mem; 1use core::mem;
2use core::sync::atomic::{Ordering, compiler_fence};
3 3
4use super::blocking_delay_us; 4use super::blocking_delay_us;
5use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; 5use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel};
6use crate::dma::{Priority, ReadableRingBuffer, TransferOptions}; 6use crate::pac::adc::vals;
7use crate::peripherals::ADC1; 7use crate::peripherals::ADC1;
8use crate::time::Hertz; 8use crate::time::Hertz;
9use crate::{Peri, rcc}; 9use crate::{Peri, rcc};
@@ -11,6 +11,13 @@ use crate::{Peri, rcc};
11mod ringbuffered; 11mod ringbuffered;
12pub use ringbuffered::RingBufferedAdc; 12pub use ringbuffered::RingBufferedAdc;
13 13
14fn clear_interrupt_flags(r: crate::pac::adc::Adc) {
15 r.sr().modify(|regs| {
16 regs.set_eoc(false);
17 regs.set_ovr(false);
18 });
19}
20
14/// Default VREF voltage used for sample conversion to millivolts. 21/// Default VREF voltage used for sample conversion to millivolts.
15pub const VREF_DEFAULT_MV: u32 = 3300; 22pub const VREF_DEFAULT_MV: u32 = 3300;
16/// VREF voltage used for factory calibration of VREFINTCAL register. 23/// VREF voltage used for factory calibration of VREFINTCAL register.
@@ -134,18 +141,6 @@ where
134 ) -> RingBufferedAdc<'d, T> { 141 ) -> RingBufferedAdc<'d, T> {
135 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); 142 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
136 143
137 let opts: crate::dma::TransferOptions = TransferOptions {
138 half_transfer_ir: true,
139 priority: Priority::VeryHigh,
140 ..Default::default()
141 };
142
143 // Safety: we forget the struct before this function returns.
144 let rx_src = T::regs().dr().as_ptr() as *mut u16;
145 let request = dma.request();
146
147 let ring_buf = unsafe { ReadableRingBuffer::new(dma, request, rx_src, dma_buf, opts) };
148
149 T::regs().cr2().modify(|reg| { 144 T::regs().cr2().modify(|reg| {
150 reg.set_adon(true); 145 reg.set_adon(true);
151 }); 146 });
@@ -165,13 +160,59 @@ where
165 Self::set_channel_sample_time(channel.channel(), sample_time); 160 Self::set_channel_sample_time(channel.channel(), sample_time);
166 } 161 }
167 162
163 compiler_fence(Ordering::SeqCst);
164
165 let r = T::regs();
166
167 // Clear all interrupts
168 r.sr().modify(|regs| {
169 regs.set_eoc(false);
170 regs.set_ovr(false);
171 regs.set_strt(false);
172 });
173
174 r.cr1().modify(|w| {
175 // Enable interrupt for end of conversion
176 w.set_eocie(true);
177 // Enable interrupt for overrun
178 w.set_ovrie(true);
179 // Scanning converisons of multiple channels
180 w.set_scan(true);
181 // Continuous conversion mode
182 w.set_discen(false);
183 });
184
185 r.cr2().modify(|w| {
186 // Enable DMA mode
187 w.set_dma(true);
188 // Enable continuous conversions
189 w.set_cont(true);
190 // DMA requests are issues as long as DMA=1 and data are converted.
191 w.set_dds(vals::Dds::CONTINUOUS);
192 // EOC flag is set at the end of each conversion.
193 w.set_eocs(vals::Eocs::EACH_CONVERSION);
194 });
195
168 // Don't disable the clock 196 // Don't disable the clock
169 mem::forget(self); 197 mem::forget(self);
170 198
171 RingBufferedAdc { 199 RingBufferedAdc::new(dma, dma_buf)
172 _phantom: PhantomData, 200 }
173 ring_buf, 201
174 } 202 pub(super) fn start() {
203 // Begin ADC conversions
204 T::regs().cr2().modify(|reg| {
205 reg.set_adon(true);
206 reg.set_swstart(true);
207 });
208 }
209
210 pub(super) fn stop() {
211 // Stop ADC
212 T::regs().cr2().modify(|reg| {
213 // Stop ADC
214 reg.set_swstart(false);
215 });
175 } 216 }
176 217
177 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 218 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
@@ -260,6 +301,31 @@ where
260 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); 301 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
261 } 302 }
262 } 303 }
304
305 pub(super) fn teardown_adc() {
306 let r = T::regs();
307
308 // Stop ADC
309 r.cr2().modify(|reg| {
310 // Stop ADC
311 reg.set_swstart(false);
312 // Stop ADC
313 reg.set_adon(false);
314 // Stop DMA
315 reg.set_dma(false);
316 });
317
318 r.cr1().modify(|w| {
319 // Disable interrupt for end of conversion
320 w.set_eocie(false);
321 // Disable interrupt for overrun
322 w.set_ovrie(false);
323 });
324
325 clear_interrupt_flags(r);
326
327 compiler_fence(Ordering::SeqCst);
328 }
263} 329}
264 330
265impl<'d, T: Instance> Drop for Adc<'d, T> { 331impl<'d, T: Instance> Drop for Adc<'d, T> {
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 8a0cc0fcf..6da0adb44 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -181,6 +181,38 @@ impl<'d, T: Instance> Adc<'d, T> {
181 blocking_delay_us(1); 181 blocking_delay_us(1);
182 } 182 }
183 183
184 #[cfg(any(adc_v3, adc_g0, adc_u0))]
185 pub(super) fn start() {
186 // Start adc conversion
187 T::regs().cr().modify(|reg| {
188 reg.set_adstart(true);
189 });
190 }
191
192 #[cfg(any(adc_v3, adc_g0, adc_u0))]
193 pub(super) fn stop() {
194 // Stop adc conversion
195 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
196 T::regs().cr().modify(|reg| {
197 reg.set_adstp(true);
198 });
199 while T::regs().cr().read().adstart() {}
200 }
201 }
202
203 #[cfg(any(adc_v3, adc_g0, adc_u0))]
204 pub(super) fn teardown_adc() {
205 //disable dma control
206 #[cfg(not(any(adc_g0, adc_u0)))]
207 T::regs().cfgr().modify(|reg| {
208 reg.set_dmaen(false);
209 });
210 #[cfg(any(adc_g0, adc_u0))]
211 T::regs().cfgr1().modify(|reg| {
212 reg.set_dmaen(false);
213 });
214 }
215
184 /// Initialize the ADC leaving any analog clock at reset value. 216 /// Initialize the ADC leaving any analog clock at reset value.
185 /// For G0 and WL, this is the async clock without prescaler. 217 /// For G0 and WL, this is the async clock without prescaler.
186 pub fn new(adc: Peri<'d, T>) -> Self { 218 pub fn new(adc: Peri<'d, T>) -> Self {