stm32_hal2/adc.rs
1//! Support for the ADC (Analog to Digital Converter) peripheral.
2
3use core::ptr;
4
5use cfg_if::cfg_if;
6use cortex_m::asm;
7use paste::paste;
8
9#[cfg(any(feature = "f3", feature = "l4"))]
10use crate::dma::DmaInput;
11#[cfg(not(any(feature = "f4", feature = "l552", feature = "h5")))]
12use crate::dma::{self, ChannelCfg, DmaChannel};
13use crate::{
14 clocks::Clocks,
15 error::{Error, Result},
16 pac::{self, RCC},
17 util::{bounded_loop, rcc_en_reset},
18};
19
20// Address of the ADCinterval voltage reference. This address is found in the User manual. It appears
21// to be the same for most STM32s. The voltage this is measured at my vary by variant; eg 3.0 vice 3.3.
22// So far, it seems it's always on ADC1, but the channel depends on variant.
23// G474 manual implies you can use *any* ADC on ch 18. G491 shows ADC 1 and 3, ch 18 on both.
24// L4x2 implies ADC1 only.
25cfg_if! {
26 if #[cfg(feature = "h7")] {
27 // These values are from the H723 User manual
28 const VREFINT_ADDR: u32 = 0x1FF1_E860;
29 const VREFINT_VOLTAGE: f32 = 3.3;
30 const VREFINT_CH: u8 = 0; // todo: Unknown. What is it?
31 } else if #[cfg(feature = "g4")] {
32 const VREFINT_ADDR: u32 = 0x1FFF_75AA;
33 const VREFINT_VOLTAGE: f32 = 3.0;
34 const VREFINT_CH: u8 = 18; // G491, G431
35 } else {
36 const VREFINT_ADDR: u32 = 0x1FFF_75AA;
37 const VREFINT_VOLTAGE: f32 = 3.0;
38 const VREFINT_CH: u8 = 0; // L412
39 }
40}
41
42const MAX_ADVREGEN_STARTUP_US: u32 = 10;
43
44#[derive(Clone, Copy, PartialEq)]
45pub enum AdcDevice {
46 One,
47 Two,
48 Three,
49 #[cfg(feature = "g4")] // todo: Check the specifics.
50 Four,
51 #[cfg(feature = "g4")]
52 Five,
53}
54
55#[derive(Clone, Copy)]
56#[repr(u8)]
57/// Select a trigger. Sets CFGR reg, EXTSEL field. See G4 RM, table 163: ADC1/2 - External
58/// triggers for regular channels.
59pub enum Trigger {
60 // todo: Injected.
61 Tim1Cc1 = 0b00000,
62 Tim1Cc2 = 0b00001,
63 Tim1Cc3 = 0b00010,
64 Tim2Cc2 = 0b00011,
65 Tim3Trgo = 0b00100,
66 Tim4Cc4 = 0b00101,
67 Exti11 = 0b00110,
68 Tim8Trgo = 0b00111,
69 Tim8Trgo2 = 0b01000,
70 Tim1Trgo = 0b01001,
71 Tim1Trgo2 = 0b01010,
72 Tim2Trgo = 0b01011,
73 Tim4Trgo = 0b01100,
74 Tim6Trgo = 0b01101,
75 Tim15Trgo = 0b01110,
76 Tim3Cc4 = 0b01111,
77 // todo: Fill in remaining ones.
78 Tim7Trgo = 0b11110,
79}
80
81#[derive(Clone, Copy)]
82#[repr(u8)]
83/// Select a trigger. Sets CFGR reg, EXTEN field. See G4 RM, table 161:
84/// Configuring the trigger polarity for regular external triggers
85/// (Also applies for injected)
86pub enum TriggerEdge {
87 /// Hardware Trigger detection disabled, software trigger detection enabled
88 Software = 0b00,
89 /// Hardware Trigger with detection on the rising edge
90 HardwareRising = 0b01,
91 /// Hardware Trigger with detection on the falling edge
92 HardwareFalling = 0b10,
93 /// Hardware Trigger with detection on both the rising and falling edges
94 HardwareBoth = 0b11,
95}
96
97#[derive(Copy, Clone)]
98#[repr(u8)]
99/// ADC interrupts. See L44 RM, section 16.5: ADC interrupts. Set in the IER register, and cleared
100/// in the ISR register.
101pub enum AdcInterrupt {
102 /// ADC ready (ADRDYIE field)
103 Ready,
104 /// End of regular conversion interrupt enable (EOCIE field)
105 EndOfConversion,
106 /// End of regular sequence of conversions (EOSIE field)
107 EndOfSequence,
108 /// End of injected conversion (JEOCIE field)
109 EndofConversionInjected,
110 /// End of injected sequence of conversions (JEOSIE field)
111 EndOfSequenceInjected,
112 /// Analog watchdog 1 interrupt (AWD1IE field)
113 Watchdog1,
114 /// Analog watchdog 2 interrupt (AWD2IE field)
115 Watchdog2,
116 /// Analog watchdog 3 interrupt (AWD3IE field)
117 Watchdog3,
118 /// End of sampling flag interrupt enable for regular conversions (EOSMPIE field)
119 EndOfSamplingPhase,
120 /// Overrun (OVRIE field)
121 Overrun,
122 /// Injected Context Queue Overflow (JQOVFIE field)
123 InjectedOverflow,
124}
125
126// todo: Adc sampling time below depends on the STM32 family. Eg the numbers below
127// todo are wrong for L4, but the idea is the same.
128/// ADC sampling time. Sets ADC_SMPRx register, SMPy field.
129///
130/// Each channel can be sampled with a different sample time.
131/// There is always an overhead of 13 ADC clock cycles.
132/// E.g. For Sampletime T_19 the total conversion time (in ADC clock cycles) is
133/// 13 + 19 = 32 ADC Clock Cycles
134#[derive(Clone, Copy)]
135#[repr(u8)]
136pub enum SampleTime {
137 /// 1.5 ADC clock cycles (2.5 on G4)
138 T1 = 0b000,
139 /// 2.5 ADC clock cycles (6.5 on G4)
140 T2 = 0b001,
141 /// 4.5 ADC clock cycles (12.5 on G4)
142 T4 = 0b010,
143 /// 7.5 ADC clock cycles (24.5 on G4)
144 T7 = 0b011,
145 /// 19.5 ADC clock cycles (47.5 on G4)
146 T19 = 0b100,
147 /// 61.5 ADC clock cycles (92.5 on G4)
148 T61 = 0b101,
149 /// 181.5 ADC clock cycles (247.5 on G4)
150 T181 = 0b110,
151 /// 601.5 ADC clock cycles (640.5 on G4 and H7)
152 T601 = 0b111,
153}
154
155impl Default for SampleTime {
156 /// T_1 is the reset value; pick a higher one, as the lower values may cause significantly
157 /// lower-than-accurate readings.
158 fn default() -> Self {
159 SampleTime::T181
160 }
161}
162
163#[derive(Clone, Copy)]
164#[repr(u8)]
165/// Select single-ended, or differential inputs. Sets bits in the ADC\[x\]_DIFSEL register.
166pub enum InputType {
167 SingleEnded = 0,
168 Differential = 1,
169}
170
171#[derive(Clone, Copy)]
172#[repr(u8)]
173/// ADC operation mode
174pub enum OperationMode {
175 /// OneShot Mode
176 OneShot = 0,
177 Continuous = 1,
178}
179
180// todo: Check the diff ways of configuring clock; i don't think teh enum below covers all.(?)
181
182#[derive(Clone, Copy, PartialEq)]
183#[repr(u8)]
184/// ADC Clock mode
185/// (L44 RM, Section 16.4.3) The input clock is the same for the three ADCs and can be selected between two different
186/// clock sources (see Figure 40: ADC clock scheme):
187/// 1. The ADC clock can be a specific clock source. It can be derived from the following
188/// clock sources:
189/// – The system clock
190/// – PLLSAI1 (single ADC implementation)
191/// Refer to RCC Section for more information on how to generate ADC dedicated clock.
192/// To select this scheme, bits CKMODE\[1:0\] of the ADCx_CCR register must be reset.
193/// 2. The ADC clock can be derived from the AHB clock of the ADC bus interface, divided by
194/// a programmable factor (1, 2 or 4). In this mode, a programmable divider factor can be
195/// selected (/1, 2 or 4 according to bits CKMODE\[1:0\]).
196/// To select this scheme, bits CKMODE\[1:0\] of the ADCx_CCR register must be different
197/// from “00”.
198pub enum ClockMode {
199 /// Use Kernel Clock adc_ker_ck_input divided by PRESC. Asynchronous to AHB clock
200 Async = 0b00,
201 /// Use AHB clock rcc_hclk3 (or just hclk depending on variant).
202 /// "For option 2), a prescaling factor of 1 (CKMODE\[1:0\]=01) can be used only if the AHB
203 /// prescaler is set to 1 (HPRE\[3:0\] = 0xxx in RCC_CFGR register)."
204 SyncDiv1 = 0b01,
205 /// Use AHB clock rcc_hclk3 (or just hclk depending on variant) divided by 2
206 SyncDiv2 = 0b10,
207 /// Use AHB clock rcc_hclk3 (or just hclk depending on variant) divided by 4
208 SyncDiv4 = 0b11,
209}
210
211/// Sets ADC clock prescaler; ADCx_CCR register, PRESC field.
212#[derive(Clone, Copy)]
213#[repr(u8)]
214pub enum Prescaler {
215 D1 = 0b0000,
216 D2 = 0b0001,
217 D4 = 0b0010,
218 D6 = 0b0011,
219 D8 = 0b0100,
220 D10 = 0b0101,
221 D12 = 0b0110,
222 D16 = 0b0111,
223 D32 = 0b1000,
224 D64 = 0b1001,
225 D128 = 0b1010,
226 D256 = 0b1011,
227}
228
229#[cfg(not(feature = "h7"))]
230/// ADC data register alignment
231#[derive(Clone, Copy)]
232#[repr(u8)]
233pub enum Align {
234 /// Right alignment of output data
235 Right = 0,
236 /// Left alignment of output data
237 Left = 1,
238}
239
240#[cfg(not(feature = "h7"))]
241impl Default for Align {
242 fn default() -> Self {
243 Align::Right
244 }
245}
246
247#[cfg(feature = "h7")]
248/// ADC data register alignment
249#[derive(Clone, Copy)]
250#[repr(u8)]
251pub enum Align {
252 NoShift = 0,
253 L1 = 1,
254 L2 = 2,
255 L3 = 3,
256 L4 = 4,
257 L5 = 5,
258 L6 = 6,
259 L7 = 7,
260 L8 = 8,
261 L9 = 9,
262 L10 = 10,
263 L11 = 11,
264 L12 = 12,
265 L13 = 13,
266 L14 = 14,
267 L15 = 15,
268}
269
270#[cfg(feature = "h7")]
271impl Default for Align {
272 fn default() -> Self {
273 Align::NoShift
274 }
275}
276
277// todo impl
278// /// Ratio options for oversampling.
279// #[derive(Clone, Copy)]
280// #[repr(u8)]
281// pub enum OversamplingRatio {
282// Times2 = 0b000,
283// Times4 = 0b001,
284// Times8 = 0b010,
285// Times16 = 0b011,
286// Times32 = 0b100,
287// Times64 = 0b101,
288// Times128 = 0b110,
289// Times256 = 0b111,
290// }
291//
292// /// Shift options for oversampling.
293// #[derive(Clone, Copy)]
294// #[repr(u8)]
295// pub enum OversamplingShift {
296// None = 0b0000,
297// Bits1 = 0b0001,
298// Bits2 = 0b0010,
299// Bits3 = 0b0011,
300// Bits4 = 0b0100,
301// Bits5 = 0b0101,
302// Bits6 = 0b0110,
303// Bits7 = 0b0111,
304// Bits8 = 0b1000,
305// }
306
307/// Initial configuration data for the ADC peripheral.
308#[derive(Clone)]
309pub struct AdcConfig {
310 /// ADC clock mode. Defaults to AHB clock rcc_hclk3 (or hclk) divided by 2.
311 pub clock_mode: ClockMode,
312 /// ADC sample time. See the `SampleTime` enum for details. Higher values
313 /// result in more accurate readings.
314 pub sample_time: SampleTime,
315 /// ADC clock prescaler. Defaults to no division.
316 pub prescaler: Prescaler,
317 /// One-shot, or continuous measurements. Defaults to one-shot.
318 pub operation_mode: OperationMode,
319 // Most families use u8 values for calibration, but H7 uses u16.
320 /// Optional calibration data for single-ended measurements.
321 pub cal_single_ended: Option<u16>,
322 /// Optional calibration data for differential measurements.
323 pub cal_differential: Option<u16>,
324}
325
326impl Default for AdcConfig {
327 fn default() -> Self {
328 Self {
329 // todo: What should this be? Async seems to be having trouble.
330 // clock_mode: ClockMode::Async,
331 clock_mode: ClockMode::SyncDiv1,
332 sample_time: Default::default(),
333 prescaler: Prescaler::D1,
334 operation_mode: OperationMode::OneShot,
335 cal_single_ended: None,
336 cal_differential: None,
337 }
338 }
339}
340
341/// Represents an Analog to Digital Converter (ADC) peripheral.
342pub struct Adc<R> {
343 /// ADC Register
344 pub regs: R,
345 // Note: We don't own the common regs; pass them mutably where required, since they may be used
346 // by a different ADC.
347 device: AdcDevice,
348 pub cfg: AdcConfig,
349 /// This field is managed internally, and is set up on init.
350 pub vdda_calibrated: f32,
351}
352
353// todo: Remove this macro, and replace using a `regs` fn like you use in GPIO.
354macro_rules! hal {
355 ($ADC:ident, $ADC_COMMON:ident, $adc:ident, $rcc_num:tt) => {
356 impl Adc<pac::$ADC> {
357 paste! {
358 /// Initialize an ADC peripheral, including configuration register writes, enabling and resetting
359 /// its RCC peripheral clock, and calibrtation.
360 ///
361 /// If used with ADC1, this also performs VDDA measurement,
362 /// used for converting raw output to voltage. If using an ADC other than ADC1, this measurement
363 /// is skipped, and 3.3V is assumed. In this case, it's recommended to setup ADC1, read
364 /// it's VDDA value (`vdda_calibrated` field), and update the ADC in question with it.
365 pub fn [<new_ $adc>](
366 regs: pac::$ADC,
367 device: AdcDevice,
368 cfg: AdcConfig,
369 ahb_freq: u32, // Used for blocking delays in init.
370 ) -> Result<Self> {
371 let mut adc = Self {
372 regs,
373 device,
374 cfg,
375 vdda_calibrated: 0.
376 };
377
378 let rcc = unsafe { &(*RCC::ptr()) };
379 let common_regs = unsafe { &*pac::$ADC_COMMON::ptr() };
380
381 // Note: We only perform RCC enabling, not resetingg; resetting will
382 // cause ADCs that share RCC en/reset registers (eg ADC1/2 on G4) that
383 // were previously set up to stop working.
384 paste! {
385 cfg_if! {
386 if #[cfg(feature = "f3")] {
387 rcc_en_reset!(ahb1, [<adc $rcc_num>], rcc);
388 } else if #[cfg(feature = "f4")] {
389 rcc_en_reset!(2, [<adc $rcc_num>], rcc);
390 } else if #[cfg(feature = "h7")] {
391 match device {
392 AdcDevice::One | AdcDevice::Two => {
393 rcc.ahb1enr().modify(|_, w| w.adc12en().bit(true));
394 }
395 AdcDevice::Three => {
396 rcc.ahb4enr().modify(|_, w| w.adc3en().bit(true));
397 }
398 }
399 } else if #[cfg(any(feature = "g4"))] {
400 rcc.ahb2enr().modify(|_, w| w.adc12en().bit(true));
401 // rcc_en_reset!(ahb2, [<adc $rcc_num>], rcc);
402 } else { // ie L4, L5, G0(?)
403 rcc_en_reset!(ahb2, adc, rcc);
404 }
405 }
406 }
407
408 common_regs.ccr().modify(|_, w| unsafe {
409 #[cfg(not(any(feature = "f3", feature = "l4x5")))] // PAC ommission l4x5?
410 w.presc().bits(adc.cfg.prescaler as u8);
411 return w.ckmode().bits(adc.cfg.clock_mode as u8);
412 });
413
414 adc.set_align(Align::default());
415
416
417 adc.advregen_enable(ahb_freq);
418
419 adc.calibrate(InputType::SingleEnded, ahb_freq)?;
420 adc.calibrate(InputType::Differential, ahb_freq)?;
421
422 // Reference Manual: "ADEN bit cannot be set during ADCAL=1
423 // and 4 ADC clock cycle after the ADCAL
424 // bit is cleared by hardware."
425 let adc_per_cpu_cycles = match adc.cfg.clock_mode {
426 ClockMode::Async => 1,
427 ClockMode::SyncDiv1 => 1,
428 ClockMode::SyncDiv2 => 2,
429 ClockMode::SyncDiv4 => 4,
430 };
431 asm::delay(adc_per_cpu_cycles * 4 * 2); // additional x2 is a pad;
432
433 // "Must be used when ADC clock > 20 MHz
434 // ...The software is allowed to write this bit only when ADSTART=0 and JADSTART=0 (which
435 // ensures that no conversion is ongoing)."
436 // todo: On H7, allow disabling boost, either manually, or by checking the clock speed.
437 #[cfg(all(feature = "h7", not(any(feature = "h743", feature = "h753", feature = "h735"))))]
438 adc.regs.cr().modify(|_, w| unsafe { w.boost().bits(1)});
439
440 #[cfg(any(feature = "h743", feature = "h753"))]
441 adc.regs.cr().modify(|_, w| w.boost().bit(true));
442
443 // #[cfg(feature = "h735")]
444 // result.regs.cr().modify(|_, w| w.boost().bits(1));
445
446 adc.enable()?;
447
448 // Set up VDDA only after the ADC is otherwise enabled.
449 adc.setup_vdda(ahb_freq)?;
450
451 // Don't set continuous mode until after configuring VDDA, since it needs
452 // to take a oneshot reading.
453 adc.regs.cfgr().modify(|_, w| w.cont().bit(adc.cfg.operation_mode as u8 != 0));
454
455 for ch in 1..10 {
456 adc.set_sample_time(ch, adc.cfg.sample_time)?;
457 }
458 // Note: We are getting a hardfault on G431 when setting this for channel 10.
459 for ch in 11..19 {
460 adc.set_sample_time(ch, adc.cfg.sample_time)?;
461 }
462
463 Ok(adc)
464 }
465 }
466
467 // /// Get the current ADC effective clock speed, in Mhz.
468 // pub fn speed(clocks: &ClockCfg) -> u32 {
469 // 0 // todo
470 // }
471
472 /// Set the ADC conversion sequence length, between 1 and 16.
473 pub fn set_sequence_len(&mut self, len: u8) {
474 if len - 1 >= 16 {
475 panic!("ADC sequence length must be in 1..=16")
476 }
477
478 self.regs.sqr1().modify(|_, w| unsafe { w.l().bits(len - 1) });
479 }
480
481 /// Set the alignment mode.
482 pub fn set_align(&self, align: Align) {
483 #[cfg(all(feature = "h7", not(feature = "h735")))]
484 self.regs.cfgr2().modify(|_, w| unsafe { w.lshift().bits(align as u8)});
485 // todo: How to do on H735?
486
487 #[cfg(not(feature = "h7"))]
488 self.regs.cfgr().modify(|_, w| w.align().bit(align as u8 != 0));
489 }
490
491 /// Enable the ADC.
492 /// ADEN=1 enables the ADC. The flag ADRDY will be set once the ADC is ready for
493 /// operation.
494 pub fn enable(&mut self) -> Result<()> {
495 // 1. Clear the ADRDY bit in the ADC_ISR register by writing ‘1’.
496 self.regs.isr().modify(|_, w| w.adrdy().bit(true));
497 // 2. Set ADEN=1.
498 self.regs.cr().modify(|_, w| w.aden().bit(true)); // Enable
499 // 3. Wait until ADRDY=1 (ADRDY is set after the ADC startup time). This can be done
500 // using the associated interrupt (setting ADRDYIE=1).
501 // Wait until ready
502 bounded_loop!(self.regs.isr().read().adrdy().bit_is_clear(), Error::RegisterUnchanged);
503 // 4. Clear the ADRDY bit in the ADC_ISR register by writing ‘1’ (optional).
504 self.regs.isr().modify(|_, w| w.adrdy().bit(true));
505
506 Ok(())
507 }
508
509 /// Disable the ADC.
510 /// ADDIS=1 disables the ADC. ADEN and ADDIS are then automatically cleared by
511 /// hardware as soon as the analog ADC is effectively disabled
512 pub fn disable(&mut self) -> Result<()> {
513 // 1. Check that both ADSTART=0 and JADSTART=0 to ensure that no conversion is
514 // ongoing. If required, stop any regular and injected conversion ongoing by setting
515 // ADSTP=1 and JADSTP=1 and then wait until ADSTP=0 and JADSTP=0.
516 self.stop_conversions()?;
517
518 // 2. Set ADDIS=1.
519 self.regs.cr().modify(|_, w| w.addis().bit(true)); // Disable
520
521 // 3. If required by the application, wait until ADEN=0, until the analog
522 // ADC is effectively disabled (ADDIS will automatically be reset once ADEN=0)
523 bounded_loop!(self.regs.cr().read().aden().bit_is_set(), Error::RegisterUnchanged);
524
525 Ok(())
526 }
527
528 /// If any conversions are in progress, stop them. This is a step listed in the RMs
529 /// for disable, and calibration procedures. See L4 RM: 16.4.17.
530 /// When the ADSTP bit is set by software, any ongoing regular conversion is aborted with
531 /// partial result discarded (ADC_DR register is not updated with the current conversion).
532 /// When the JADSTP bit is set by software, any ongoing injected conversion is aborted with
533 /// partial result discarded (ADC_JDRy register is not updated with the current conversion).
534 /// The scan sequence is also aborted and reset (meaning that relaunching the ADC would
535 /// restart a new sequence).
536 pub fn stop_conversions(&mut self) -> Result<()> {
537 // The software can decide to stop regular conversions ongoing by setting ADSTP=1 and
538 // injected conversions ongoing by setting JADSTP=1.
539 // Stopping conversions will reset the ongoing ADC operation. Then the ADC can be
540 // reconfigured (ex: changing the channel selection or the trigger) ready for a new operation.
541 let cr_val = self.regs.cr().read();
542 if cr_val.adstart().bit_is_set() || self.regs.cr().read().jadstart().bit_is_set() {
543 self.regs.cr().modify(|_, w| {
544 w.adstp().bit(true);
545 w.jadstp().bit(true)
546 });
547 bounded_loop!(
548 self.regs.cr().read().adstart().bit_is_set() || self.regs.cr().read().jadstart().bit_is_set(),
549 Error::RegisterUnchanged
550 );
551 }
552 Ok(())
553 }
554
555 /// Check if the ADC is enabled.
556 pub fn is_enabled(&self) -> bool {
557 self.regs.cr().read().aden().bit_is_set()
558 }
559
560 /// Check if the ADC voltage regulator is enabled.
561 pub fn is_advregen_enabled(&self) -> bool {
562 cfg_if! {
563 if #[cfg(feature = "f3")] {
564 self.regs.cr().read().advregen().bits() == 1
565 } else {
566 self.regs.cr().read().advregen().bit_is_set()
567 }
568 }
569 }
570
571 /// Enable the ADC voltage regulator, and exit deep sleep mode (some MCUs)
572 pub fn advregen_enable(&mut self, ahb_freq: u32) {
573 cfg_if! {
574 if #[cfg(feature = "f3")] {
575 // `F303 RM, 15.3.6:
576 // 1. Change ADVREGEN\[1:0\] bits from ‘10’ (disabled state, reset state) into ‘00’.
577 // 2. Change ADVREGEN\[1:0\] bits from ‘00’ into ‘01’ (enabled state).
578 self.regs.cr().modify(|_, w| unsafe { w.advregen().bits(0b00)});
579 self.regs.cr().modify(|_, w| unsafe { w.advregen().bits(0b01)});
580 } else {
581 // L443 RM, 16.4.6; G4 RM, section 21.4.6: Deep-power-down mode (DEEPPWD) and ADC voltage
582 // regulator (ADVREGEN)
583 //
584 // "By default, the ADC is in Deep-power-down mode where its supply is internally switched off
585 // to reduce the leakage currents (the reset state of bit DEEPPWD is 1 in the ADC_CR
586 // register).
587 // To start ADC operations, it is first needed to exit Deep-power-down mode by setting bit
588 // DEEPPWD=0.""
589 self.regs.cr().modify(|_, w| {
590 w.deeppwd().clear_bit(); // Exit deep sleep mode.
591 w.advregen().bit(true) // Enable voltage regulator.
592
593 });
594 }
595 }
596
597 self.wait_advregen_startup(ahb_freq)
598 }
599
600 /// Disable power, eg to save power in low power modes. Inferred from RM,
601 /// we should run this before entering `STOP` mode, in conjunction with with
602 /// disabling the ADC.
603 pub fn advregen_disable(&mut self) {
604 cfg_if! {
605 if #[cfg(feature = "f3")] {
606 // `F303 RM, 15.3.6:
607 // 1. Change ADVREGEN\[1:0\] bits from ‘01’ (enabled state) into ‘00’.
608 // 2. Change ADVREGEN\[1:0\] bits from ‘00’ into ‘10’ (disabled state)
609 self.regs.cr().modify(|_, w| unsafe { w.advregen().bits(0b00) });
610 self.regs.cr().modify(|_, w| unsafe { w.advregen().bits(0b10) });
611 } else {
612 // L4 RM, 16.4.6: Writing DEEPPWD=1 automatically disables the ADC voltage
613 // regulator and bit ADVREGEN is automatically cleared.
614 // When the internal voltage regulator is disabled (ADVREGEN=0), the internal analog
615 // calibration is kept.
616 // In ADC Deep-power-down mode (DEEPPWD=1), the internal analog calibration is lost and
617 // it is necessary to either relaunch a calibration or re-apply the calibration factor which was
618 // previously saved (
619 self.regs.cr().modify(|_, w| w.deeppwd().bit(true));
620 // todo: We could offer an option to disable advregen without setting deeppwd,
621 // todo, which would keep calibration.
622 }
623 }
624 }
625
626 /// Wait for the advregen to startup.
627 ///
628 /// This is based on the MAX_ADVREGEN_STARTUP_US of the device.
629 fn wait_advregen_startup(&self, ahb_freq: u32) {
630 crate::delay_us(MAX_ADVREGEN_STARTUP_US, ahb_freq)
631 }
632
633 /// Calibrate. See L4 RM, 16.5.8, or F404 RM, section 15.3.8.
634 /// Stores calibration values, which can be re-inserted later,
635 /// eg after entering ADC deep sleep mode, or MCU STANDBY or VBAT.
636 pub fn calibrate(&mut self, input_type: InputType, ahb_freq: u32) -> Result<()> {
637 // 1. Ensure DEEPPWD=0, ADVREGEN=1 and that ADC voltage regulator startup time has
638 // elapsed.
639 if !self.is_advregen_enabled() {
640 self.advregen_enable(ahb_freq);
641 }
642
643 let was_enabled = self.is_enabled();
644 // Calibration can only be initiated when the ADC is disabled (when ADEN=0).
645 // 2. Ensure that ADEN=0
646 if was_enabled {
647 self.disable()?;
648 }
649
650 self.regs.cr().modify(|_, w| w
651 // RM:
652 // The calibration factor to be applied for single-ended input conversions is different from the
653 // factor to be applied for differential input conversions:
654 // • Write ADCALDIF=0 before launching a calibration which will be applied for singleended input conversions.
655 // • Write ADCALDIF=1 before launching a calibration which will be applied for differential
656 // input conversions.
657 // 3. Select the input mode for this calibration by setting ADCALDIF=0 (single-ended input)
658 // or ADCALDIF=1 (differential input).
659 .adcaldif().bit(input_type as u8 != 0)
660 // The calibration is then initiated by software by setting bit ADCAL=1.
661 // 4. Set ADCAL=1.
662 .adcal().bit(true)); // start calibration.
663
664 // ADCAL bit stays at 1 during all the
665 // calibration sequence. It is then cleared by hardware as soon the calibration completes. At
666 // this time, the associated calibration factor is stored internally in the analog ADC and also in
667 // the bits CALFACT_S\[6:0\] or CALFACT_D\[6:0\] of ADC_CALFACT register (depending on
668 // single-ended or differential input calibration)
669 // 5. Wait until ADCAL=0.
670 bounded_loop!(
671 self.regs.cr().read().adcal().bit_is_set(),
672 Error::RegisterUnchanged
673 );
674
675 // 6. The calibration factor can be read from ADC_CALFACT register.
676 match input_type {
677 InputType::SingleEnded => {
678 let val = self.regs.calfact().read().calfact_s().bits();
679 #[cfg(not(feature = "h7"))]
680 let val = val as u16;
681 #[cfg(feature = "h735")]
682 let val = val as u16;
683 self.cfg.cal_single_ended = Some(val);
684 }
685 InputType::Differential => {
686 let val = self.regs.calfact().read().calfact_d().bits();
687 #[cfg(not(feature = "h7"))]
688 let val = val as u16;
689 #[cfg(feature = "h735")]
690 let val = val as u16;
691 self.cfg.cal_differential = Some(val);
692 }
693 }
694
695 if was_enabled {
696 self.enable()?;
697 }
698
699 Ok(())
700 }
701
702 /// Insert a previously-saved calibration value into the ADC.
703 /// Se L4 RM, 16.4.8.
704 pub fn inject_calibration(&mut self) -> Result<()> {
705 // 1. Ensure ADEN=1 and ADSTART=0 and JADSTART=0 (ADC enabled and no
706 // conversion is ongoing).
707 if !self.is_enabled() {
708 self.enable()?;
709 }
710 self.stop_conversions()?;
711
712
713 // 2. Write CALFACT_S and CALFACT_D with the new calibration factors.
714 if let Some(cal) = self.cfg.cal_single_ended {
715 #[cfg(not(feature = "h7"))]
716 let cal = cal as u8;
717 self.regs.calfact().modify(|_, w| unsafe { w.calfact_s().bits(cal.try_into().unwrap()) });
718 }
719 if let Some(cal) = self.cfg.cal_differential {
720 #[cfg(not(feature = "h7"))]
721 let cal = cal as u8;
722 self.regs.calfact().modify(|_, w| unsafe { w.calfact_d().bits(cal.try_into().unwrap()) });
723 }
724
725 // 3. When a conversion is launched, the calibration factor will be injected into the analog
726 // ADC only if the internal analog calibration factor differs from the one stored in bits
727 // CALFACT_S for single-ended input channel or bits CALFACT_D for differential input
728 // channel.
729 Ok(())
730 }
731
732 /// Select single-ended, or differential conversions for a given channel.
733 pub fn set_input_type(&mut self, channel: u8, input_type: InputType) -> Result<()> {
734 // L44 RM, 16.4.7:
735 // Channels can be configured to be either single-ended input or differential input by writing
736 // into bits DIFSEL\[15:1\] in the ADC_DIFSEL register. This configuration must be written while
737 // the ADC is disabled (ADEN=0). Note that DIFSEL\[18:16,0\] are fixed to single ended
738 // channels and are always read as 0.
739 let was_enabled = self.is_enabled();
740 if was_enabled {
741 self.disable()?;
742 }
743
744 // Note that we don't use the `difsel` PAC accessor here, due to its varying
745 // implementations across different PACs.
746 // todo: 1 offset? Experiment in firmware.
747 let val = self.regs.difsel().read().bits();
748
749 let val_new = match input_type {
750 InputType::SingleEnded => val & !(1 << channel),
751 InputType::Differential => val | (1 << channel),
752 };
753 self.regs.difsel().write(|w| unsafe { w.bits(val_new)});
754
755 // The commented code below is for some PAC variants taht support a method to
756 // choose the diffsel field.
757
758 // let v = input_type as u8 != 0;
759 // self.regs.difsel().modify(|_, w| {
760 // match channel {
761 // // todo: Do these need to be offset by 1??
762 // 0 => w.difsel_0().bit(v),
763 // 1 => w.difsel_1().bit(v),
764 // 2 => w.difsel_2().bit(v),
765 // 3 => w.difsel_3().bit(v),
766 // 4 => w.difsel_4().bit(v),
767 // 5 => w.difsel_5().bit(v),
768 // 6 => w.difsel_6().bit(v),
769 // 7 => w.difsel_7().bit(v),
770 // 8 => w.difsel_8().bit(v),
771 // 9 => w.difsel_9().bit(v),
772 // 10 => w.difsel_10().bit(v),
773 // 11 => w.difsel_11().bit(v),
774 // 12 => w.difsel_12().bit(v),
775 // 13 => w.difsel_13().bit(v),
776 // 14 => w.difsel_14().bit(v),
777 // 15 => w.difsel_15().bit(v),
778 // 16 => w.difsel_16().bit(v),
779 // 17 => w.difsel_17().bit(v),
780 // 18 => w.difsel_18().bit(v),
781 // _ => panic!(),
782 // }
783 // });
784
785 if was_enabled {
786 self.enable()?;
787 }
788 Ok(())
789 }
790
791 /// Select a sequence to sample, by inputting a single channel and position.
792 pub fn set_sequence(&mut self, chan: u8, position: u8) {
793 match position {
794 1 => self.regs.sqr1().modify(|_, w| unsafe { w.sq1().bits(chan) }),
795 2 => self.regs.sqr1().modify(|_, w| unsafe { w.sq2().bits(chan) }),
796 3 => self.regs.sqr1().modify(|_, w| unsafe { w.sq3().bits(chan) }),
797 4 => self.regs.sqr1().modify(|_, w| unsafe { w.sq4().bits(chan) }),
798 5 => self.regs.sqr2().modify(|_, w| unsafe { w.sq5().bits(chan) }),
799 6 => self.regs.sqr2().modify(|_, w| unsafe { w.sq6().bits(chan) }),
800 7 => self.regs.sqr2().modify(|_, w| unsafe { w.sq7().bits(chan) }),
801 8 => self.regs.sqr2().modify(|_, w| unsafe { w.sq8().bits(chan) }),
802 9 => self.regs.sqr2().modify(|_, w| unsafe { w.sq9().bits(chan) }),
803 10 => self.regs.sqr3().modify(|_, w| unsafe { w.sq10().bits(chan) }),
804 11 => self.regs.sqr3().modify(|_, w| unsafe { w.sq11().bits(chan) }),
805 12 => self.regs.sqr3().modify(|_, w| unsafe { w.sq12().bits(chan) }),
806 13 => self.regs.sqr3().modify(|_, w| unsafe { w.sq13().bits(chan) }),
807 14 => self.regs.sqr3().modify(|_, w| unsafe { w.sq14().bits(chan) }),
808 15 => self.regs.sqr4().modify(|_, w| unsafe { w.sq15().bits(chan) }),
809 16 => self.regs.sqr4().modify(|_, w| unsafe { w.sq16().bits(chan) }),
810 _ => panic!("Sequence out of bounds. Only 16 positions are available, starting at 1."),
811 };
812
813 #[cfg(all(feature = "h7", not(feature = "h735")))]
814 self.regs.pcsel().modify(|r, w| unsafe { w.pcsel().bits(r.pcsel().bits() | (1 << chan)) });
815
816 // todo: Figure this out, and put back (July 2025/pack 0.16)
817 // #[cfg(feature = "h735")]
818 // match chan {
819 // 0 => self.regs.pcsel().modify(|r, w| w.pcsel0().bit(true)),
820 // 1 => self.regs.pcsel().modify(|r, w| w.pcsel1().bit(true)),
821 // 2 => self.regs.pcsel().modify(|r, w| w.pcsel2().bit(true)),
822 // 3 => self.regs.pcsel().modify(|r, w| w.pcsel3().bit(true)),
823 // 4 => self.regs.pcsel().modify(|r, w| w.pcsel4().bit(true)),
824 // 5 => self.regs.pcsel().modify(|r, w| w.pcsel5().bit(true)),
825 // 6 => self.regs.pcsel().modify(|r, w| w.pcsel6().bit(true)),
826 // 7 => self.regs.pcsel().modify(|r, w| w.pcsel7().bit(true)),
827 // 8 => self.regs.pcsel().modify(|r, w| w.pcsel8().bit(true)),
828 // 9 => self.regs.pcsel().modify(|r, w| w.pcsel9().bit(true)),
829 // 10 => self.regs.pcsel().modify(|r, w| w.pcsel10().bit(true)),
830 // 11 => self.regs.pcsel().modify(|r, w| w.pcsel11().bit(true)),
831 // 12 => self.regs.pcsel().modify(|r, w| w.pcsel12().bit(true)),
832 // 13 => self.regs.pcsel().modify(|r, w| w.pcsel13().bit(true)),
833 // 14 => self.regs.pcsel().modify(|r, w| w.pcsel14().bit(true)),
834 // 15 => self.regs.pcsel().modify(|r, w| w.pcsel15().bit(true)),
835 // 16 => self.regs.pcsel().modify(|r, w| w.pcsel16().bit(true)),
836 // 17 => self.regs.pcsel().modify(|r, w| w.pcsel17().bit(true)),
837 // 18 => self.regs.pcsel().modify(|r, w| w.pcsel18().bit(true)),
838 // 19=> self.regs.pcsel().modify(|r, w| w.pcsel19().bit(true)),
839 // _ => ()
840 // };
841 }
842
843 /// Select the sample time for a given channel.
844 pub fn set_sample_time(&mut self, chan: u8, smp: SampleTime) -> Result<()> {
845 // Channel is the ADC channel to use.
846
847 // RM: Note: only allowed when ADSTART = 0 and JADSTART = 0.
848 self.stop_conversions()?;
849
850 // self.disable();
851 // while self.regs.cr().read().adstart().bit_is_set() || self.regs.cr().read().jadstart().bit_is_set() {}
852
853 unsafe {
854 match chan {
855 #[cfg(not(feature = "f3"))]
856 0 => self.regs.smpr1().modify(|_, w| w.smp0().bits(smp as u8)),
857 1 => self.regs.smpr1().modify(|_, w| w.smp1().bits(smp as u8)),
858 2 => self.regs.smpr1().modify(|_, w| w.smp2().bits(smp as u8)),
859 3 => self.regs.smpr1().modify(|_, w| w.smp3().bits(smp as u8)),
860 4 => self.regs.smpr1().modify(|_, w| w.smp4().bits(smp as u8)),
861 5 => self.regs.smpr1().modify(|_, w| w.smp5().bits(smp as u8)),
862 6 => self.regs.smpr1().modify(|_, w| w.smp6().bits(smp as u8)),
863 7 => self.regs.smpr1().modify(|_, w| w.smp7().bits(smp as u8)),
864 8 => self.regs.smpr1().modify(|_, w| w.smp8().bits(smp as u8)),
865 9 => self.regs.smpr1().modify(|_, w| w.smp9().bits(smp as u8)),
866 11 => self.regs.smpr2().modify(|_, w| w.smp10().bits(smp as u8)),
867 12 => self.regs.smpr2().modify(|_, w| w.smp12().bits(smp as u8)),
868 13 => self.regs.smpr2().modify(|_, w| w.smp13().bits(smp as u8)),
869 14 => self.regs.smpr2().modify(|_, w| w.smp14().bits(smp as u8)),
870 15 => self.regs.smpr2().modify(|_, w| w.smp15().bits(smp as u8)),
871 16 => self.regs.smpr2().modify(|_, w| w.smp16().bits(smp as u8)),
872 17 => self.regs.smpr2().modify(|_, w| w.smp17().bits(smp as u8)),
873 18 => self.regs.smpr2().modify(|_, w| w.smp18().bits(smp as u8)),
874 // 19 => self.regs.smpr2().modify(|_, w| w.smp19().bits(smp as u8)),
875 // 20 => self.regs.smpr2().modify(|_, w| w.smp20().bits(smp as u8)),
876 _ => unreachable!(),
877 };
878 }
879
880 Ok(())
881 // self.enable();
882 }
883
884
885 /// Find and store the internal voltage reference, to improve conversion from reading
886 /// to voltage accuracy. See L44 RM, section 16.4.34: "Monitoring the internal voltage reference"
887 fn setup_vdda(&mut self, ahb_freq: u32) -> Result<()> {
888 let common_regs = unsafe { &*pac::$ADC_COMMON::ptr() };
889 // RM: It is possible to monitor the internal voltage reference (VREFINT) to have a reference point for
890 // evaluating the ADC VREF+ voltage level.
891 // The internal voltage reference is internally connected to the input channel 0 of the ADC1
892 // (ADC1_INP0).
893
894 // todo: On H7, you may need to use ADC3 for this...
895
896 // Regardless of which ADC we're on, we take this reading using ADC1.
897 self.vdda_calibrated = if self.device != AdcDevice::One {
898 // todo: What if ADC1 is already enabled and configured differently?
899 // todo: Either way, if you're also using ADC1, this will screw things up⋅.
900
901 // let dp = unsafe { pac::Peripherals::steal() };
902 //
903 // #[cfg(feature = "l5")]
904 // let dp_adc = dp.ADC;
905 // #[cfg(not(feature = "l5"))]
906 // let dp_adc = dp.ADC1;
907
908 // If we're currently using ADC1 (and this is a different ADC), skip this step for now;
909 // VDDA will be wrong,
910 // and all readings using voltage conversion will be wrong.
911 // todo: Take an ADC1 reading if this is the case, or let the user pass in VDDA from there.
912 // if dp_adc.cr().read().aden().bit_is_set() {
913 // self.vdda_calibrated = 3.3; // A guess.
914 // return
915 // }
916
917 // todo: Get this working.
918 // let mut adc1 = Adc::new_adc1(
919 // dp_adc,
920 // AdcDevice::One,
921 // // We use self cfg, in case ADC1 is on the same common regs as this; we don't
922 // // want it overwriting prescaler and clock cfg.
923 // self.cfg.clone(),
924 // ahb_freq,
925 // );
926 // adc1.disable();
927
928 // This fn will be called recursively for ADC1, generating the vdda value we need.
929 // adc1.vdda_calibrated
930 3.3
931 } else {
932 // "Table 24. Embedded internal voltage reference" states that the sample time needs to be
933 // at a minimum 4 us. With 640.5 ADC cycles we have a minimum of 8 us at 80 MHz, leaving
934 // some headroom.
935
936 common_regs.ccr().modify(|_, w| w.vrefen().bit(true));
937 // User manual table: "Embedded internal voltage reference" states that it takes a maximum of 12 us
938 // to stabilize the internal voltage reference, we wait a little more.
939
940 // todo: Not sure what to set this delay to and how to change it based on variant, so picking
941 // todo something conservative.
942 crate::delay_us(100, ahb_freq);
943
944 // This sample time is overkill.
945 // Note that you will need to reset the sample time if you use this channel on this
946 // ADC for something other than reading vref later.
947 self.set_sample_time(VREFINT_CH, SampleTime::T601)?;
948 let reading = self.read(VREFINT_CH)?;
949 self.stop_conversions()?;
950
951 common_regs.ccr().modify(|_, w| w.vrefen().clear_bit());
952
953 // The VDDA power supply voltage applied to the microcontroller may be subject to variation or
954 // not precisely known. The embedded internal voltage reference (VREFINT) and its calibration
955 // data acquired by the ADC during the manufacturing process at VDDA = 3.0 V can be used to
956 // evaluate the actual VDDA voltage level.
957 // The following formula gives the actual VDDA voltage supplying the device:
958 // VDDA = 3.0 V x VREFINT_CAL / VREFINT_DATA
959 // where:
960 // • VREFINT_CAL is the VREFINT calibration value
961 // • VREFINT_DATA is the actual VREFINT output value converted by ADC
962
963 // todo: This address may be different on different MCUs, even within the same family.
964 // Although, it seems relatively consistent. Check User Manuals.
965 let vrefint_cal: u16 = unsafe { ptr::read_volatile(&*(VREFINT_ADDR as *const _)) };
966 VREFINT_VOLTAGE * vrefint_cal as f32 / reading as f32
967 };
968
969 Ok(())
970 }
971
972 /// Convert a raw measurement into a voltage in Volts, using the calibrated VDDA.
973 /// See RM0394, section 16.4.34
974 pub fn reading_to_voltage(&self, reading: u16) -> f32 {
975 // RM:
976 // Converting a supply-relative ADC measurement to an absolute voltage value
977 // The ADC is designed to deliver a digital value corresponding to the ratio between the analog
978 // power supply and the voltage applied on the converted channel. For most application use
979 // cases, it is necessary to convert this ratio into a voltage independent of VDDA. For
980 // applications where VDDA is known and ADC converted values are right-aligned you can use
981 // the following formula to get this absolute value:
982
983 // V_CHANNELx = V_DDA / FULL_SCALE x ADCx_DATA
984
985 // Where:
986 // • VREFINT_CAL is the VREFINT calibration value
987 // • ADC_DATA is the value measured by the ADC on channel x (right-aligned)
988 // • VREFINT_DATA is the actual VREFINT output value converted by the ADC
989 // • FULL_SCALE is the maximum digital value of the ADC output. For example with 12-bit
990 // resolution, it will be 212 − 1 = 4095 or with 8-bit resolution, 28 − 1 = 255
991 // todo: FULL_SCALE will be different for 16-bit. And differential?
992
993 self.vdda_calibrated / 4_096. * reading as f32
994 }
995
996 /// Start a conversion: Either a single measurement, or continuous conversions.
997 /// Blocks until the conversion is complete.
998 /// See L4 RM 16.4.15 for details.
999 pub fn start_conversion(&mut self, sequence: &[u8]) -> Result<()> {
1000 // todo: You should call this elsewhere, once, to prevent unneded reg writes.
1001 for (i, channel) in sequence.iter().enumerate() {
1002 self.set_sequence(*channel, i as u8 + 1); // + 1, since sequences start at 1.
1003 }
1004
1005 // L4 RM: In Single conversion mode, the ADC performs once all the conversions of the channels.
1006 // This mode is started with the CONT bit at 0 by either:
1007 // • Setting the ADSTART bit in the ADC_CR register (for a regular channel)
1008 // • Setting the JADSTART bit in the ADC_CR register (for an injected channel)
1009 // • External hardware trigger event (for a regular or injected channel)
1010 // (Here, we assume a regular channel)
1011 self.regs.cr().modify(|_, w| w.adstart().bit(true)); // Start
1012
1013 // After the regular sequence is complete, after each conversion is complete,
1014 // the EOC (end of regular conversion) flag is set.
1015 // After the regular sequence is complete: The EOS (end of regular sequence) flag is set.
1016 // wait until complete.
1017 bounded_loop!(
1018 self.regs.isr().read().eos().bit_is_clear(),
1019 Error::RegisterUnchanged
1020 );
1021
1022 Ok(())
1023 }
1024
1025 #[cfg(feature = "h7")]
1026 /// Read data from a conversion. In OneShot mode, this will generally be run right
1027 /// after `start_conversion`.
1028 pub fn read_result(&mut self, ch: u8) -> u16 {
1029 #[cfg(not(feature = "h735"))]
1030 self.regs.pcsel().modify(|r, w| unsafe { w.pcsel().bits(r.pcsel().bits() & !(1 << ch)) });
1031
1032 // todo: Figure this out, and put back (July 2025/pack 0.16)
1033 // #[cfg(feature = "h735")]
1034 // match ch {
1035 // 0 => self.regs.pcsel().modify(|r, w| w.pcsel0().bit(true)),
1036 // 1 => self.regs.pcsel().modify(|r, w| w.pcsel1().bit(true)),
1037 // 2 => self.regs.pcsel().modify(|r, w| w.pcsel2().bit(true)),
1038 // 3 => self.regs.pcsel().modify(|r, w| w.pcsel3().bit(true)),
1039 // 4 => self.regs.pcsel().modify(|r, w| w.pcsel4().bit(true)),
1040 // 5 => self.regs.pcsel().modify(|r, w| w.pcsel5().bit(true)),
1041 // 6 => self.regs.pcsel().modify(|r, w| w.pcsel6().bit(true)),
1042 // 7 => self.regs.pcsel().modify(|r, w| w.pcsel7().bit(true)),
1043 // 8 => self.regs.pcsel().modify(|r, w| w.pcsel8().bit(true)),
1044 // 9 => self.regs.pcsel().modify(|r, w| w.pcsel9().bit(true)),
1045 // 10 => self.regs.pcsel().modify(|r, w| w.pcsel10().bit(true)),
1046 // 11 => self.regs.pcsel().modify(|r, w| w.pcsel11().bit(true)),
1047 // 12 => self.regs.pcsel().modify(|r, w| w.pcsel12().bit(true)),
1048 // 13 => self.regs.pcsel().modify(|r, w| w.pcsel13().bit(true)),
1049 // 14 => self.regs.pcsel().modify(|r, w| w.pcsel14().bit(true)),
1050 // 15 => self.regs.pcsel().modify(|r, w| w.pcsel15().bit(true)),
1051 // 16 => self.regs.pcsel().modify(|r, w| w.pcsel16().bit(true)),
1052 // 17 => self.regs.pcsel().modify(|r, w| w.pcsel17().bit(true)),
1053 // 18 => self.regs.pcsel().modify(|r, w| w.pcsel18().bit(true)),
1054 // 19=> self.regs.pcsel().modify(|r, w| w.pcsel19().bit(true)),
1055 // _ => ()
1056 // }
1057
1058 return self.regs.dr().read().bits() as u16;
1059 return self.regs.dr().read().rdata().bits() as u16;
1060 }
1061
1062 #[cfg(not(feature = "h7"))]
1063 /// Read data from a conversion. In OneShot mode, this will generally be run right
1064 /// after `start_conversion`.
1065 pub fn read_result(&mut self) -> u16 {
1066 #[cfg(feature = "l4")]
1067 return self.regs.dr().read().bits() as u16;
1068 #[cfg(not(feature = "l4"))]
1069 return self.regs.dr().read().rdata().bits() as u16;
1070 }
1071
1072 /// Take a single reading; return a raw integer value.
1073 pub fn read(&mut self, channel: u8) -> Result<u16> {
1074 self.start_conversion(&[channel])?;
1075 #[cfg(feature = "h7")]
1076 return Ok(self.read_result(channel));
1077 #[cfg(not(feature = "h7"))]
1078 return Ok(self.read_result());
1079 }
1080
1081 /// Take a single reading; return a voltage.
1082 pub fn read_voltage(&mut self, channel: u8) -> Result<f32> {
1083 let reading = self.read(channel)?;
1084 Ok(self.reading_to_voltage(reading))
1085 }
1086
1087 /// Select and activate a trigger. See G4 RM, section 21.4.18:
1088 /// Conversion on external trigger and trigger polarit
1089 pub fn set_trigger(&mut self, trigger: Trigger, edge: TriggerEdge) {
1090 self.regs.cfgr().modify(|_, w| unsafe {
1091 w.exten().bits(edge as u8);
1092 w.extsel().bits(trigger as u8)
1093 });
1094 }
1095
1096 #[cfg(not(any(feature = "f4", feature = "l552", feature = "h5")))]
1097 /// Take a reading, using DMA. Sets conversion sequence; no need to set it directly.
1098 /// Note that the `channel` argument is unused on F3 and L4, since it is hard-coded,
1099 /// and can't be configured using the DMAMUX peripheral. (`dma::mux()` fn).
1100 pub unsafe fn read_dma(
1101 &mut self, buf: &mut [u16],
1102 adc_channels: &[u8],
1103 dma_channel: DmaChannel,
1104 channel_cfg: ChannelCfg,
1105 dma_periph: dma::DmaPeriph,
1106 ) -> Result<()> {
1107 let (ptr, len) = (buf.as_mut_ptr(), buf.len());
1108 // The software is allowed to write (dmaen and dmacfg) only when ADSTART=0 and JADSTART=0 (which
1109 // ensures that no conversion is ongoing)
1110 self.stop_conversions()?;
1111
1112 #[cfg(not(feature = "h7"))]
1113 self.regs.cfgr().modify(|_, w| {
1114 w.dmacfg().bit(channel_cfg.circular == dma::Circular::Enabled);
1115 w.dmaen().bit(true)
1116 });
1117
1118 #[cfg(all(feature = "h7", not(feature = "h735")))]
1119 self.regs.cfgr().modify(|_, w| {
1120 // Note: To use non-DMA after this has been set, need to configure manually.
1121 // ie set back to 0b00.
1122 w.dmngt().bits(if channel_cfg.circular == dma::Circular::Enabled { 0b11 } else { 0b01 })
1123 });
1124
1125 // todo: How to do in H735? Pac 0.16 change? Jully 2025.
1126
1127 // L44 RM, Table 41. "DMA1 requests for each channel
1128 // todo: DMA2 support.
1129 #[cfg(any(feature = "f3", feature = "l4"))]
1130 let dma_channel = match self.device {
1131 AdcDevice::One => DmaInput::Adc1.dma1_channel(),
1132 AdcDevice::Two => DmaInput::Adc2.dma1_channel(),
1133 _ => panic!("DMA on ADC beyond 2 is not supported. If it is for your MCU, please submit an issue \
1134 or PR on Github.")
1135 };
1136
1137 #[cfg(feature = "l4")]
1138 match dma_periph {
1139 dma::DmaPeriph::Dma1 => {
1140 let mut regs = unsafe { &(*pac::DMA1::ptr()) };
1141 match self.device {
1142 AdcDevice::One => dma::channel_select(&mut regs, DmaInput::Adc1),
1143 AdcDevice::Two => dma::channel_select(&mut regs, DmaInput::Adc2),
1144 _ => unimplemented!(),
1145 }
1146 }
1147 dma::DmaPeriph::Dma2 => {
1148 let mut regs = unsafe { &(*pac::DMA2::ptr()) };
1149 match self.device {
1150 AdcDevice::One => dma::channel_select(&mut regs, DmaInput::Adc1),
1151 AdcDevice::Two => dma::channel_select(&mut regs, DmaInput::Adc2),
1152 _ => unimplemented!(),
1153 }
1154 }
1155 }
1156
1157 let mut seq_len = 0;
1158 for (i, ch) in adc_channels.iter().enumerate() {
1159 self.set_sequence(*ch, i as u8 + 1);
1160 seq_len += 1;
1161 }
1162 self.set_sequence_len(seq_len);
1163
1164 self.regs.cr().modify(|_, w| w.adstart().bit(true)); // Start
1165
1166 // Since converted channel values are stored into a unique data register, it is useful to use
1167 // DMA for conversion of more than one channel. This avoids the loss of the data already
1168 // stored in the ADC_DR register.
1169 // When the DMA mode is enabled (DMAEN bit set to 1 in the ADC_CFGR register in single
1170 // ADC mode or MDMA different from 0b00 in dual ADC mode), a DMA request is generated
1171 // after each conversion of a channel. This allows the transfer of the converted data from the
1172 // ADC_DR register to the destination location selected by the software.
1173 // Despite this, if an overrun occurs (OVR=1) because the DMA could not serve the DMA
1174 // transfer request in time, the ADC stops generating DMA requests and the data
1175 // corresponding to the new conversion is not transferred by the DMA. Which means that all
1176 // the data transferred to the RAM can be considered as valid.
1177 // Depending on the configuration of OVRMOD bit, the data is either preserved or overwritten
1178 // (refer to Section : ADC overrun (OVR, OVRMOD)).
1179 // The DMA transfer requests are blocked until the software clears the OVR bit.
1180 // Two different DMA modes are proposed depending on the application use and are
1181 // configured with bit DMACFG of the ADC_CFGR register in single ADC mode, or with bit
1182 // DMACFG of the ADC_CCR register in dual ADC mode:
1183 // • DMA one shot mode (DMACFG=0).
1184 // This mode is suitable when the DMA is programmed to transfer a fixed number of data.
1185 // • DMA circular mode (DMACFG=1)
1186 // This mode is suitable when programming the DMA in circular mode.
1187
1188
1189 // In [DMA one shot mode], the ADC generates a DMA transfer request each time a new conversion data
1190 // is available and stops generating DMA requests once the DMA has reached the last DMA
1191 // transfer (when DMA_EOT interrupt occurs - refer to DMA paragraph) even if a conversion
1192 // has been started again.
1193 // When the DMA transfer is complete (all the transfers configured in the DMA controller have
1194 // been done):
1195 // • The content of the ADC data register is frozen.
1196 // • Any ongoing conversion is aborted with partial result discarded.
1197 // • No new DMA request is issued to the DMA controller. This avoids generating an
1198 // overrun error if there are still conversions which are started.
1199 // • Scan sequence is stopped and reset.
1200 // • The DMA is stopped.
1201
1202 let num_data = len as u32;
1203
1204 match dma_periph {
1205 dma::DmaPeriph::Dma1 => {
1206 let mut regs = unsafe { &(*pac::DMA1::ptr()) };
1207 dma::cfg_channel(
1208 &mut regs,
1209 dma_channel,
1210 self.regs.dr().as_ptr() as u32,
1211 ptr as u32,
1212 num_data,
1213 dma::Direction::ReadFromPeriph,
1214 dma::DataSize::S16,
1215 dma::DataSize::S16,
1216 channel_cfg,
1217 )
1218 }
1219 #[cfg(dma2)]
1220 dma::DmaPeriph::Dma2 => {
1221 let mut regs = unsafe { &(*pac::DMA2::ptr()) };
1222 dma::cfg_channel(
1223 &mut regs,
1224 dma_channel,
1225 self.regs.dr().as_ptr() as u32,
1226 ptr as u32,
1227 num_data,
1228 dma::Direction::ReadFromPeriph,
1229 dma::DataSize::S16,
1230 dma::DataSize::S16,
1231 channel_cfg,
1232 )
1233 }
1234 }
1235 }
1236
1237 /// Enable a specific type of ADC interrupt.
1238 pub fn enable_interrupt(&mut self, interrupt: AdcInterrupt) {
1239 self.regs.ier().modify(|_, w| match interrupt {
1240 AdcInterrupt::Ready => w.adrdyie().bit(true),
1241 AdcInterrupt::EndOfConversion => w.eocie().bit(true),
1242 AdcInterrupt::EndOfSequence => w.eosie().bit(true),
1243 AdcInterrupt::EndofConversionInjected => w.jeocie().bit(true),
1244 AdcInterrupt::EndOfSequenceInjected => w.jeosie().bit(true),
1245 AdcInterrupt::Watchdog1 => w.awd1ie().bit(true),
1246 AdcInterrupt::Watchdog2 => w.awd2ie().bit(true),
1247 AdcInterrupt::Watchdog3 => w.awd3ie().bit(true),
1248 AdcInterrupt::EndOfSamplingPhase => w.eosmpie().bit(true),
1249 AdcInterrupt::Overrun => w.ovrie().bit(true),
1250 AdcInterrupt::InjectedOverflow => w.jqovfie().bit(true),
1251 });
1252 }
1253
1254 /// Clear an interrupt flag of the specified type. Consider running this in the
1255 /// corresponding ISR.
1256 pub fn clear_interrupt(&mut self, interrupt: AdcInterrupt) {
1257 self.regs.isr().write(|w| match interrupt {
1258 AdcInterrupt::Ready => w.adrdy().bit(true),
1259 AdcInterrupt::EndOfConversion => w.eoc().bit(true),
1260 AdcInterrupt::EndOfSequence => w.eos().bit(true),
1261 AdcInterrupt::EndofConversionInjected => w.jeoc().bit(true),
1262 AdcInterrupt::EndOfSequenceInjected => w.jeos().bit(true),
1263 AdcInterrupt::Watchdog1 => w.awd1().bit(true),
1264 AdcInterrupt::Watchdog2 => w.awd2().bit(true),
1265 AdcInterrupt::Watchdog3 => w.awd3().bit(true),
1266 AdcInterrupt::EndOfSamplingPhase => w.eosmp().bit(true),
1267 AdcInterrupt::Overrun => w.ovr().bit(true),
1268 AdcInterrupt::InjectedOverflow => w.jqovf().bit(true),
1269 });
1270 // match interrupt {
1271 // AdcInterrupt::Ready => self.regs.icr().write(|_w| w.adrdy().bit(true)),
1272 // AdcInterrupt::EndOfConversion => self.regs.icr().write(|w| w.eoc().bit(true)),
1273 // AdcInterrupt::EndOfSequence => self.regs.icr().write(|_w| w.eos().bit(true)),
1274 // AdcInterrupt::EndofConversionInjected => self.regs.icr().write(|_w| w.jeoc().bit(true)),
1275 // AdcInterrupt::EndOfSequenceInjected => self.regs.icr().write(|_w| w.jeos().bit(true)),
1276 // AdcInterrupt::Watchdog1 => self.regs.icr().write(|_w| w.awd1().bit(true)),
1277 // AdcInterrupt::Watchdog2 => self.regs.icr().write(|_w| w.awd2().bit(true)),
1278 // AdcInterrupt::Watchdog3 => self.regs.icr().write(|_w| w.awd3().bit(true)),
1279 // AdcInterrupt::EndOfSamplingPhase => self.regs.icr().write(|_w| w.eosmp().bit(true)),
1280 // AdcInterrupt::Overrun => self.regs.icr().write(|_w| w.ovr().bit(true)),
1281 // AdcInterrupt::InjectedOverflow => self.regs.icr().write(|_w| w.jqovf().bit(true)),
1282 // }
1283 }
1284
1285
1286 /// Print the (raw) contents of the status register.
1287 pub fn read_status(&self) -> u32 {
1288 unsafe { self.regs.isr().read().bits() }
1289 }
1290 }
1291 }
1292}
1293
1294#[cfg(any(feature = "f301", feature = "f302", feature = "f303",))]
1295hal!(ADC1, ADC1_2, adc1, 12);
1296
1297#[cfg(any(feature = "f302", feature = "f303",))]
1298hal!(ADC2, ADC1_2, adc2, 12);
1299
1300#[cfg(any(feature = "f303"))]
1301hal!(ADC3, ADC3_4, adc3, 34);
1302
1303#[cfg(any(feature = "f303"))]
1304hal!(ADC4, ADC3_4, adc4, 34);
1305
1306#[cfg(any(feature = "l4", feature = "l5"))]
1307hal!(ADC1, ADC_COMMON, adc1, _);
1308
1309#[cfg(any(
1310 feature = "l4x1",
1311 feature = "l4x2",
1312 feature = "l412",
1313 feature = "l4x5",
1314 feature = "l4x6",
1315))]
1316hal!(ADC2, ADC_COMMON, adc2, _);
1317
1318#[cfg(any(feature = "l4x5", feature = "l4x6",))]
1319hal!(ADC3, ADC_COMMON, adc3, _);
1320
1321// todo Implement ADC3 on H7. The issue is the enable / reset being on ahb4.
1322cfg_if! {
1323 if #[cfg(feature = "h7")] {
1324 hal!(ADC1, ADC12_COMMON, adc1, 12);
1325 hal!(ADC2, ADC12_COMMON, adc2, 12);
1326 hal!(ADC3, ADC3_COMMON, adc3, 3);
1327 }
1328}
1329
1330cfg_if! {
1331 if #[cfg(feature = "g4")] {
1332 hal!(ADC1, ADC12_COMMON, adc1, 12);
1333 hal!(ADC2, ADC12_COMMON, adc2, 12);
1334 }
1335}
1336
1337#[cfg(all(feature = "g4", not(any(feature = "g431", feature = "g441"))))]
1338hal!(ADC3, ADC345_COMMON, adc3, 345);
1339
1340cfg_if! {
1341 if #[cfg(any(feature = "g473", feature = "g474", feature = "g483", feature = "g484"))] {
1342 hal!(ADC4, ADC345_COMMON, adc4, 345);
1343 hal!(ADC5, ADC345_COMMON, adc5, 345);
1344 }
1345}
1346
1347// todo F4 as (depending on variant?) ADC 1, 2, 3