aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/adc/g4.rs125
-rw-r--r--embassy-stm32/src/adc/injected.rs2
-rw-r--r--embassy-stm32/src/adc/ringbuffered.rs2
-rw-r--r--embassy-stm32/src/adc/v2.rs164
-rw-r--r--embassy-stm32/src/adc/v3.rs2
5 files changed, 140 insertions, 155 deletions
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 2138a82b4..5d9c6ff74 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -147,7 +147,7 @@ impl<'d, T: Instance> Adc<'d, T> {
147 s.calibrate(); 147 s.calibrate();
148 blocking_delay_us(1); 148 blocking_delay_us(1);
149 149
150 s.enable(); 150 Self::enable();
151 s.configure(); 151 s.configure();
152 152
153 s 153 s
@@ -192,7 +192,7 @@ impl<'d, T: Instance> Adc<'d, T> {
192 blocking_delay_us(20); 192 blocking_delay_us(20);
193 } 193 }
194 194
195 fn enable(&mut self) { 195 fn enable() {
196 // Make sure bits are off 196 // Make sure bits are off
197 while T::regs().cr().read().addis() { 197 while T::regs().cr().read().addis() {
198 // spin 198 // spin
@@ -363,7 +363,7 @@ impl<'d, T: Instance> Adc<'d, T> {
363 } 363 }
364 364
365 /// Teardown method for stopping regular ADC conversions 365 /// Teardown method for stopping regular ADC conversions
366 pub(super) fn teardown_adc() { 366 pub(super) fn teardown_dma() {
367 Self::stop_regular_conversions(); 367 Self::stop_regular_conversions();
368 368
369 // Disable dma control 369 // Disable dma control
@@ -418,39 +418,13 @@ impl<'d, T: Instance> Adc<'d, T> {
418 418
419 // Ensure no conversions are ongoing and ADC is enabled. 419 // Ensure no conversions are ongoing and ADC is enabled.
420 Self::stop_regular_conversions(); 420 Self::stop_regular_conversions();
421 self.enable(); 421 Self::enable();
422 422
423 // Set sequence length 423 Self::configure_sequence(sequence.map(|(channel, sample_time)| {
424 T::regs().sqr1().modify(|w| { 424 channel.setup();
425 w.set_l(sequence.len() as u8 - 1); 425
426 }); 426 (channel.channel, sample_time)
427 // Configure channels and ranks 427 }));
428 for (_i, (channel, sample_time)) in sequence.enumerate() {
429 Self::configure_channel(channel, sample_time);
430 match _i {
431 0..=3 => {
432 T::regs().sqr1().modify(|w| {
433 w.set_sq(_i, channel.channel());
434 });
435 }
436 4..=8 => {
437 T::regs().sqr2().modify(|w| {
438 w.set_sq(_i - 4, channel.channel());
439 });
440 }
441 9..=13 => {
442 T::regs().sqr3().modify(|w| {
443 w.set_sq(_i - 9, channel.channel());
444 });
445 }
446 14..=15 => {
447 T::regs().sqr4().modify(|w| {
448 w.set_sq(_i - 14, channel.channel());
449 });
450 }
451 _ => unreachable!(),
452 }
453 }
454 428
455 // Set continuous mode with oneshot dma. 429 // Set continuous mode with oneshot dma.
456 // Clear overrun flag before starting transfer. 430 // Clear overrun flag before starting transfer.
@@ -493,6 +467,47 @@ impl<'d, T: Instance> Adc<'d, T> {
493 }); 467 });
494 } 468 }
495 469
470 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = (u8, SampleTime)>) {
471 // Set sequence length
472 T::regs().sqr1().modify(|w| {
473 w.set_l(sequence.len() as u8 - 1);
474 });
475
476 // Configure channels and ranks
477 for (_i, (ch, sample_time)) in sequence.enumerate() {
478 let sample_time = sample_time.into();
479 if ch <= 9 {
480 T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time));
481 } else {
482 T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
483 }
484
485 match _i {
486 0..=3 => {
487 T::regs().sqr1().modify(|w| {
488 w.set_sq(_i, ch);
489 });
490 }
491 4..=8 => {
492 T::regs().sqr2().modify(|w| {
493 w.set_sq(_i - 4, ch);
494 });
495 }
496 9..=13 => {
497 T::regs().sqr3().modify(|w| {
498 w.set_sq(_i - 9, ch);
499 });
500 }
501 14..=15 => {
502 T::regs().sqr4().modify(|w| {
503 w.set_sq(_i - 14, ch);
504 });
505 }
506 _ => unreachable!(),
507 }
508 }
509 }
510
496 /// Set external trigger for regular conversion sequence 511 /// Set external trigger for regular conversion sequence
497 fn set_regular_conversion_trigger(&mut self, trigger: ConversionTrigger) { 512 fn set_regular_conversion_trigger(&mut self, trigger: ConversionTrigger) {
498 T::regs().cfgr().modify(|r| { 513 T::regs().cfgr().modify(|r| {
@@ -546,43 +561,15 @@ impl<'d, T: Instance> Adc<'d, T> {
546 ); 561 );
547 // reset conversions and enable the adc 562 // reset conversions and enable the adc
548 Self::stop_regular_conversions(); 563 Self::stop_regular_conversions();
549 self.enable(); 564 Self::enable();
550 565
551 //adc side setup 566 //adc side setup
552 567
553 // Set sequence length 568 Self::configure_sequence(sequence.map(|(mut channel, sample_time)| {
554 T::regs().sqr1().modify(|w| { 569 channel.setup();
555 w.set_l(sequence.len() as u8 - 1);
556 });
557
558 // Configure channels and ranks
559 for (_i, (mut channel, sample_time)) in sequence.enumerate() {
560 Self::configure_channel(&mut channel, sample_time);
561 570
562 match _i { 571 (channel.channel, sample_time)
563 0..=3 => { 572 }));
564 T::regs().sqr1().modify(|w| {
565 w.set_sq(_i, channel.channel());
566 });
567 }
568 4..=8 => {
569 T::regs().sqr2().modify(|w| {
570 w.set_sq(_i - 4, channel.channel());
571 });
572 }
573 9..=13 => {
574 T::regs().sqr3().modify(|w| {
575 w.set_sq(_i - 9, channel.channel());
576 });
577 }
578 14..=15 => {
579 T::regs().sqr4().modify(|w| {
580 w.set_sq(_i - 14, channel.channel());
581 });
582 }
583 _ => unreachable!(),
584 }
585 }
586 573
587 // Clear overrun flag before starting transfer. 574 // Clear overrun flag before starting transfer.
588 T::regs().isr().modify(|reg| { 575 T::regs().isr().modify(|reg| {
@@ -655,7 +642,7 @@ impl<'d, T: Instance> Adc<'d, T> {
655 ); 642 );
656 643
657 Self::stop_regular_conversions(); 644 Self::stop_regular_conversions();
658 self.enable(); 645 Self::enable();
659 646
660 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); 647 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1));
661 648
diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs
index 0e4fe5847..f9f1bba2a 100644
--- a/embassy-stm32/src/adc/injected.rs
+++ b/embassy-stm32/src/adc/injected.rs
@@ -38,7 +38,7 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> {
38 38
39impl<T: Instance, const N: usize> Drop for InjectedAdc<T, N> { 39impl<T: Instance, const N: usize> Drop for InjectedAdc<T, N> {
40 fn drop(&mut self) { 40 fn drop(&mut self) {
41 Adc::<T>::teardown_adc(); 41 Adc::<T>::teardown_dma();
42 compiler_fence(Ordering::SeqCst); 42 compiler_fence(Ordering::SeqCst);
43 } 43 }
44} 44}
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs
index 971c8195c..024c6acdc 100644
--- a/embassy-stm32/src/adc/ringbuffered.rs
+++ b/embassy-stm32/src/adc/ringbuffered.rs
@@ -172,7 +172,7 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
172 172
173impl<T: Instance> Drop for RingBufferedAdc<'_, T> { 173impl<T: Instance> Drop for RingBufferedAdc<'_, T> {
174 fn drop(&mut self) { 174 fn drop(&mut self) {
175 Adc::<T>::teardown_adc(); 175 Adc::<T>::teardown_dma();
176 176
177 compiler_fence(Ordering::SeqCst); 177 compiler_fence(Ordering::SeqCst);
178 178
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index af5d486d9..88a8b96ed 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -125,57 +125,14 @@ where
125 ) -> RingBufferedAdc<'d, T> { 125 ) -> RingBufferedAdc<'d, T> {
126 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); 126 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
127 127
128 T::regs().cr2().modify(|reg| { 128 Self::configure_sequence(sequence.map(|(mut channel, sample_time)| {
129 reg.set_adon(true);
130 });
131
132 // Check the sequence is long enough
133 T::regs().sqr1().modify(|r| {
134 r.set_l((sequence.len() - 1).try_into().unwrap());
135 });
136
137 for (i, (mut channel, sample_time)) in sequence.enumerate() {
138 // Set this GPIO as an analog input.
139 channel.setup(); 129 channel.setup();
140 130
141 // Set the channel in the right sequence field. 131 (channel.channel, sample_time)
142 T::regs().sqr3().modify(|w| w.set_sq(i, channel.channel())); 132 }));
143
144 Self::set_channel_sample_time(channel.channel(), sample_time);
145 }
146
147 compiler_fence(Ordering::SeqCst); 133 compiler_fence(Ordering::SeqCst);
148 134
149 let r = T::regs(); 135 Self::setup_dma();
150
151 // Clear all interrupts
152 r.sr().modify(|regs| {
153 regs.set_eoc(false);
154 regs.set_ovr(false);
155 regs.set_strt(false);
156 });
157
158 r.cr1().modify(|w| {
159 // Enable interrupt for end of conversion
160 w.set_eocie(true);
161 // Enable interrupt for overrun
162 w.set_ovrie(true);
163 // Scanning converisons of multiple channels
164 w.set_scan(true);
165 // Continuous conversion mode
166 w.set_discen(false);
167 });
168
169 r.cr2().modify(|w| {
170 // Enable DMA mode
171 w.set_dma(true);
172 // Enable continuous conversions
173 w.set_cont(true);
174 // DMA requests are issues as long as DMA=1 and data are converted.
175 w.set_dds(vals::Dds::CONTINUOUS);
176 // EOC flag is set at the end of each conversion.
177 w.set_eocs(vals::Eocs::EACH_CONVERSION);
178 });
179 136
180 // Don't disable the clock 137 // Don't disable the clock
181 mem::forget(self); 138 mem::forget(self);
@@ -183,24 +140,14 @@ where
183 RingBufferedAdc::new(dma, dma_buf) 140 RingBufferedAdc::new(dma, dma_buf)
184 } 141 }
185 142
186 pub(super) fn start() { 143 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
187 // Begin ADC conversions 144 channel.setup();
188 T::regs().cr2().modify(|reg| {
189 reg.set_adon(true);
190 reg.set_swstart(true);
191 });
192 }
193 145
194 pub(super) fn stop() { 146 // Configure ADC
195 // Stop ADC 147 let channel = channel.channel();
196 T::regs().cr2().modify(|reg| {
197 // Stop ADC
198 reg.set_swstart(false);
199 });
200 }
201 148
202 pub fn set_resolution(&mut self, resolution: Resolution) { 149 Self::configure_sequence([(channel, sample_time)].into_iter());
203 T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); 150 Self::blocking_convert()
204 } 151 }
205 152
206 /// Enables internal voltage reference and returns [VrefInt], which can be used in 153 /// Enables internal voltage reference and returns [VrefInt], which can be used in
@@ -236,8 +183,27 @@ where
236 Vbat {} 183 Vbat {}
237 } 184 }
238 185
239 /// Perform a single conversion. 186 pub(super) fn start() {
240 fn convert(&mut self) -> u16 { 187 // Begin ADC conversions
188 T::regs().cr2().modify(|reg| {
189 reg.set_adon(true);
190 reg.set_swstart(true);
191 });
192 }
193
194 pub(super) fn stop() {
195 // Stop ADC
196 T::regs().cr2().modify(|reg| {
197 // Stop ADC
198 reg.set_swstart(false);
199 });
200 }
201
202 pub fn set_resolution(&mut self, resolution: Resolution) {
203 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
204 }
205
206 pub(super) fn blocking_convert() -> u16 {
241 // clear end of conversion flag 207 // clear end of conversion flag
242 T::regs().sr().modify(|reg| { 208 T::regs().sr().modify(|reg| {
243 reg.set_eoc(false); 209 reg.set_eoc(false);
@@ -258,31 +224,63 @@ where
258 T::regs().dr().read().0 as u16 224 T::regs().dr().read().0 as u16
259 } 225 }
260 226
261 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { 227 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = (u8, SampleTime)>) {
262 channel.setup(); 228 T::regs().cr2().modify(|reg| {
229 reg.set_adon(true);
230 });
263 231
264 // Configure ADC 232 // Check the sequence is long enough
265 let channel = channel.channel(); 233 T::regs().sqr1().modify(|r| {
234 r.set_l((sequence.len() - 1).try_into().unwrap());
235 });
266 236
267 // Select channel 237 for (i, (ch, sample_time)) in sequence.enumerate() {
268 T::regs().sqr3().write(|reg| reg.set_sq(0, channel)); 238 // Set the channel in the right sequence field.
239 T::regs().sqr3().modify(|w| w.set_sq(i, ch));
240
241 let sample_time = sample_time.into();
242 if ch <= 9 {
243 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
244 } else {
245 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
246 }
247 }
248 }
269 249
270 // Configure channel 250 pub(super) fn setup_dma() {
271 Self::set_channel_sample_time(channel, sample_time); 251 let r = T::regs();
272 252
273 self.convert() 253 // Clear all interrupts
274 } 254 r.sr().modify(|regs| {
255 regs.set_eoc(false);
256 regs.set_ovr(false);
257 regs.set_strt(false);
258 });
275 259
276 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 260 r.cr1().modify(|w| {
277 let sample_time = sample_time.into(); 261 // Enable interrupt for end of conversion
278 if ch <= 9 { 262 w.set_eocie(true);
279 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); 263 // Enable interrupt for overrun
280 } else { 264 w.set_ovrie(true);
281 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); 265 // Scanning converisons of multiple channels
282 } 266 w.set_scan(true);
267 // Continuous conversion mode
268 w.set_discen(false);
269 });
270
271 r.cr2().modify(|w| {
272 // Enable DMA mode
273 w.set_dma(true);
274 // Enable continuous conversions
275 w.set_cont(true);
276 // DMA requests are issues as long as DMA=1 and data are converted.
277 w.set_dds(vals::Dds::CONTINUOUS);
278 // EOC flag is set at the end of each conversion.
279 w.set_eocs(vals::Eocs::EACH_CONVERSION);
280 });
283 } 281 }
284 282
285 pub(super) fn teardown_adc() { 283 pub(super) fn teardown_dma() {
286 let r = T::regs(); 284 let r = T::regs();
287 285
288 // Stop ADC 286 // Stop ADC
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 0822fbb69..e816907d1 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -198,7 +198,7 @@ impl<'d, T: Instance> Adc<'d, T> {
198 } 198 }
199 199
200 #[cfg(any(adc_v3, adc_g0, adc_u0))] 200 #[cfg(any(adc_v3, adc_g0, adc_u0))]
201 pub(super) fn teardown_adc() { 201 pub(super) fn teardown_dma() {
202 //disable dma control 202 //disable dma control
203 #[cfg(not(any(adc_g0, adc_u0)))] 203 #[cfg(not(any(adc_g0, adc_u0)))]
204 T::regs().cfgr().modify(|reg| { 204 T::regs().cfgr().modify(|reg| {