aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-12 20:06:00 -0600
committerxoviat <[email protected]>2025-11-12 20:06:00 -0600
commitf0506252e21c96ce3b03e0d1c061a831d7dfe3c3 (patch)
tree839f8dac139321665abc293f907ad13d5721aede
parent07c918023c1b233a2f9f16eb0b654169c0379f79 (diff)
stm32: extract adc4
extract adc4 into common adc system and add anyInstance trait to cover adc4 and not adc4
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/build.rs4
-rw-r--r--embassy-stm32/src/adc/adc4.rs312
-rw-r--r--embassy-stm32/src/adc/g4.rs206
-rw-r--r--embassy-stm32/src/adc/injected.rs6
-rw-r--r--embassy-stm32/src/adc/mod.rs111
-rw-r--r--embassy-stm32/src/adc/ringbuffered.rs12
-rw-r--r--embassy-stm32/src/adc/v2.rs66
-rw-r--r--embassy-stm32/src/adc/v3.rs302
-rw-r--r--embassy-stm32/src/adc/v4.rs220
-rw-r--r--examples/stm32u5/src/bin/adc.rs21
-rw-r--r--examples/stm32wba/src/bin/adc.rs17
-rw-r--r--examples/stm32wba6/src/bin/adc.rs17
13 files changed, 651 insertions, 644 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index ec49924a2..2f4f2ce51 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -188,6 +188,7 @@ embedded-io = { version = "0.6.0" }
188embedded-io-async = { version = "0.6.1" } 188embedded-io-async = { version = "0.6.1" }
189chrono = { version = "^0.4", default-features = false, optional = true } 189chrono = { version = "^0.4", default-features = false, optional = true }
190bit_field = "0.10.2" 190bit_field = "0.10.2"
191trait-set = "0.3.0"
191document-features = "0.2.7" 192document-features = "0.2.7"
192 193
193static_assertions = { version = "1.1" } 194static_assertions = { version = "1.1" }
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 48da475df..ad6743f96 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -1602,13 +1602,13 @@ fn main() {
1602 .into(); 1602 .into();
1603 1603
1604 if chip_name.starts_with("stm32u5") { 1604 if chip_name.starts_with("stm32u5") {
1605 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4)); 1605 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
1606 } else { 1606 } else {
1607 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma)); 1607 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
1608 } 1608 }
1609 1609
1610 if chip_name.starts_with("stm32wba") { 1610 if chip_name.starts_with("stm32wba") {
1611 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma4)); 1611 signals.insert(("adc", "ADC4"), quote!(crate::adc::RxDma));
1612 } 1612 }
1613 1613
1614 if chip_name.starts_with("stm32g4") { 1614 if chip_name.starts_with("stm32g4") {
diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs
index 04d976513..52678d1b6 100644
--- a/embassy-stm32/src/adc/adc4.rs
+++ b/embassy-stm32/src/adc/adc4.rs
@@ -4,8 +4,8 @@ use pac::adc::vals::{Adc4Dmacfg as Dmacfg, Adc4Exten as Exten, Adc4OversamplingR
4#[cfg(stm32wba)] 4#[cfg(stm32wba)]
5use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel}; 5use pac::adc::vals::{Chselrmod, Cont, Dmacfg, Exten, OversamplingRatio, Ovss, Smpsel};
6 6
7use super::{AdcChannel, AnyAdcChannel, RxDma4, blocking_delay_us}; 7use super::blocking_delay_us;
8use crate::dma::Transfer; 8use crate::adc::ConversionMode;
9#[cfg(stm32u5)] 9#[cfg(stm32u5)]
10pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr; 10pub use crate::pac::adc::regs::Adc4Chselrmod0 as Chselr;
11#[cfg(stm32wba)] 11#[cfg(stm32wba)]
@@ -153,6 +153,121 @@ pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeri
153 type Interrupt: crate::interrupt::typelevel::Interrupt; 153 type Interrupt: crate::interrupt::typelevel::Interrupt;
154} 154}
155 155
156foreach_adc!(
157 (ADC4, $common_inst:ident, $clock:ident) => {
158 use crate::peripherals::ADC4;
159
160 impl super::BasicAnyInstance for ADC4 {
161 type SampleTime = SampleTime;
162 }
163
164 impl super::SealedAnyInstance for ADC4 {
165 fn dr() -> *mut u16 {
166 ADC4::regs().dr().as_ptr() as *mut u16
167 }
168
169 fn enable() {
170 ADC4::regs().isr().write(|w| w.set_adrdy(true));
171 ADC4::regs().cr().modify(|w| w.set_aden(true));
172 while !ADC4::regs().isr().read().adrdy() {}
173 ADC4::regs().isr().write(|w| w.set_adrdy(true));
174 }
175
176 fn start() {
177 // Start conversion
178 ADC4::regs().cr().modify(|reg| {
179 reg.set_adstart(true);
180 });
181 }
182
183 fn stop() {
184 if ADC4::regs().cr().read().adstart() && !ADC4::regs().cr().read().addis() {
185 ADC4::regs().cr().modify(|reg| {
186 reg.set_adstp(true);
187 });
188 while ADC4::regs().cr().read().adstart() {}
189 }
190
191 // Reset configuration.
192 ADC4::regs().cfgr1().modify(|reg| {
193 reg.set_dmaen(false);
194 });
195 }
196
197 fn configure_dma(conversion_mode: ConversionMode) {
198 match conversion_mode {
199 ConversionMode::Singular => {
200 ADC4::regs().isr().modify(|reg| {
201 reg.set_ovr(true);
202 reg.set_eos(true);
203 reg.set_eoc(true);
204 });
205
206 ADC4::regs().cfgr1().modify(|reg| {
207 reg.set_dmaen(true);
208 reg.set_dmacfg(Dmacfg::ONE_SHOT);
209 #[cfg(stm32u5)]
210 reg.set_chselrmod(false);
211 #[cfg(stm32wba)]
212 reg.set_chselrmod(Chselrmod::ENABLE_INPUT)
213 });
214 }
215 _ => unreachable!(),
216 }
217 }
218
219 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
220 let mut prev_channel: i16 = -1;
221 #[cfg(stm32wba)]
222 ADC4::regs().chselr().write_value(Chselr(0_u32));
223 #[cfg(stm32u5)]
224 ADC4::regs().chselrmod0().write_value(Chselr(0_u32));
225 for (_i, ((channel, _), sample_time)) in sequence.enumerate() {
226 ADC4::regs().smpr().modify(|w| {
227 w.set_smp(_i, sample_time);
228 });
229
230 let channel_num = channel;
231 if channel_num as i16 <= prev_channel {
232 return;
233 };
234 prev_channel = channel_num as i16;
235
236 #[cfg(stm32wba)]
237 ADC4::regs().chselr().modify(|w| {
238 w.set_chsel0(channel as usize, true);
239 });
240 #[cfg(stm32u5)]
241 ADC4::regs().chselrmod0().modify(|w| {
242 w.set_chsel(channel as usize, true);
243 });
244 }
245 }
246
247 fn convert() -> u16 {
248 // Reset interrupts
249 ADC4::regs().isr().modify(|reg| {
250 reg.set_eos(true);
251 reg.set_eoc(true);
252 });
253
254 // Start conversion
255 ADC4::regs().cr().modify(|reg| {
256 reg.set_adstart(true);
257 });
258
259 while !ADC4::regs().isr().read().eos() {
260 // spin
261 }
262
263 ADC4::regs().dr().read().0 as u16
264 }
265 }
266
267 impl super::AnyInstance for ADC4 {}
268 };
269);
270
156pub struct Adc4<'d, T: Instance> { 271pub struct Adc4<'d, T: Instance> {
157 #[allow(unused)] 272 #[allow(unused)]
158 adc: crate::Peri<'d, T>, 273 adc: crate::Peri<'d, T>,
@@ -164,9 +279,9 @@ pub enum Adc4Error {
164 DMAError, 279 DMAError,
165} 280}
166 281
167impl<'d, T: Instance> Adc4<'d, T> { 282impl<'d, T: Instance + super::AnyInstance> super::Adc<'d, T> {
168 /// Create a new ADC driver. 283 /// Create a new ADC driver.
169 pub fn new(adc: Peri<'d, T>) -> Self { 284 pub fn new_adc4(adc: Peri<'d, T>) -> Self {
170 rcc::enable_and_reset::<T>(); 285 rcc::enable_and_reset::<T>();
171 let prescaler = Prescaler::from_ker_ck(T::frequency()); 286 let prescaler = Prescaler::from_ker_ck(T::frequency());
172 287
@@ -200,7 +315,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
200 315
201 blocking_delay_us(1); 316 blocking_delay_us(1);
202 317
203 Self::enable(); 318 T::enable();
204 319
205 // single conversion mode, software trigger 320 // single conversion mode, software trigger
206 T::regs().cfgr1().modify(|w| { 321 T::regs().cfgr1().modify(|w| {
@@ -231,15 +346,8 @@ impl<'d, T: Instance> Adc4<'d, T> {
231 Self { adc } 346 Self { adc }
232 } 347 }
233 348
234 fn enable() {
235 T::regs().isr().write(|w| w.set_adrdy(true));
236 T::regs().cr().modify(|w| w.set_aden(true));
237 while !T::regs().isr().read().adrdy() {}
238 T::regs().isr().write(|w| w.set_adrdy(true));
239 }
240
241 /// Enable reading the voltage reference internal channel. 349 /// Enable reading the voltage reference internal channel.
242 pub fn enable_vrefint(&self) -> super::VrefInt { 350 pub fn enable_vrefint_adc4(&self) -> super::VrefInt {
243 T::regs().ccr().modify(|w| { 351 T::regs().ccr().modify(|w| {
244 w.set_vrefen(true); 352 w.set_vrefen(true);
245 }); 353 });
@@ -248,7 +356,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
248 } 356 }
249 357
250 /// Enable reading the temperature internal channel. 358 /// Enable reading the temperature internal channel.
251 pub fn enable_temperature(&self) -> super::Temperature { 359 pub fn enable_temperature_adc4(&self) -> super::Temperature {
252 T::regs().ccr().modify(|w| { 360 T::regs().ccr().modify(|w| {
253 w.set_vsensesel(true); 361 w.set_vsensesel(true);
254 }); 362 });
@@ -258,7 +366,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
258 366
259 /// Enable reading the vbat internal channel. 367 /// Enable reading the vbat internal channel.
260 #[cfg(stm32u5)] 368 #[cfg(stm32u5)]
261 pub fn enable_vbat(&self) -> super::Vbat { 369 pub fn enable_vbat_adc4(&self) -> super::Vbat {
262 T::regs().ccr().modify(|w| { 370 T::regs().ccr().modify(|w| {
263 w.set_vbaten(true); 371 w.set_vbaten(true);
264 }); 372 });
@@ -267,13 +375,13 @@ impl<'d, T: Instance> Adc4<'d, T> {
267 } 375 }
268 376
269 /// Enable reading the vbat internal channel. 377 /// Enable reading the vbat internal channel.
270 pub fn enable_vcore(&self) -> super::Vcore { 378 pub fn enable_vcore_adc4(&self) -> super::Vcore {
271 super::Vcore {} 379 super::Vcore {}
272 } 380 }
273 381
274 /// Enable reading the vbat internal channel. 382 /// Enable reading the vbat internal channel.
275 #[cfg(stm32u5)] 383 #[cfg(stm32u5)]
276 pub fn enable_dac_channel(&self, dac: DacChannel) -> super::Dac { 384 pub fn enable_dac_channel_adc4(&self, dac: DacChannel) -> super::Dac {
277 let mux; 385 let mux;
278 match dac { 386 match dac {
279 DacChannel::OUT1 => mux = false, 387 DacChannel::OUT1 => mux = false,
@@ -284,13 +392,13 @@ impl<'d, T: Instance> Adc4<'d, T> {
284 } 392 }
285 393
286 /// Set the ADC resolution. 394 /// Set the ADC resolution.
287 pub fn set_resolution(&mut self, resolution: Resolution) { 395 pub fn set_resolution_adc4(&mut self, resolution: Resolution) {
288 T::regs().cfgr1().modify(|w| w.set_res(resolution.into())); 396 T::regs().cfgr1().modify(|w| w.set_res(resolution.into()));
289 } 397 }
290 398
291 /// Set hardware averaging. 399 /// Set hardware averaging.
292 #[cfg(stm32u5)] 400 #[cfg(stm32u5)]
293 pub fn set_averaging(&mut self, averaging: Averaging) { 401 pub fn set_averaging_adc4(&mut self, averaging: Averaging) {
294 let (enable, samples, right_shift) = match averaging { 402 let (enable, samples, right_shift) = match averaging {
295 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, 0), 403 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, 0),
296 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, 1), 404 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, 1),
@@ -310,7 +418,7 @@ impl<'d, T: Instance> Adc4<'d, T> {
310 }) 418 })
311 } 419 }
312 #[cfg(stm32wba)] 420 #[cfg(stm32wba)]
313 pub fn set_averaging(&mut self, averaging: Averaging) { 421 pub fn set_averaging_adc4(&mut self, averaging: Averaging) {
314 let (enable, samples, right_shift) = match averaging { 422 let (enable, samples, right_shift) = match averaging {
315 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT0), 423 Averaging::Disabled => (false, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT0),
316 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT1), 424 Averaging::Samples2 => (true, OversamplingRatio::OVERSAMPLE2X, Ovss::SHIFT1),
@@ -329,168 +437,4 @@ impl<'d, T: Instance> Adc4<'d, T> {
329 w.set_ovse(enable) 437 w.set_ovse(enable)
330 }) 438 })
331 } 439 }
332
333 /// Read an ADC channel.
334 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
335 T::regs().smpr().modify(|w| {
336 w.set_smp(0, sample_time);
337 });
338
339 channel.setup();
340
341 // Select channel
342 #[cfg(stm32wba)]
343 {
344 T::regs().chselr().write_value(Chselr(0_u32));
345 T::regs().chselr().modify(|w| {
346 w.set_chsel0(channel.channel() as usize, true);
347 });
348 }
349 #[cfg(stm32u5)]
350 {
351 T::regs().chselrmod0().write_value(Chselr(0_u32));
352 T::regs().chselrmod0().modify(|w| {
353 w.set_chsel(channel.channel() as usize, true);
354 });
355 }
356
357 // Reset interrupts
358 T::regs().isr().modify(|reg| {
359 reg.set_eos(true);
360 reg.set_eoc(true);
361 });
362
363 // Start conversion
364 T::regs().cr().modify(|reg| {
365 reg.set_adstart(true);
366 });
367
368 while !T::regs().isr().read().eos() {
369 // spin
370 }
371
372 T::regs().dr().read().0 as u16
373 }
374
375 /// Read one or multiple ADC channels using DMA.
376 ///
377 /// `sequence` iterator and `readings` must have the same length.
378 /// The channels in `sequence` must be in ascending order.
379 ///
380 /// Example
381 /// ```rust,ignore
382 /// use embassy_stm32::adc::adc4;
383 /// use embassy_stm32::adc::AdcChannel;
384 ///
385 /// let mut adc4 = adc4::Adc4::new(p.ADC4);
386 /// let mut adc4_pin1 = p.PC1;
387 /// let mut adc4_pin2 = p.PC0;
388 /// let mut.into()d41 = adc4_pin1.into();
389 /// let mut.into()d42 = adc4_pin2.into();
390 /// let mut measurements = [0u16; 2];
391 /// // not that the channels must be in ascending order
392 /// adc4.read(
393 /// &mut p.GPDMA1_CH1,
394 /// [
395 /// &mut.into()d42,
396 /// &mut.into()d41,
397 /// ]
398 /// .into_iter(),
399 /// &mut measurements,
400 /// ).await.unwrap();
401 /// ```
402 pub async fn read(
403 &mut self,
404 rx_dma: Peri<'_, impl RxDma4<T>>,
405 sequence: impl ExactSizeIterator<Item = &mut AnyAdcChannel<T>>,
406 readings: &mut [u16],
407 ) -> Result<(), Adc4Error> {
408 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
409 assert!(
410 sequence.len() == readings.len(),
411 "Sequence length must be equal to readings length"
412 );
413
414 // Ensure no conversions are ongoing
415 Self::cancel_conversions();
416
417 T::regs().isr().modify(|reg| {
418 reg.set_ovr(true);
419 reg.set_eos(true);
420 reg.set_eoc(true);
421 });
422
423 T::regs().cfgr1().modify(|reg| {
424 reg.set_dmaen(true);
425 reg.set_dmacfg(Dmacfg::ONE_SHOT);
426 #[cfg(stm32u5)]
427 reg.set_chselrmod(false);
428 #[cfg(stm32wba)]
429 reg.set_chselrmod(Chselrmod::ENABLE_INPUT)
430 });
431
432 // Verify and activate sequence
433 let mut prev_channel: i16 = -1;
434 #[cfg(stm32wba)]
435 T::regs().chselr().write_value(Chselr(0_u32));
436 #[cfg(stm32u5)]
437 T::regs().chselrmod0().write_value(Chselr(0_u32));
438 for channel in sequence {
439 let channel_num = channel.channel;
440 if channel_num as i16 <= prev_channel {
441 return Err(Adc4Error::InvalidSequence);
442 };
443 prev_channel = channel_num as i16;
444
445 #[cfg(stm32wba)]
446 T::regs().chselr().modify(|w| {
447 w.set_chsel0(channel.channel as usize, true);
448 });
449 #[cfg(stm32u5)]
450 T::regs().chselrmod0().modify(|w| {
451 w.set_chsel(channel.channel as usize, true);
452 });
453 }
454
455 let request = rx_dma.request();
456 let transfer = unsafe {
457 Transfer::new_read(
458 rx_dma,
459 request,
460 T::regs().dr().as_ptr() as *mut u16,
461 readings,
462 Default::default(),
463 )
464 };
465
466 // Start conversion
467 T::regs().cr().modify(|reg| {
468 reg.set_adstart(true);
469 });
470
471 transfer.await;
472
473 // Ensure conversions are finished.
474 Self::cancel_conversions();
475
476 // Reset configuration.
477 T::regs().cfgr1().modify(|reg| {
478 reg.set_dmaen(false);
479 });
480
481 if T::regs().isr().read().ovr() {
482 Err(Adc4Error::DMAError)
483 } else {
484 Ok(())
485 }
486 }
487
488 fn cancel_conversions() {
489 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
490 T::regs().cr().modify(|reg| {
491 reg.set_adstp(true);
492 });
493 while T::regs().cr().read().adstart() {}
494 }
495 }
496} 440}
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 0a9f35a5b..71dc8acc0 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -12,7 +12,7 @@ use super::{
12 Adc, AnyAdcChannel, ConversionMode, Instance, RegularConversionMode, Resolution, RxDma, SampleTime, 12 Adc, AnyAdcChannel, ConversionMode, Instance, RegularConversionMode, Resolution, RxDma, SampleTime,
13 blocking_delay_us, 13 blocking_delay_us,
14}; 14};
15use crate::adc::SealedAdcChannel; 15use crate::adc::{AnyInstance, SealedAdcChannel};
16use crate::time::Hertz; 16use crate::time::Hertz;
17use crate::{Peri, pac, rcc}; 17use crate::{Peri, pac, rcc};
18 18
@@ -122,98 +122,12 @@ pub struct ConversionTrigger {
122 pub edge: Exten, 122 pub edge: Exten,
123} 123}
124 124
125impl<'d, T: Instance> Adc<'d, T> { 125impl<T: Instance> super::SealedAnyInstance for T {
126 /// Create a new ADC driver. 126 fn dr() -> *mut u16 {
127 pub fn new(adc: Peri<'d, T>, config: AdcConfig) -> Self { 127 T::regs().dr().as_ptr() as *mut u16
128 rcc::enable_and_reset::<T>();
129
130 let prescaler = Prescaler::from_ker_ck(T::frequency());
131
132 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
133
134 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
135 trace!("ADC frequency set to {}", frequency);
136
137 if frequency > MAX_ADC_CLK_FREQ {
138 panic!(
139 "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
140 MAX_ADC_CLK_FREQ.0 / 1_000_000
141 );
142 }
143
144 T::regs().cr().modify(|reg| {
145 reg.set_deeppwd(false);
146 reg.set_advregen(true);
147 });
148
149 blocking_delay_us(20);
150
151 T::regs().difsel().modify(|w| {
152 for n in 0..18 {
153 w.set_difsel(n, Difsel::SINGLE_ENDED);
154 }
155 });
156
157 T::regs().cr().modify(|w| {
158 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
159 });
160
161 T::regs().cr().modify(|w| w.set_adcal(true));
162
163 while T::regs().cr().read().adcal() {}
164
165 blocking_delay_us(20);
166
167 T::regs().cr().modify(|w| {
168 w.set_adcaldif(Adcaldif::DIFFERENTIAL);
169 });
170
171 T::regs().cr().modify(|w| w.set_adcal(true));
172
173 while T::regs().cr().read().adcal() {}
174
175 blocking_delay_us(20);
176
177 Self::enable();
178
179 // single conversion mode, software trigger
180 T::regs().cfgr().modify(|w| {
181 w.set_cont(false);
182 w.set_exten(Exten::DISABLED);
183 });
184
185 if let Some(dual) = config.dual_mode {
186 T::common_regs().ccr().modify(|reg| {
187 reg.set_dual(dual);
188 })
189 }
190
191 if let Some(resolution) = config.resolution {
192 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
193 }
194
195 #[cfg(stm32g4)]
196 if let Some(shift) = config.oversampling_shift {
197 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
198 }
199
200 #[cfg(stm32g4)]
201 if let Some(ratio) = config.oversampling_ratio {
202 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
203 }
204
205 #[cfg(stm32g4)]
206 if let Some((mode, trig_mode, enable)) = config.oversampling_mode {
207 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
208 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
209 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
210 }
211
212 Self { adc }
213 } 128 }
214 129
215 /// Enable the ADC 130 fn enable() {
216 pub(super) fn enable() {
217 // Make sure bits are off 131 // Make sure bits are off
218 while T::regs().cr().read().addis() { 132 while T::regs().cr().read().addis() {
219 // spin 133 // spin
@@ -234,15 +148,13 @@ impl<'d, T: Instance> Adc<'d, T> {
234 } 148 }
235 } 149 }
236 150
237 /// Start regular adc conversion 151 fn start() {
238 pub(super) fn start() {
239 T::regs().cr().modify(|reg| { 152 T::regs().cr().modify(|reg| {
240 reg.set_adstart(true); 153 reg.set_adstart(true);
241 }); 154 });
242 } 155 }
243 156
244 /// Stop regular conversions and disable DMA 157 fn stop() {
245 pub(super) fn stop() {
246 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 158 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
247 T::regs().cr().modify(|reg| { 159 T::regs().cr().modify(|reg| {
248 reg.set_adstp(Adstp::STOP); 160 reg.set_adstp(Adstp::STOP);
@@ -259,8 +171,7 @@ impl<'d, T: Instance> Adc<'d, T> {
259 }); 171 });
260 } 172 }
261 173
262 /// Perform a single conversion. 174 fn convert() -> u16 {
263 pub(super) fn convert() -> u16 {
264 T::regs().isr().modify(|reg| { 175 T::regs().isr().modify(|reg| {
265 reg.set_eos(true); 176 reg.set_eos(true);
266 reg.set_eoc(true); 177 reg.set_eoc(true);
@@ -278,7 +189,7 @@ impl<'d, T: Instance> Adc<'d, T> {
278 T::regs().dr().read().0 as u16 189 T::regs().dr().read().0 as u16
279 } 190 }
280 191
281 pub(super) fn configure_dma(conversion_mode: ConversionMode) { 192 fn configure_dma(conversion_mode: ConversionMode) {
282 T::regs().isr().modify(|reg| { 193 T::regs().isr().modify(|reg| {
283 reg.set_ovr(true); 194 reg.set_ovr(true);
284 }); 195 });
@@ -316,7 +227,7 @@ impl<'d, T: Instance> Adc<'d, T> {
316 } 227 }
317 } 228 }
318 229
319 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 230 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
320 // Set sequence length 231 // Set sequence length
321 T::regs().sqr1().modify(|w| { 232 T::regs().sqr1().modify(|w| {
322 w.set_l(sequence.len() as u8 - 1); 233 w.set_l(sequence.len() as u8 - 1);
@@ -374,6 +285,97 @@ impl<'d, T: Instance> Adc<'d, T> {
374 } 285 }
375 } 286 }
376 } 287 }
288}
289
290impl<'d, T: Instance + AnyInstance> Adc<'d, T> {
291 /// Create a new ADC driver.
292 pub fn new(adc: Peri<'d, T>, config: AdcConfig) -> Self {
293 rcc::enable_and_reset::<T>();
294
295 let prescaler = Prescaler::from_ker_ck(T::frequency());
296
297 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
298
299 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
300 trace!("ADC frequency set to {}", frequency);
301
302 if frequency > MAX_ADC_CLK_FREQ {
303 panic!(
304 "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
305 MAX_ADC_CLK_FREQ.0 / 1_000_000
306 );
307 }
308
309 T::regs().cr().modify(|reg| {
310 reg.set_deeppwd(false);
311 reg.set_advregen(true);
312 });
313
314 blocking_delay_us(20);
315
316 T::regs().difsel().modify(|w| {
317 for n in 0..18 {
318 w.set_difsel(n, Difsel::SINGLE_ENDED);
319 }
320 });
321
322 T::regs().cr().modify(|w| {
323 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
324 });
325
326 T::regs().cr().modify(|w| w.set_adcal(true));
327
328 while T::regs().cr().read().adcal() {}
329
330 blocking_delay_us(20);
331
332 T::regs().cr().modify(|w| {
333 w.set_adcaldif(Adcaldif::DIFFERENTIAL);
334 });
335
336 T::regs().cr().modify(|w| w.set_adcal(true));
337
338 while T::regs().cr().read().adcal() {}
339
340 blocking_delay_us(20);
341
342 T::enable();
343
344 // single conversion mode, software trigger
345 T::regs().cfgr().modify(|w| {
346 w.set_cont(false);
347 w.set_exten(Exten::DISABLED);
348 });
349
350 if let Some(dual) = config.dual_mode {
351 T::common_regs().ccr().modify(|reg| {
352 reg.set_dual(dual);
353 })
354 }
355
356 if let Some(resolution) = config.resolution {
357 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
358 }
359
360 #[cfg(stm32g4)]
361 if let Some(shift) = config.oversampling_shift {
362 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
363 }
364
365 #[cfg(stm32g4)]
366 if let Some(ratio) = config.oversampling_ratio {
367 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
368 }
369
370 #[cfg(stm32g4)]
371 if let Some((mode, trig_mode, enable)) = config.oversampling_mode {
372 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
373 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
374 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
375 }
376
377 Self { adc }
378 }
377 379
378 /// Enable reading the voltage reference internal channel. 380 /// Enable reading the voltage reference internal channel.
379 pub fn enable_vrefint(&self) -> super::VrefInt 381 pub fn enable_vrefint(&self) -> super::VrefInt
@@ -464,8 +466,8 @@ impl<'d, T: Instance> Adc<'d, T> {
464 NR_INJECTED_RANKS 466 NR_INJECTED_RANKS
465 ); 467 );
466 468
467 Self::stop(); 469 T::stop();
468 Self::enable(); 470 T::enable();
469 471
470 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); 472 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1));
471 473
@@ -536,7 +538,7 @@ impl<'d, T: Instance> Adc<'d, T> {
536 self, 538 self,
537 dma: Peri<'a, impl RxDma<T>>, 539 dma: Peri<'a, impl RxDma<T>>,
538 dma_buf: &'a mut [u16], 540 dma_buf: &'a mut [u16],
539 regular_sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>, 541 regular_sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, T::SampleTime)>,
540 regular_conversion_mode: RegularConversionMode, 542 regular_conversion_mode: RegularConversionMode,
541 injected_sequence: [(AnyAdcChannel<T>, SampleTime); N], 543 injected_sequence: [(AnyAdcChannel<T>, SampleTime); N],
542 injected_trigger: ConversionTrigger, 544 injected_trigger: ConversionTrigger,
diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs
index 7bb3a541c..ccaa5d1b2 100644
--- a/embassy-stm32/src/adc/injected.rs
+++ b/embassy-stm32/src/adc/injected.rs
@@ -5,9 +5,9 @@ use core::sync::atomic::{Ordering, compiler_fence};
5use embassy_hal_internal::Peri; 5use embassy_hal_internal::Peri;
6 6
7use super::{AnyAdcChannel, SampleTime}; 7use super::{AnyAdcChannel, SampleTime};
8use crate::adc::Adc;
9#[allow(unused_imports)] 8#[allow(unused_imports)]
10use crate::adc::Instance; 9use crate::adc::Instance;
10use crate::adc::{Adc, AnyInstance};
11 11
12/// Injected ADC sequence with owned channels. 12/// Injected ADC sequence with owned channels.
13pub struct InjectedAdc<T: Instance, const N: usize> { 13pub struct InjectedAdc<T: Instance, const N: usize> {
@@ -36,9 +36,9 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> {
36 } 36 }
37} 37}
38 38
39impl<T: Instance, const N: usize> Drop for InjectedAdc<T, N> { 39impl<T: Instance + AnyInstance, const N: usize> Drop for InjectedAdc<T, N> {
40 fn drop(&mut self) { 40 fn drop(&mut self) {
41 Adc::<T>::stop(); 41 T::stop();
42 compiler_fence(Ordering::SeqCst); 42 compiler_fence(Ordering::SeqCst);
43 } 43 }
44} 44}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index bf404d6ef..856c2e61e 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -41,15 +41,10 @@ pub use crate::pac::adc::vals::Res as Resolution;
41pub use crate::pac::adc::vals::SampleTime; 41pub use crate::pac::adc::vals::SampleTime;
42use crate::peripherals; 42use crate::peripherals;
43 43
44#[cfg(not(adc_wba))] 44dma_trait!(RxDma, AnyInstance);
45dma_trait!(RxDma, Instance);
46#[cfg(adc_u5)]
47dma_trait!(RxDma4, adc4::Instance);
48#[cfg(adc_wba)]
49dma_trait!(RxDma4, adc4::Instance);
50 45
51/// Analog to Digital driver. 46/// Analog to Digital driver.
52pub struct Adc<'d, T: Instance> { 47pub struct Adc<'d, T: AnyInstance> {
53 #[allow(unused)] 48 #[allow(unused)]
54 adc: crate::Peri<'d, T>, 49 adc: crate::Peri<'d, T>,
55} 50}
@@ -92,6 +87,49 @@ pub(crate) trait SealedAdcChannel<T> {
92 } 87 }
93} 88}
94 89
90// Temporary patch for ADCs that have not implemented the standard iface yet
91#[cfg(not(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4)))]
92trait_set::trait_set! {
93 pub trait AnyInstance = Instance;
94}
95
96#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4))]
97#[allow(dead_code)]
98pub trait BasicAnyInstance {
99 type SampleTime;
100}
101
102#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4))]
103#[allow(dead_code)]
104pub(self) trait SealedAnyInstance: BasicAnyInstance {
105 fn enable();
106 fn start();
107 fn stop();
108 fn convert() -> u16;
109 fn configure_dma(conversion_mode: ConversionMode);
110 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), Self::SampleTime)>);
111 fn dr() -> *mut u16;
112}
113
114// On chips without ADC4, AnyInstance is an Instance
115#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_g4))]
116#[allow(private_bounds)]
117pub trait AnyInstance: SealedAnyInstance + Instance {}
118
119// On chips with ADC4, AnyInstance is an Instance or adc4::Instance
120#[cfg(any(adc_v4, adc_u5, adc_wba))]
121#[allow(private_bounds)]
122pub trait AnyInstance: SealedAnyInstance + crate::PeripheralType + crate::rcc::RccPeripheral {}
123
124// Implement AnyInstance automatically for SealedAnyInstance
125#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4))]
126impl<T: SealedAnyInstance + Instance> BasicAnyInstance for T {
127 type SampleTime = SampleTime;
128}
129
130#[cfg(any(adc_v2, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_g4))]
131impl<T: SealedAnyInstance + Instance> AnyInstance for T {}
132
95/// Performs a busy-wait delay for a specified number of microseconds. 133/// Performs a busy-wait delay for a specified number of microseconds.
96#[allow(unused)] 134#[allow(unused)]
97pub(crate) fn blocking_delay_us(us: u32) { 135pub(crate) fn blocking_delay_us(us: u32) {
@@ -110,16 +148,18 @@ pub(crate) fn blocking_delay_us(us: u32) {
110 } 148 }
111} 149}
112 150
113#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))] 151#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba))]
114pub(self) enum ConversionMode { 152#[allow(dead_code)]
115 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))] 153pub(crate) enum ConversionMode {
154 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba))]
116 Singular, 155 Singular,
117 #[allow(dead_code)] 156 #[allow(dead_code)]
118 Repeated(RegularConversionMode), 157 Repeated(RegularConversionMode),
119} 158}
120 159
121#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))] 160#[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba))]
122// Conversion mode for regular ADC channels 161// Conversion mode for regular ADC channels
162#[allow(dead_code)]
123#[derive(Copy, Clone)] 163#[derive(Copy, Clone)]
124pub enum RegularConversionMode { 164pub enum RegularConversionMode {
125 // Samples as fast as possible 165 // Samples as fast as possible
@@ -129,21 +169,21 @@ pub enum RegularConversionMode {
129 Triggered(ConversionTrigger), 169 Triggered(ConversionTrigger),
130} 170}
131 171
132impl<'d, T: Instance> Adc<'d, T> { 172impl<'d, T: AnyInstance> Adc<'d, T> {
133 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u5, adc_v4))] 173 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u5, adc_v4, adc_wba))]
134 /// Read an ADC pin. 174 /// Read an ADC pin.
135 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { 175 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: T::SampleTime) -> u16 {
136 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))] 176 #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
137 channel.setup(); 177 channel.setup();
138 178
139 #[cfg(not(adc_v4))] 179 #[cfg(not(adc_v4))]
140 Self::enable(); 180 T::enable();
141 Self::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter()); 181 T::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter());
142 182
143 Self::convert() 183 T::convert()
144 } 184 }
145 185
146 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))] 186 #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba))]
147 /// Read one or multiple ADC regular channels using DMA. 187 /// Read one or multiple ADC regular channels using DMA.
148 /// 188 ///
149 /// `sequence` iterator and `readings` must have the same length. 189 /// `sequence` iterator and `readings` must have the same length.
@@ -175,7 +215,7 @@ impl<'d, T: Instance> Adc<'d, T> {
175 pub async fn read( 215 pub async fn read(
176 &mut self, 216 &mut self,
177 rx_dma: embassy_hal_internal::Peri<'_, impl RxDma<T>>, 217 rx_dma: embassy_hal_internal::Peri<'_, impl RxDma<T>>,
178 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>, 218 sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, T::SampleTime)>,
179 readings: &mut [u16], 219 readings: &mut [u16],
180 ) { 220 ) {
181 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); 221 assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty");
@@ -189,33 +229,26 @@ impl<'d, T: Instance> Adc<'d, T> {
189 ); 229 );
190 230
191 // Ensure no conversions are ongoing and ADC is enabled. 231 // Ensure no conversions are ongoing and ADC is enabled.
192 Self::stop(); 232 T::stop();
193 Self::enable(); 233 T::enable();
194 234
195 Self::configure_sequence( 235 T::configure_sequence(
196 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), 236 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
197 ); 237 );
198 238
199 Self::configure_dma(ConversionMode::Singular); 239 T::configure_dma(ConversionMode::Singular);
200 240
201 let request = rx_dma.request(); 241 let request = rx_dma.request();
202 let transfer = unsafe { 242 let transfer =
203 crate::dma::Transfer::new_read( 243 unsafe { crate::dma::Transfer::new_read(rx_dma, request, T::dr(), readings, Default::default()) };
204 rx_dma,
205 request,
206 T::regs().dr().as_ptr() as *mut u16,
207 readings,
208 Default::default(),
209 )
210 };
211 244
212 Self::start(); 245 T::start();
213 246
214 // Wait for conversion sequence to finish. 247 // Wait for conversion sequence to finish.
215 transfer.await; 248 transfer.await;
216 249
217 // Ensure conversions are finished. 250 // Ensure conversions are finished.
218 Self::stop(); 251 T::stop();
219 } 252 }
220 253
221 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))] 254 #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))]
@@ -244,7 +277,7 @@ impl<'d, T: Instance> Adc<'d, T> {
244 self, 277 self,
245 dma: embassy_hal_internal::Peri<'a, impl RxDma<T>>, 278 dma: embassy_hal_internal::Peri<'a, impl RxDma<T>>,
246 dma_buf: &'a mut [u16], 279 dma_buf: &'a mut [u16],
247 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>, 280 sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, T::SampleTime)>,
248 mode: RegularConversionMode, 281 mode: RegularConversionMode,
249 ) -> RingBufferedAdc<'a, T> { 282 ) -> RingBufferedAdc<'a, T> {
250 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); 283 assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
@@ -254,15 +287,15 @@ impl<'d, T: Instance> Adc<'d, T> {
254 "Asynchronous read sequence cannot be more than 16 in length" 287 "Asynchronous read sequence cannot be more than 16 in length"
255 ); 288 );
256 // reset conversions and enable the adc 289 // reset conversions and enable the adc
257 Self::stop(); 290 T::stop();
258 Self::enable(); 291 T::enable();
259 292
260 //adc side setup 293 //adc side setup
261 Self::configure_sequence( 294 T::configure_sequence(
262 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), 295 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
263 ); 296 );
264 297
265 Self::configure_dma(ConversionMode::Repeated(mode)); 298 T::configure_dma(ConversionMode::Repeated(mode));
266 299
267 core::mem::forget(self); 300 core::mem::forget(self);
268 301
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs
index 62ea0d3a2..a56f8ca0b 100644
--- a/embassy-stm32/src/adc/ringbuffered.rs
+++ b/embassy-stm32/src/adc/ringbuffered.rs
@@ -4,7 +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; 7use crate::adc::AnyInstance;
8#[allow(unused_imports)] 8#[allow(unused_imports)]
9use crate::adc::{Instance, RxDma}; 9use crate::adc::{Instance, RxDma};
10#[allow(unused_imports)] 10#[allow(unused_imports)]
@@ -19,7 +19,7 @@ pub struct RingBufferedAdc<'d, T: Instance> {
19 ring_buf: ReadableRingBuffer<'d, u16>, 19 ring_buf: ReadableRingBuffer<'d, u16>,
20} 20}
21 21
22impl<'d, T: Instance> RingBufferedAdc<'d, T> { 22impl<'d, T: Instance + AnyInstance> RingBufferedAdc<'d, T> {
23 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 {
24 //dma side setup 24 //dma side setup
25 let opts = TransferOptions { 25 let opts = TransferOptions {
@@ -45,11 +45,11 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
45 compiler_fence(Ordering::SeqCst); 45 compiler_fence(Ordering::SeqCst);
46 self.ring_buf.start(); 46 self.ring_buf.start();
47 47
48 Adc::<T>::start(); 48 T::start();
49 } 49 }
50 50
51 pub fn stop(&mut self) { 51 pub fn stop(&mut self) {
52 Adc::<T>::stop(); 52 T::stop();
53 53
54 self.ring_buf.request_pause(); 54 self.ring_buf.request_pause();
55 55
@@ -170,9 +170,9 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
170 } 170 }
171} 171}
172 172
173impl<T: Instance> Drop for RingBufferedAdc<'_, T> { 173impl<T: Instance + AnyInstance> Drop for RingBufferedAdc<'_, T> {
174 fn drop(&mut self) { 174 fn drop(&mut self) {
175 Adc::<T>::stop(); 175 T::stop();
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 2f9fabafb..4065f89a7 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -91,35 +91,14 @@ pub struct AdcConfig {
91 resolution: Option<Resolution>, 91 resolution: Option<Resolution>,
92} 92}
93 93
94impl<'d, T> Adc<'d, T> 94impl<T: Instance> super::SealedAnyInstance for T {
95where 95 fn dr() -> *mut u16 {
96 T: Instance, 96 T::regs().dr().as_ptr() as *mut u16
97{
98 pub fn new(adc: Peri<'d, T>) -> Self {
99 Self::new_with_config(adc, Default::default())
100 }
101
102 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
103 rcc::enable_and_reset::<T>();
104
105 let presc = Prescaler::from_pclk2(T::frequency());
106 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));
107 T::regs().cr2().modify(|reg| {
108 reg.set_adon(true);
109 });
110
111 blocking_delay_us(3);
112
113 if let Some(resolution) = config.resolution {
114 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
115 }
116
117 Self { adc }
118 } 97 }
119 98
120 pub(super) fn enable() {} 99 fn enable() {}
121 100
122 pub(super) fn start() { 101 fn start() {
123 // Begin ADC conversions 102 // Begin ADC conversions
124 T::regs().cr2().modify(|reg| { 103 T::regs().cr2().modify(|reg| {
125 reg.set_adon(true); 104 reg.set_adon(true);
@@ -127,7 +106,7 @@ where
127 }); 106 });
128 } 107 }
129 108
130 pub(super) fn stop() { 109 fn stop() {
131 let r = T::regs(); 110 let r = T::regs();
132 111
133 // Stop ADC 112 // Stop ADC
@@ -152,7 +131,7 @@ where
152 compiler_fence(Ordering::SeqCst); 131 compiler_fence(Ordering::SeqCst);
153 } 132 }
154 133
155 pub(super) fn convert() -> u16 { 134 fn convert() -> u16 {
156 // clear end of conversion flag 135 // clear end of conversion flag
157 T::regs().sr().modify(|reg| { 136 T::regs().sr().modify(|reg| {
158 reg.set_eoc(false); 137 reg.set_eoc(false);
@@ -173,7 +152,7 @@ where
173 T::regs().dr().read().0 as u16 152 T::regs().dr().read().0 as u16
174 } 153 }
175 154
176 pub(super) fn configure_dma(conversion_mode: ConversionMode) { 155 fn configure_dma(conversion_mode: ConversionMode) {
177 match conversion_mode { 156 match conversion_mode {
178 ConversionMode::Repeated(_) => { 157 ConversionMode::Repeated(_) => {
179 let r = T::regs(); 158 let r = T::regs();
@@ -210,7 +189,7 @@ where
210 } 189 }
211 } 190 }
212 191
213 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 192 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
214 T::regs().cr2().modify(|reg| { 193 T::regs().cr2().modify(|reg| {
215 reg.set_adon(true); 194 reg.set_adon(true);
216 }); 195 });
@@ -232,6 +211,33 @@ where
232 } 211 }
233 } 212 }
234 } 213 }
214}
215
216impl<'d, T> Adc<'d, T>
217where
218 T: Instance,
219{
220 pub fn new(adc: Peri<'d, T>) -> Self {
221 Self::new_with_config(adc, Default::default())
222 }
223
224 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
225 rcc::enable_and_reset::<T>();
226
227 let presc = Prescaler::from_pclk2(T::frequency());
228 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));
229 T::regs().cr2().modify(|reg| {
230 reg.set_adon(true);
231 });
232
233 blocking_delay_us(3);
234
235 if let Some(resolution) = config.resolution {
236 T::regs().cr1().modify(|reg| reg.set_res(resolution.into()));
237 }
238
239 Self { adc }
240 }
235 241
236 /// Enables internal voltage reference and returns [VrefInt], which can be used in 242 /// Enables internal voltage reference and returns [VrefInt], which can be used in
237 /// [Adc::read_internal()] to perform conversion. 243 /// [Adc::read_internal()] to perform conversion.
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 62b5043ee..4cce1dac3 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -161,152 +161,13 @@ pub struct AdcConfig {
161 pub averaging: Option<Averaging>, 161 pub averaging: Option<Averaging>,
162} 162}
163 163
164impl<'d, T: Instance> Adc<'d, T> { 164impl<T: Instance> super::SealedAnyInstance for T {
165 /// Enable the voltage regulator 165 fn dr() -> *mut u16 {
166 fn init_regulator() { 166 T::regs().dr().as_ptr() as *mut u16
167 rcc::enable_and_reset::<T>();
168 T::regs().cr().modify(|reg| {
169 #[cfg(not(any(adc_g0, adc_u0)))]
170 reg.set_deeppwd(false);
171 reg.set_advregen(true);
172 });
173
174 // If this is false then each ADC_CHSELR bit enables an input channel.
175 // This is the reset value, so has no effect.
176 #[cfg(any(adc_g0, adc_u0))]
177 T::regs().cfgr1().modify(|reg| {
178 reg.set_chselrmod(false);
179 });
180
181 blocking_delay_us(20);
182 }
183
184 /// Calibrate to remove conversion offset
185 fn init_calibrate() {
186 T::regs().cr().modify(|reg| {
187 reg.set_adcal(true);
188 });
189
190 while T::regs().cr().read().adcal() {
191 // spin
192 }
193
194 blocking_delay_us(1);
195 }
196
197 /// Initialize the ADC leaving any analog clock at reset value.
198 /// For G0 and WL, this is the async clock without prescaler.
199 pub fn new(adc: Peri<'d, T>) -> Self {
200 Self::init_regulator();
201 Self::init_calibrate();
202 Self { adc }
203 }
204
205 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
206 #[cfg(not(adc_g0))]
207 let s = Self::new(adc);
208
209 #[cfg(adc_g0)]
210 let s = match config.clock {
211 Some(clock) => Self::new_with_clock(adc, clock),
212 None => Self::new(adc),
213 };
214
215 #[cfg(any(adc_g0, adc_u0, adc_v3))]
216 if let Some(shift) = config.oversampling_shift {
217 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
218 }
219
220 #[cfg(any(adc_g0, adc_u0, adc_v3))]
221 if let Some(ratio) = config.oversampling_ratio {
222 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
223 }
224
225 #[cfg(any(adc_g0, adc_u0))]
226 if let Some(enable) = config.oversampling_enable {
227 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable));
228 }
229
230 #[cfg(adc_v3)]
231 if let Some((mode, trig_mode, enable)) = config.oversampling_mode {
232 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
233 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
234 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
235 }
236
237 if let Some(resolution) = config.resolution {
238 #[cfg(not(any(adc_g0, adc_u0)))]
239 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
240 #[cfg(any(adc_g0, adc_u0))]
241 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
242 }
243
244 if let Some(averaging) = config.averaging {
245 let (enable, samples, right_shift) = match averaging {
246 Averaging::Disabled => (false, 0, 0),
247 Averaging::Samples2 => (true, 0, 1),
248 Averaging::Samples4 => (true, 1, 2),
249 Averaging::Samples8 => (true, 2, 3),
250 Averaging::Samples16 => (true, 3, 4),
251 Averaging::Samples32 => (true, 4, 5),
252 Averaging::Samples64 => (true, 5, 6),
253 Averaging::Samples128 => (true, 6, 7),
254 Averaging::Samples256 => (true, 7, 8),
255 };
256 T::regs().cfgr2().modify(|reg| {
257 #[cfg(not(any(adc_g0, adc_u0)))]
258 reg.set_rovse(enable);
259 #[cfg(any(adc_g0, adc_u0))]
260 reg.set_ovse(enable);
261 #[cfg(any(adc_h5, adc_h7rs))]
262 reg.set_ovsr(samples.into());
263 #[cfg(not(any(adc_h5, adc_h7rs)))]
264 reg.set_ovsr(samples.into());
265 reg.set_ovss(right_shift.into());
266 })
267 }
268
269 s
270 }
271
272 #[cfg(adc_g0)]
273 /// Initialize ADC with explicit clock for the analog ADC
274 pub fn new_with_clock(adc: Peri<'d, T>, clock: Clock) -> Self {
275 Self::init_regulator();
276
277 #[cfg(any(stm32wl5x))]
278 {
279 // Reset value 0 is actually _No clock selected_ in the STM32WL5x reference manual
280 let async_clock_available = pac::RCC.ccipr().read().adcsel() != pac::rcc::vals::Adcsel::_RESERVED_0;
281 match clock {
282 Clock::Async { div: _ } => {
283 assert!(async_clock_available);
284 }
285 Clock::Sync { div: _ } => {
286 if async_clock_available {
287 warn!("Not using configured ADC clock");
288 }
289 }
290 }
291 }
292 match clock {
293 Clock::Async { div } => T::regs().ccr().modify(|reg| reg.set_presc(div)),
294 Clock::Sync { div } => T::regs().cfgr2().modify(|reg| {
295 reg.set_ckmode(match div {
296 CkModePclk::DIV1 => Ckmode::PCLK,
297 CkModePclk::DIV2 => Ckmode::PCLK_DIV2,
298 CkModePclk::DIV4 => Ckmode::PCLK_DIV4,
299 })
300 }),
301 }
302
303 Self::init_calibrate();
304
305 Self { adc }
306 } 167 }
307 168
308 // Enable ADC only when it is not already running. 169 // Enable ADC only when it is not already running.
309 pub(super) fn enable() { 170 fn enable() {
310 // Make sure bits are off 171 // Make sure bits are off
311 while T::regs().cr().read().addis() { 172 while T::regs().cr().read().addis() {
312 // spin 173 // spin
@@ -327,7 +188,7 @@ impl<'d, T: Instance> Adc<'d, T> {
327 } 188 }
328 } 189 }
329 190
330 pub(super) fn start() { 191 fn start() {
331 #[cfg(any(adc_v3, adc_g0, adc_u0))] 192 #[cfg(any(adc_v3, adc_g0, adc_u0))]
332 { 193 {
333 // Start adc conversion 194 // Start adc conversion
@@ -337,7 +198,7 @@ impl<'d, T: Instance> Adc<'d, T> {
337 } 198 }
338 } 199 }
339 200
340 pub(super) fn stop() { 201 fn stop() {
341 #[cfg(any(adc_v3, adc_g0, adc_u0))] 202 #[cfg(any(adc_v3, adc_g0, adc_u0))]
342 { 203 {
343 // Ensure conversions are finished. 204 // Ensure conversions are finished.
@@ -363,7 +224,7 @@ impl<'d, T: Instance> Adc<'d, T> {
363 } 224 }
364 225
365 /// Perform a single conversion. 226 /// Perform a single conversion.
366 pub(super) fn convert() -> u16 { 227 fn convert() -> u16 {
367 // Some models are affected by an erratum: 228 // Some models are affected by an erratum:
368 // If we perform conversions slower than 1 kHz, the first read ADC value can be 229 // If we perform conversions slower than 1 kHz, the first read ADC value can be
369 // corrupted, so we discard it and measure again. 230 // corrupted, so we discard it and measure again.
@@ -395,7 +256,7 @@ impl<'d, T: Instance> Adc<'d, T> {
395 T::regs().dr().read().0 as u16 256 T::regs().dr().read().0 as u16
396 } 257 }
397 258
398 pub(super) fn configure_dma(conversion_mode: ConversionMode) { 259 fn configure_dma(conversion_mode: ConversionMode) {
399 // Set continuous mode with oneshot dma. 260 // Set continuous mode with oneshot dma.
400 // Clear overrun flag before starting transfer. 261 // Clear overrun flag before starting transfer.
401 T::regs().isr().modify(|reg| { 262 T::regs().isr().modify(|reg| {
@@ -419,7 +280,7 @@ impl<'d, T: Instance> Adc<'d, T> {
419 }); 280 });
420 } 281 }
421 282
422 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 283 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
423 // Set sequence length 284 // Set sequence length
424 #[cfg(not(any(adc_g0, adc_u0)))] 285 #[cfg(not(any(adc_g0, adc_u0)))]
425 T::regs().sqr1().modify(|w| { 286 T::regs().sqr1().modify(|w| {
@@ -532,6 +393,151 @@ impl<'d, T: Instance> Adc<'d, T> {
532 }); 393 });
533 } 394 }
534 } 395 }
396}
397
398impl<'d, T: Instance> Adc<'d, T> {
399 /// Enable the voltage regulator
400 fn init_regulator() {
401 rcc::enable_and_reset::<T>();
402 T::regs().cr().modify(|reg| {
403 #[cfg(not(any(adc_g0, adc_u0)))]
404 reg.set_deeppwd(false);
405 reg.set_advregen(true);
406 });
407
408 // If this is false then each ADC_CHSELR bit enables an input channel.
409 // This is the reset value, so has no effect.
410 #[cfg(any(adc_g0, adc_u0))]
411 T::regs().cfgr1().modify(|reg| {
412 reg.set_chselrmod(false);
413 });
414
415 blocking_delay_us(20);
416 }
417
418 /// Calibrate to remove conversion offset
419 fn init_calibrate() {
420 T::regs().cr().modify(|reg| {
421 reg.set_adcal(true);
422 });
423
424 while T::regs().cr().read().adcal() {
425 // spin
426 }
427
428 blocking_delay_us(1);
429 }
430
431 /// Initialize the ADC leaving any analog clock at reset value.
432 /// For G0 and WL, this is the async clock without prescaler.
433 pub fn new(adc: Peri<'d, T>) -> Self {
434 Self::init_regulator();
435 Self::init_calibrate();
436 Self { adc }
437 }
438
439 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
440 #[cfg(not(adc_g0))]
441 let s = Self::new(adc);
442
443 #[cfg(adc_g0)]
444 let s = match config.clock {
445 Some(clock) => Self::new_with_clock(adc, clock),
446 None => Self::new(adc),
447 };
448
449 #[cfg(any(adc_g0, adc_u0, adc_v3))]
450 if let Some(shift) = config.oversampling_shift {
451 T::regs().cfgr2().modify(|reg| reg.set_ovss(shift));
452 }
453
454 #[cfg(any(adc_g0, adc_u0, adc_v3))]
455 if let Some(ratio) = config.oversampling_ratio {
456 T::regs().cfgr2().modify(|reg| reg.set_ovsr(ratio));
457 }
458
459 #[cfg(any(adc_g0, adc_u0))]
460 if let Some(enable) = config.oversampling_enable {
461 T::regs().cfgr2().modify(|reg| reg.set_ovse(enable));
462 }
463
464 #[cfg(adc_v3)]
465 if let Some((mode, trig_mode, enable)) = config.oversampling_mode {
466 T::regs().cfgr2().modify(|reg| reg.set_trovs(trig_mode));
467 T::regs().cfgr2().modify(|reg| reg.set_rovsm(mode));
468 T::regs().cfgr2().modify(|reg| reg.set_rovse(enable));
469 }
470
471 if let Some(resolution) = config.resolution {
472 #[cfg(not(any(adc_g0, adc_u0)))]
473 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
474 #[cfg(any(adc_g0, adc_u0))]
475 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
476 }
477
478 if let Some(averaging) = config.averaging {
479 let (enable, samples, right_shift) = match averaging {
480 Averaging::Disabled => (false, 0, 0),
481 Averaging::Samples2 => (true, 0, 1),
482 Averaging::Samples4 => (true, 1, 2),
483 Averaging::Samples8 => (true, 2, 3),
484 Averaging::Samples16 => (true, 3, 4),
485 Averaging::Samples32 => (true, 4, 5),
486 Averaging::Samples64 => (true, 5, 6),
487 Averaging::Samples128 => (true, 6, 7),
488 Averaging::Samples256 => (true, 7, 8),
489 };
490 T::regs().cfgr2().modify(|reg| {
491 #[cfg(not(any(adc_g0, adc_u0)))]
492 reg.set_rovse(enable);
493 #[cfg(any(adc_g0, adc_u0))]
494 reg.set_ovse(enable);
495 #[cfg(any(adc_h5, adc_h7rs))]
496 reg.set_ovsr(samples.into());
497 #[cfg(not(any(adc_h5, adc_h7rs)))]
498 reg.set_ovsr(samples.into());
499 reg.set_ovss(right_shift.into());
500 })
501 }
502
503 s
504 }
505
506 #[cfg(adc_g0)]
507 /// Initialize ADC with explicit clock for the analog ADC
508 pub fn new_with_clock(adc: Peri<'d, T>, clock: Clock) -> Self {
509 Self::init_regulator();
510
511 #[cfg(any(stm32wl5x))]
512 {
513 // Reset value 0 is actually _No clock selected_ in the STM32WL5x reference manual
514 let async_clock_available = pac::RCC.ccipr().read().adcsel() != pac::rcc::vals::Adcsel::_RESERVED_0;
515 match clock {
516 Clock::Async { div: _ } => {
517 assert!(async_clock_available);
518 }
519 Clock::Sync { div: _ } => {
520 if async_clock_available {
521 warn!("Not using configured ADC clock");
522 }
523 }
524 }
525 }
526 match clock {
527 Clock::Async { div } => T::regs().ccr().modify(|reg| reg.set_presc(div)),
528 Clock::Sync { div } => T::regs().cfgr2().modify(|reg| {
529 reg.set_ckmode(match div {
530 CkModePclk::DIV1 => Ckmode::PCLK,
531 CkModePclk::DIV2 => Ckmode::PCLK_DIV2,
532 CkModePclk::DIV4 => Ckmode::PCLK_DIV4,
533 })
534 }),
535 }
536
537 Self::init_calibrate();
538
539 Self { adc }
540 }
535 541
536 pub fn enable_vrefint(&self) -> VrefInt { 542 pub fn enable_vrefint(&self) -> VrefInt {
537 #[cfg(not(any(adc_g0, adc_u0)))] 543 #[cfg(not(any(adc_g0, adc_u0)))]
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 9be6bcd0b..43eb16fd5 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -151,124 +151,26 @@ pub struct AdcConfig {
151 pub averaging: Option<Averaging>, 151 pub averaging: Option<Averaging>,
152} 152}
153 153
154impl<'d, T: Instance> Adc<'d, T> { 154impl<T: Instance> super::SealedAnyInstance for T {
155 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self { 155 fn dr() -> *mut u16 {
156 let s = Self::new(adc); 156 T::regs().dr().as_ptr() as *mut u16
157
158 // Set the ADC resolution.
159 if let Some(resolution) = config.resolution {
160 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
161 }
162
163 // Set hardware averaging.
164 if let Some(averaging) = config.averaging {
165 let (enable, samples, right_shift) = match averaging {
166 Averaging::Disabled => (false, 0, 0),
167 Averaging::Samples2 => (true, 1, 1),
168 Averaging::Samples4 => (true, 3, 2),
169 Averaging::Samples8 => (true, 7, 3),
170 Averaging::Samples16 => (true, 15, 4),
171 Averaging::Samples32 => (true, 31, 5),
172 Averaging::Samples64 => (true, 63, 6),
173 Averaging::Samples128 => (true, 127, 7),
174 Averaging::Samples256 => (true, 255, 8),
175 Averaging::Samples512 => (true, 511, 9),
176 Averaging::Samples1024 => (true, 1023, 10),
177 };
178
179 T::regs().cfgr2().modify(|reg| {
180 reg.set_rovse(enable);
181 reg.set_ovsr(samples);
182 reg.set_ovss(right_shift);
183 })
184 }
185
186 s
187 } 157 }
188 158
189 /// Create a new ADC driver. 159 fn enable() {
190 pub fn new(adc: Peri<'d, T>) -> Self {
191 rcc::enable_and_reset::<T>();
192
193 let prescaler = Prescaler::from_ker_ck(T::frequency());
194
195 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
196
197 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
198 info!("ADC frequency set to {}", frequency);
199
200 if frequency > MAX_ADC_CLK_FREQ {
201 panic!(
202 "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
203 MAX_ADC_CLK_FREQ.0 / 1_000_000
204 );
205 }
206
207 #[cfg(stm32h7)]
208 {
209 let boost = if frequency < Hertz::khz(6_250) {
210 Boost::LT6_25
211 } else if frequency < Hertz::khz(12_500) {
212 Boost::LT12_5
213 } else if frequency < Hertz::mhz(25) {
214 Boost::LT25
215 } else {
216 Boost::LT50
217 };
218 T::regs().cr().modify(|w| w.set_boost(boost));
219 }
220
221 T::regs().cr().modify(|reg| {
222 reg.set_deeppwd(false);
223 reg.set_advregen(true);
224 });
225
226 blocking_delay_us(10);
227
228 T::regs().difsel().modify(|w| {
229 for n in 0..20 {
230 w.set_difsel(n, Difsel::SINGLE_ENDED);
231 }
232 });
233
234 T::regs().cr().modify(|w| {
235 #[cfg(not(adc_u5))]
236 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
237 w.set_adcallin(true);
238 });
239
240 T::regs().cr().modify(|w| w.set_adcal(true));
241
242 while T::regs().cr().read().adcal() {}
243
244 blocking_delay_us(1);
245
246 Self::enable();
247
248 // single conversion mode, software trigger
249 T::regs().cfgr().modify(|w| {
250 w.set_cont(false);
251 w.set_exten(Exten::DISABLED);
252 });
253
254 Self { adc }
255 }
256
257 pub(super) fn enable() {
258 T::regs().isr().write(|w| w.set_adrdy(true)); 160 T::regs().isr().write(|w| w.set_adrdy(true));
259 T::regs().cr().modify(|w| w.set_aden(true)); 161 T::regs().cr().modify(|w| w.set_aden(true));
260 while !T::regs().isr().read().adrdy() {} 162 while !T::regs().isr().read().adrdy() {}
261 T::regs().isr().write(|w| w.set_adrdy(true)); 163 T::regs().isr().write(|w| w.set_adrdy(true));
262 } 164 }
263 165
264 pub(super) fn start() { 166 fn start() {
265 // Start conversion 167 // Start conversion
266 T::regs().cr().modify(|reg| { 168 T::regs().cr().modify(|reg| {
267 reg.set_adstart(true); 169 reg.set_adstart(true);
268 }); 170 });
269 } 171 }
270 172
271 pub(super) fn stop() { 173 fn stop() {
272 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 174 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
273 T::regs().cr().modify(|reg| { 175 T::regs().cr().modify(|reg| {
274 reg.set_adstp(Adstp::STOP); 176 reg.set_adstp(Adstp::STOP);
@@ -283,7 +185,7 @@ impl<'d, T: Instance> Adc<'d, T> {
283 }); 185 });
284 } 186 }
285 187
286 pub(super) fn convert() -> u16 { 188 fn convert() -> u16 {
287 T::regs().isr().modify(|reg| { 189 T::regs().isr().modify(|reg| {
288 reg.set_eos(true); 190 reg.set_eos(true);
289 reg.set_eoc(true); 191 reg.set_eoc(true);
@@ -301,7 +203,7 @@ impl<'d, T: Instance> Adc<'d, T> {
301 T::regs().dr().read().0 as u16 203 T::regs().dr().read().0 as u16
302 } 204 }
303 205
304 pub(super) fn configure_dma(conversion_mode: ConversionMode) { 206 fn configure_dma(conversion_mode: ConversionMode) {
305 match conversion_mode { 207 match conversion_mode {
306 ConversionMode::Singular => { 208 ConversionMode::Singular => {
307 T::regs().isr().modify(|reg| { 209 T::regs().isr().modify(|reg| {
@@ -316,7 +218,7 @@ impl<'d, T: Instance> Adc<'d, T> {
316 } 218 }
317 } 219 }
318 220
319 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) { 221 fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
320 // Set sequence length 222 // Set sequence length
321 T::regs().sqr1().modify(|w| { 223 T::regs().sqr1().modify(|w| {
322 w.set_l(sequence.len() as u8 - 1); 224 w.set_l(sequence.len() as u8 - 1);
@@ -366,6 +268,110 @@ impl<'d, T: Instance> Adc<'d, T> {
366 } 268 }
367 } 269 }
368 } 270 }
271}
272
273impl<'d, T: Instance + super::AnyInstance> Adc<'d, T> {
274 pub fn new_with_config(adc: Peri<'d, T>, config: AdcConfig) -> Self {
275 let s = Self::new(adc);
276
277 // Set the ADC resolution.
278 if let Some(resolution) = config.resolution {
279 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
280 }
281
282 // Set hardware averaging.
283 if let Some(averaging) = config.averaging {
284 let (enable, samples, right_shift) = match averaging {
285 Averaging::Disabled => (false, 0, 0),
286 Averaging::Samples2 => (true, 1, 1),
287 Averaging::Samples4 => (true, 3, 2),
288 Averaging::Samples8 => (true, 7, 3),
289 Averaging::Samples16 => (true, 15, 4),
290 Averaging::Samples32 => (true, 31, 5),
291 Averaging::Samples64 => (true, 63, 6),
292 Averaging::Samples128 => (true, 127, 7),
293 Averaging::Samples256 => (true, 255, 8),
294 Averaging::Samples512 => (true, 511, 9),
295 Averaging::Samples1024 => (true, 1023, 10),
296 };
297
298 T::regs().cfgr2().modify(|reg| {
299 reg.set_rovse(enable);
300 reg.set_ovsr(samples);
301 reg.set_ovss(right_shift);
302 })
303 }
304
305 s
306 }
307
308 /// Create a new ADC driver.
309 pub fn new(adc: Peri<'d, T>) -> Self {
310 rcc::enable_and_reset::<T>();
311
312 let prescaler = Prescaler::from_ker_ck(T::frequency());
313
314 T::common_regs().ccr().modify(|w| w.set_presc(prescaler.presc()));
315
316 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
317 info!("ADC frequency set to {}", frequency);
318
319 if frequency > MAX_ADC_CLK_FREQ {
320 panic!(
321 "Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.",
322 MAX_ADC_CLK_FREQ.0 / 1_000_000
323 );
324 }
325
326 #[cfg(stm32h7)]
327 {
328 let boost = if frequency < Hertz::khz(6_250) {
329 Boost::LT6_25
330 } else if frequency < Hertz::khz(12_500) {
331 Boost::LT12_5
332 } else if frequency < Hertz::mhz(25) {
333 Boost::LT25
334 } else {
335 Boost::LT50
336 };
337 T::regs().cr().modify(|w| w.set_boost(boost));
338 }
339
340 T::regs().cr().modify(|reg| {
341 reg.set_deeppwd(false);
342 reg.set_advregen(true);
343 });
344
345 blocking_delay_us(10);
346
347 T::regs().difsel().modify(|w| {
348 for n in 0..20 {
349 w.set_difsel(n, Difsel::SINGLE_ENDED);
350 }
351 });
352
353 T::regs().cr().modify(|w| {
354 #[cfg(not(adc_u5))]
355 w.set_adcaldif(Adcaldif::SINGLE_ENDED);
356 w.set_adcallin(true);
357 });
358
359 T::regs().cr().modify(|w| w.set_adcal(true));
360
361 while T::regs().cr().read().adcal() {}
362
363 blocking_delay_us(1);
364
365 T::enable();
366
367 // single conversion mode, software trigger
368 T::regs().cfgr().modify(|w| {
369 w.set_cont(false);
370 w.set_exten(Exten::DISABLED);
371 });
372
373 Self { adc }
374 }
369 375
370 /// Enable reading the voltage reference internal channel. 376 /// Enable reading the voltage reference internal channel.
371 pub fn enable_vrefint(&self) -> VrefInt { 377 pub fn enable_vrefint(&self) -> VrefInt {
diff --git a/examples/stm32u5/src/bin/adc.rs b/examples/stm32u5/src/bin/adc.rs
index 6b9a91d6e..ad59c0bea 100644
--- a/examples/stm32u5/src/bin/adc.rs
+++ b/examples/stm32u5/src/bin/adc.rs
@@ -2,7 +2,7 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{self, AdcChannel, AdcConfig, SampleTime, adc4}; 5use embassy_stm32::adc::{self, Adc, AdcChannel, AdcConfig, SampleTime, adc4};
6use {defmt_rtt as _, panic_probe as _}; 6use {defmt_rtt as _, panic_probe as _};
7 7
8#[embassy_executor::main] 8#[embassy_executor::main]
@@ -15,7 +15,7 @@ async fn main(_spawner: embassy_executor::Spawner) {
15 let mut config = AdcConfig::default(); 15 let mut config = AdcConfig::default();
16 config.averaging = Some(adc::Averaging::Samples1024); 16 config.averaging = Some(adc::Averaging::Samples1024);
17 config.resolution = Some(adc::Resolution::BITS14); 17 config.resolution = Some(adc::Resolution::BITS14);
18 let mut adc1 = adc::Adc::new_with_config(p.ADC1, config); 18 let mut adc1 = Adc::new_with_config(p.ADC1, config);
19 let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5 19 let mut adc1_pin1 = p.PA3; // A0 on nucleo u5a5
20 let mut adc1_pin2 = p.PA2; // A1 20 let mut adc1_pin2 = p.PA2; // A1
21 let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); 21 let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14);
@@ -24,17 +24,17 @@ async fn main(_spawner: embassy_executor::Spawner) {
24 let mut config = AdcConfig::default(); 24 let mut config = AdcConfig::default();
25 config.averaging = Some(adc::Averaging::Samples1024); 25 config.averaging = Some(adc::Averaging::Samples1024);
26 config.resolution = Some(adc::Resolution::BITS14); 26 config.resolution = Some(adc::Resolution::BITS14);
27 let mut adc2 = adc::Adc::new_with_config(p.ADC2, config); 27 let mut adc2 = Adc::new_with_config(p.ADC2, config);
28 let mut adc2_pin1 = p.PC3; // A2 28 let mut adc2_pin1 = p.PC3; // A2
29 let mut adc2_pin2 = p.PB0; // A3 29 let mut adc2_pin2 = p.PB0; // A3
30 let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); 30 let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14);
31 31
32 // **** ADC4 init **** 32 // **** ADC4 init ****
33 let mut adc4 = adc4::Adc4::new(p.ADC4); 33 let mut adc4 = Adc::new_adc4(p.ADC4);
34 let mut adc4_pin1 = p.PC1; // A4 34 let mut adc4_pin1 = p.PC1; // A4
35 let mut adc4_pin2 = p.PC0; // A5 35 let mut adc4_pin2 = p.PC0; // A5
36 adc4.set_resolution(adc4::Resolution::BITS12); 36 adc4.set_resolution_adc4(adc4::Resolution::BITS12);
37 adc4.set_averaging(adc4::Averaging::Samples256); 37 adc4.set_averaging_adc4(adc4::Averaging::Samples256);
38 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); 38 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
39 39
40 // **** ADC1 blocking read **** 40 // **** ADC1 blocking read ****
@@ -95,11 +95,14 @@ async fn main(_spawner: embassy_executor::Spawner) {
95 // The channels must be in ascending order and can't repeat for ADC4 95 // The channels must be in ascending order and can't repeat for ADC4
96 adc4.read( 96 adc4.read(
97 p.GPDMA1_CH1.reborrow(), 97 p.GPDMA1_CH1.reborrow(),
98 [&mut degraded42, &mut degraded41].into_iter(), 98 [
99 (&mut degraded42, adc4::SampleTime::CYCLES1_5),
100 (&mut degraded41, adc4::SampleTime::CYCLES1_5),
101 ]
102 .into_iter(),
99 &mut measurements, 103 &mut measurements,
100 ) 104 )
101 .await 105 .await;
102 .unwrap();
103 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; 106 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32;
104 let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32; 107 let volt1: f32 = 3.3 * measurements[1] as f32 / max4 as f32;
105 info!("Async read 4 pin 1 {}", volt1); 108 info!("Async read 4 pin 1 {}", volt1);
diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs
index 177aab3f3..ade3f5d6a 100644
--- a/examples/stm32wba/src/bin/adc.rs
+++ b/examples/stm32wba/src/bin/adc.rs
@@ -2,7 +2,7 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{AdcChannel, adc4}; 5use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4};
6use {defmt_rtt as _, panic_probe as _}; 6use {defmt_rtt as _, panic_probe as _};
7 7
8#[embassy_executor::main] 8#[embassy_executor::main]
@@ -12,11 +12,11 @@ async fn main(_spawner: embassy_executor::Spawner) {
12 let mut p = embassy_stm32::init(config); 12 let mut p = embassy_stm32::init(config);
13 13
14 // **** ADC4 init **** 14 // **** ADC4 init ****
15 let mut adc4 = adc4::Adc4::new(p.ADC4); 15 let mut adc4 = Adc::new_adc4(p.ADC4);
16 let mut adc4_pin1 = p.PA0; // A4 16 let mut adc4_pin1 = p.PA0; // A4
17 let mut adc4_pin2 = p.PA1; // A5 17 let mut adc4_pin2 = p.PA1; // A5
18 adc4.set_resolution(adc4::Resolution::BITS12); 18 adc4.set_resolution_adc4(adc4::Resolution::BITS12);
19 adc4.set_averaging(adc4::Averaging::Samples256); 19 adc4.set_averaging_adc4(adc4::Averaging::Samples256);
20 20
21 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); 21 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
22 22
@@ -37,11 +37,14 @@ async fn main(_spawner: embassy_executor::Spawner) {
37 // The channels must be in ascending order and can't repeat for ADC4 37 // The channels must be in ascending order and can't repeat for ADC4
38 adc4.read( 38 adc4.read(
39 p.GPDMA1_CH1.reborrow(), 39 p.GPDMA1_CH1.reborrow(),
40 [&mut degraded42, &mut degraded41].into_iter(), 40 [
41 (&mut degraded42, SampleTime::CYCLES12_5),
42 (&mut degraded41, SampleTime::CYCLES12_5),
43 ]
44 .into_iter(),
41 &mut measurements, 45 &mut measurements,
42 ) 46 )
43 .await 47 .await;
44 .unwrap();
45 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; 48 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32;
46 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; 49 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32;
47 info!("Async read 4 pin 1 {}", volt1); 50 info!("Async read 4 pin 1 {}", volt1);
diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs
index 0887e124c..9d1f39419 100644
--- a/examples/stm32wba6/src/bin/adc.rs
+++ b/examples/stm32wba6/src/bin/adc.rs
@@ -2,7 +2,7 @@
2#![no_main] 2#![no_main]
3 3
4use defmt::*; 4use defmt::*;
5use embassy_stm32::adc::{AdcChannel, adc4}; 5use embassy_stm32::adc::{Adc, AdcChannel, SampleTime, adc4};
6use {defmt_rtt as _, panic_probe as _}; 6use {defmt_rtt as _, panic_probe as _};
7 7
8#[embassy_executor::main] 8#[embassy_executor::main]
@@ -12,11 +12,11 @@ async fn main(_spawner: embassy_executor::Spawner) {
12 let mut p = embassy_stm32::init(config); 12 let mut p = embassy_stm32::init(config);
13 13
14 // **** ADC4 init **** 14 // **** ADC4 init ****
15 let mut adc4 = adc4::Adc4::new(p.ADC4); 15 let mut adc4 = Adc::new_adc4(p.ADC4);
16 let mut adc4_pin1 = p.PA0; // A4 16 let mut adc4_pin1 = p.PA0; // A4
17 let mut adc4_pin2 = p.PA1; // A5 17 let mut adc4_pin2 = p.PA1; // A5
18 adc4.set_resolution(adc4::Resolution::BITS12); 18 adc4.set_resolution_adc4(adc4::Resolution::BITS12);
19 adc4.set_averaging(adc4::Averaging::Samples256); 19 adc4.set_averaging_adc4(adc4::Averaging::Samples256);
20 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); 20 let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12);
21 21
22 // **** ADC4 blocking read **** 22 // **** ADC4 blocking read ****
@@ -36,11 +36,14 @@ async fn main(_spawner: embassy_executor::Spawner) {
36 // The channels must be in ascending order and can't repeat for ADC4 36 // The channels must be in ascending order and can't repeat for ADC4
37 adc4.read( 37 adc4.read(
38 p.GPDMA1_CH1.reborrow(), 38 p.GPDMA1_CH1.reborrow(),
39 [&mut degraded42, &mut degraded41].into_iter(), 39 [
40 (&mut degraded42, SampleTime::CYCLES12_5),
41 (&mut degraded41, SampleTime::CYCLES12_5),
42 ]
43 .into_iter(),
40 &mut measurements, 44 &mut measurements,
41 ) 45 )
42 .await 46 .await;
43 .unwrap();
44 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32; 47 let volt2: f32 = 3.3 * measurements[0] as f32 / max4 as f32;
45 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32; 48 let volt1: f32 = 3.0 * measurements[1] as f32 / max4 as f32;
46 info!("Async read 4 pin 1 {}", volt1); 49 info!("Async read 4 pin 1 {}", volt1);