stm32f1xx_hal/
adc.rs

1//! # API for the Analog to Digital converter
2
3use core::marker::PhantomData;
4use core::ops::Deref;
5use embedded_hal_02::adc::{Channel, OneShot};
6use fugit::HertzU32 as Hertz;
7
8#[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl")))]
9use crate::dma::dma2;
10use crate::dma::{dma1, CircBuffer, Receive, RxDma, Transfer, TransferPayload, W};
11use crate::gpio::{self, Analog};
12use crate::rcc::{Enable, Rcc, Reset};
13use crate::time::kHz;
14use core::sync::atomic::{self, Ordering};
15use cortex_m::asm::delay;
16use embedded_dma::WriteBuffer;
17
18use crate::pac::{self, RCC};
19use crate::pacext::adc::{AdcRB, Cr1W, Cr2R, Cr2W, Dr, ExtSelW};
20
21const TEMP_CHANNEL: u8 = 16;
22const VREF_CHANNEL: u8 = 17;
23
24/// Continuous mode
25pub struct Continuous;
26/// Scan mode
27pub struct Scan;
28
29/// ADC configuration
30pub struct Adc<ADC> {
31    rb: ADC,
32    sample_time: SampleTime,
33    align: Align,
34    sysclk: Hertz,
35    adcclk: Hertz,
36}
37
38/// ADC sampling time
39///
40/// Options for the sampling time, each is T + 0.5 ADC clock cycles.
41#[allow(non_camel_case_types)]
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub enum SampleTime {
44    /// 1.5 cycles sampling time
45    T_1,
46    /// 7.5 cycles sampling time
47    T_7,
48    /// 13.5 cycles sampling time
49    T_13,
50    /// 28.5 cycles sampling time
51    T_28,
52    /// 41.5 cycles sampling time
53    T_41,
54    /// 55.5 cycles sampling time
55    T_55,
56    /// 71.5 cycles sampling time
57    T_71,
58    /// 239.5 cycles sampling time
59    T_239,
60}
61
62impl Default for SampleTime {
63    /// Get the default sample time (currently 28.5 cycles)
64    fn default() -> Self {
65        SampleTime::T_28
66    }
67}
68
69impl From<SampleTime> for pac::adc1::smpr1::SMP10 {
70    fn from(val: SampleTime) -> Self {
71        use SampleTime::*;
72        match val {
73            T_1 => Self::Cycles1_5,
74            T_7 => Self::Cycles7_5,
75            T_13 => Self::Cycles13_5,
76            T_28 => Self::Cycles28_5,
77            T_41 => Self::Cycles41_5,
78            T_55 => Self::Cycles55_5,
79            T_71 => Self::Cycles71_5,
80            T_239 => Self::Cycles239_5,
81        }
82    }
83}
84
85#[derive(Clone, Copy, Debug, PartialEq, Eq)]
86/// ADC data register alignment
87pub enum Align {
88    /// Right alignment of output data
89    Right,
90    /// Left alignment of output data
91    Left,
92}
93
94impl Default for Align {
95    /// Default: right alignment
96    fn default() -> Self {
97        Align::Right
98    }
99}
100
101impl From<Align> for pac::adc1::cr2::ALIGN {
102    fn from(val: Align) -> Self {
103        match val {
104            Align::Right => Self::Right,
105            Align::Left => Self::Left,
106        }
107    }
108}
109
110macro_rules! adc_pins {
111    ($ADC:ty, $($pin:ty => $chan:literal),+ $(,)*) => {
112        $(
113            impl Channel<$ADC> for $pin {
114                type ID = u8;
115
116                fn channel() -> u8 { $chan }
117            }
118        )+
119    };
120}
121
122adc_pins!(pac::ADC1,
123    gpio::PA0<Analog> => 0,
124    gpio::PA1<Analog> => 1,
125    gpio::PA2<Analog> => 2,
126    gpio::PA3<Analog> => 3,
127    gpio::PA4<Analog> => 4,
128    gpio::PA5<Analog> => 5,
129    gpio::PA6<Analog> => 6,
130    gpio::PA7<Analog> => 7,
131    gpio::PB0<Analog> => 8,
132    gpio::PB1<Analog> => 9,
133    gpio::PC0<Analog> => 10,
134    gpio::PC1<Analog> => 11,
135    gpio::PC2<Analog> => 12,
136    gpio::PC3<Analog> => 13,
137    gpio::PC4<Analog> => 14,
138    gpio::PC5<Analog> => 15,
139);
140
141#[cfg(any(feature = "stm32f103", feature = "connectivity"))]
142adc_pins!(pac::ADC2,
143    gpio::PA0<Analog> => 0,
144    gpio::PA1<Analog> => 1,
145    gpio::PA2<Analog> => 2,
146    gpio::PA3<Analog> => 3,
147    gpio::PA4<Analog> => 4,
148    gpio::PA5<Analog> => 5,
149    gpio::PA6<Analog> => 6,
150    gpio::PA7<Analog> => 7,
151    gpio::PB0<Analog> => 8,
152    gpio::PB1<Analog> => 9,
153    gpio::PC0<Analog> => 10,
154    gpio::PC1<Analog> => 11,
155    gpio::PC2<Analog> => 12,
156    gpio::PC3<Analog> => 13,
157    gpio::PC4<Analog> => 14,
158    gpio::PC5<Analog> => 15,
159);
160
161#[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl")))]
162adc_pins!(pac::ADC3,
163    gpio::PA0<Analog> => 0,
164    gpio::PA1<Analog> => 1,
165    gpio::PA2<Analog> => 2,
166    gpio::PA3<Analog> => 3,
167    gpio::PF6<Analog> => 4,
168    gpio::PF7<Analog> => 5,
169    gpio::PF8<Analog> => 6,
170    gpio::PF9<Analog> => 7,
171    gpio::PF10<Analog> => 8,
172    gpio::PC0<Analog> => 10,
173    gpio::PC1<Analog> => 11,
174    gpio::PC2<Analog> => 12,
175    gpio::PC3<Analog> => 13,
176);
177
178/// Stored ADC config can be restored using the `Adc::restore_cfg` method
179#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
180pub struct StoredConfig(SampleTime, Align);
181
182pub trait Instance:
183    crate::Sealed + crate::Ptr<RB: AdcRB> + Deref<Target = Self::RB> + Reset + Enable
184{
185    type ExtSel;
186    #[doc(hidden)]
187    fn set_extsel(&self, trigger: Self::ExtSel);
188}
189
190impl Instance for pac::ADC1 {
191    type ExtSel = crate::pac::adc1::cr2::EXTSEL;
192    fn set_extsel(&self, trigger: Self::ExtSel) {
193        self.cr2().modify(|_, w| w.extsel().variant(trigger));
194    }
195}
196#[cfg(any(feature = "stm32f103", feature = "connectivity"))]
197impl Instance for pac::ADC2 {
198    type ExtSel = crate::pac::adc2::cr2::EXTSEL;
199    fn set_extsel(&self, trigger: Self::ExtSel) {
200        self.cr2().modify(|_, w| w.extsel().variant(trigger));
201    }
202}
203#[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl")))]
204impl Instance for pac::ADC3 {
205    type ExtSel = crate::pac::adc3::cr2::EXTSEL;
206    fn set_extsel(&self, trigger: Self::ExtSel) {
207        self.cr2().modify(|_, w| w.extsel().variant(trigger));
208    }
209}
210
211pub trait AdcExt: Sized + Instance {
212    fn adc(self, rcc: &mut Rcc) -> Adc<Self>;
213}
214
215impl<ADC: Instance> AdcExt for ADC {
216    fn adc(self, rcc: &mut Rcc) -> Adc<Self> {
217        Adc::new(self, rcc)
218    }
219}
220
221impl<ADC: Instance> Adc<ADC> {
222    /// Init a new Adc
223    ///
224    /// Sets all configurable parameters to one-shot defaults,
225    /// performs a boot-time calibration.
226    pub fn new(adc: ADC, rcc: &mut Rcc) -> Self {
227        let mut s = Self {
228            rb: adc,
229            sample_time: SampleTime::default(),
230            align: Align::default(),
231            sysclk: rcc.clocks.sysclk(),
232            adcclk: rcc.clocks.adcclk(),
233        };
234        s.enable_clock(rcc);
235        s.power_down();
236        s.reset(rcc);
237        s.setup_oneshot();
238        s.power_up();
239
240        // The manual states that we need to wait two ADC clocks cycles after power-up
241        // before starting calibration, we already delayed in the power-up process, but
242        // if the adc clock is too low that was not enough.
243        if s.adcclk < kHz(2500) {
244            let two_adc_cycles = s.sysclk / s.adcclk * 2;
245            let already_delayed = s.sysclk / kHz(800);
246            if two_adc_cycles > already_delayed {
247                delay(two_adc_cycles - already_delayed);
248            }
249        }
250        s.calibrate();
251        s
252    }
253
254    /// Save current ADC config
255    pub fn save_cfg(&mut self) -> StoredConfig {
256        StoredConfig(self.sample_time, self.align)
257    }
258
259    /// Restore saved ADC config
260    pub fn restore_cfg(&mut self, cfg: StoredConfig) {
261        self.sample_time = cfg.0;
262        self.align = cfg.1;
263    }
264
265    /// Reset the ADC config to default, return existing config
266    pub fn default_cfg(&mut self) -> StoredConfig {
267        let cfg = self.save_cfg();
268        self.sample_time = SampleTime::default();
269        self.align = Align::default();
270        cfg
271    }
272
273    /// Set ADC sampling time
274    ///
275    /// Options can be found in [SampleTime].
276    pub fn set_sample_time(&mut self, t_samp: SampleTime) {
277        self.sample_time = t_samp;
278    }
279
280    /// Set the Adc result alignment
281    ///
282    /// Options can be found in [Align].
283    pub fn set_align(&mut self, align: Align) {
284        self.align = align;
285    }
286
287    /// Returns the largest possible sample value for the current settings
288    pub fn max_sample(&self) -> u16 {
289        match self.align {
290            Align::Left => u16::MAX,
291            Align::Right => (1 << 12) - 1,
292        }
293    }
294
295    #[inline(always)]
296    pub fn set_external_trigger(&mut self, trigger: ADC::ExtSel) {
297        self.rb.set_extsel(trigger);
298    }
299
300    fn power_up(&mut self) {
301        self.rb.cr2().modify(|_, w| w.adon().set_bit());
302
303        // The reference manual says that a stabilization time is needed after power_up,
304        // this time can be found in the datasheets.
305        // Here we are delaying for approximately 1us, considering 1.25 instructions per
306        // cycle. Do we support a chip which needs more than 1us ?
307        delay(self.sysclk / kHz(800));
308    }
309
310    fn power_down(&mut self) {
311        self.rb.cr2().modify(|_, w| w.adon().clear_bit());
312    }
313
314    fn reset(&mut self, rcc: &mut RCC) {
315        ADC::reset(rcc);
316    }
317
318    fn enable_clock(&mut self, rcc: &mut RCC) {
319        ADC::enable(rcc);
320    }
321
322    fn disable_clock(&mut self, rcc: &mut RCC) {
323        ADC::disable(rcc);
324    }
325
326    fn calibrate(&mut self) {
327        /* reset calibration */
328        self.rb.cr2().modify(|_, w| w.rstcal().set_bit());
329        while self.rb.cr2().read().rstcal().bit_is_set() {}
330
331        /* calibrate */
332        self.rb.cr2().modify(|_, w| w.cal().set_bit());
333        while self.rb.cr2().read().cal().bit_is_set() {}
334    }
335
336    fn setup_oneshot(&mut self) {
337        self.rb.cr2().modify(|_, w| {
338            w.cont().clear_bit();
339            w.exttrig().set_bit();
340            w.select_swstart()
341        });
342
343        self.rb
344            .cr1()
345            .modify(|_, w| w.scan().clear_bit().discen().set_bit());
346
347        self.rb.sqr1().modify(|_, w| w.l().set(0b0));
348    }
349
350    fn set_channel_sample_time(&mut self, chan: u8, sample_time: SampleTime) {
351        let sample_time = sample_time.into();
352        match chan {
353            0..=9 => self
354                .rb
355                .smpr2()
356                .modify(|_, w| w.smp(chan).variant(sample_time)),
357            10..=17 => self
358                .rb
359                .smpr1()
360                .modify(|_, w| w.smp(chan - 10).variant(sample_time)),
361            _ => unreachable!(),
362        };
363    }
364
365    fn set_regular_sequence(&mut self, channels: &[u8]) {
366        let mut iter = channels.chunks(6);
367        unsafe {
368            if let Some(chunk) = iter.next() {
369                self.rb.sqr3().write(|w| {
370                    for (i, &c) in chunk.iter().enumerate() {
371                        w.sq(i as u8).bits(c);
372                    }
373                    w
374                });
375            }
376            if let Some(chunk) = iter.next() {
377                self.rb.sqr2().write(|w| {
378                    for (i, &c) in chunk.iter().enumerate() {
379                        w.sq(i as u8).bits(c);
380                    }
381                    w
382                });
383            }
384            self.rb.sqr1().write(|w| {
385                if let Some(chunk) = iter.next() {
386                    for (i, &c) in chunk.iter().enumerate() {
387                        w.sq(i as u8).bits(c);
388                    }
389                }
390                w.l().set((channels.len() - 1) as u8)
391            });
392        }
393    }
394
395    fn set_continuous_mode(&mut self, continuous: bool) {
396        self.rb.cr2().modify(|_, w| w.cont().bit(continuous));
397    }
398
399    fn set_discontinuous_mode(&mut self, channels_count: Option<u8>) {
400        self.rb.cr1().modify(|_, w| match channels_count {
401            Some(count) => w.discen().set_bit().discnum().set(count),
402            None => w.discen().clear_bit(),
403        });
404    }
405
406    /**
407      Performs an ADC conversion
408
409      NOTE: Conversions can be started by writing a 1 to the ADON
410      bit in the `CR2` while it is already 1, and no other bits
411      are being written in the same operation. This means that
412      the EOC bit *might* be set already when entering this function
413      which can cause a read of stale values
414
415      The check for `cr2.swstart.bit_is_set` *should* fix it, but
416      does not. Therefore, ensure you do not do any no-op modifications
417      to `cr2` just before calling this function
418    */
419    fn convert(&mut self, chan: u8) -> u16 {
420        // Dummy read in case something accidentally triggered
421        // a conversion by writing to CR2 without changing any
422        // of the bits
423        self.rb.dr().read().data().bits();
424
425        self.set_channel_sample_time(chan, self.sample_time);
426        self.rb.sqr3().modify(|_, w| unsafe { w.sq1().bits(chan) });
427
428        // ADC start conversion of regular sequence
429        self.rb.cr2().modify(|_, w| {
430            w.swstart().set_bit();
431            w.align().variant(self.align.into())
432        });
433        while self.rb.cr2().read().swstart().bit_is_set() {}
434        // ADC wait for conversion results
435        while self.rb.sr().read().eoc().bit_is_clear() {}
436
437        let res = self.rb.dr().read().data().bits();
438        res
439    }
440
441    /// Powers down the ADC, disables the ADC clock and releases the ADC Peripheral
442    pub fn release(mut self, rcc: &mut RCC) -> ADC {
443        self.power_down();
444        self.disable_clock(rcc);
445        self.rb
446    }
447
448    /// Enable interrupt for EOC (end of convert)
449    pub fn enable_eoc_interrupt(&mut self) {
450        self.rb.cr1().write(|w| w.eocie().set_bit());
451    }
452
453    /// Disable interrupt for EOC (end of convert)
454    pub fn disable_eoc_interrupt(&mut self) {
455        self.rb.cr1().write(|w| w.eocie().clear_bit());
456    }
457
458    /// Enable interrupt for JEOC (EOC for injected channels)
459    pub fn enable_jeoc_interrupt(&mut self) {
460        self.rb.cr1().write(|w| w.jeocie().set_bit());
461    }
462
463    /// Disable interrupt for JEOC (EOC for injected channels)
464    pub fn disable_jeoc_interrupt(&mut self) {
465        self.rb.cr1().write(|w| w.jeocie().clear_bit());
466    }
467}
468
469impl<ADC: Instance> ChannelTimeSequence for Adc<ADC> {
470    #[inline(always)]
471    fn set_channel_sample_time(&mut self, chan: u8, sample_time: SampleTime) {
472        self.set_channel_sample_time(chan, sample_time);
473    }
474    #[inline(always)]
475    fn set_regular_sequence(&mut self, channels: &[u8]) {
476        self.set_regular_sequence(channels);
477    }
478    #[inline(always)]
479    fn set_continuous_mode(&mut self, continuous: bool) {
480        self.set_continuous_mode(continuous);
481    }
482    #[inline(always)]
483    fn set_discontinuous_mode(&mut self, channels: Option<u8>) {
484        self.set_discontinuous_mode(channels);
485    }
486}
487
488impl<ADC: Instance, WORD, PIN> OneShot<ADC, WORD, PIN> for Adc<ADC>
489where
490    WORD: From<u16>,
491    PIN: Channel<ADC, ID = u8>,
492{
493    type Error = ();
494
495    fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
496        let res = self.convert(PIN::channel());
497        Ok(res.into())
498    }
499}
500
501impl Adc<pac::ADC1> {
502    fn read_aux(&mut self, chan: u8) -> u16 {
503        let tsv_enabled = matches!(chan, TEMP_CHANNEL | VREF_CHANNEL) && self.enable_temp_vref();
504
505        let val = self.convert(chan);
506
507        if tsv_enabled {
508            self.disable_temp_vref();
509        }
510
511        val
512    }
513
514    /// Enables the temperature / VREF sensor.
515    ///
516    /// Enabling this before calling `read_temp` or `read_vref` will speed up the reading
517    /// since you won't have to wait for the sensor to start up.
518    ///
519    /// Returns true if the sensor was previously off.
520    pub fn enable_temp_vref(&mut self) -> bool {
521        if !self.is_temp_vref_enabled() {
522            self.rb.cr2().modify(|_, w| w.tsvrefe().set_bit());
523
524            // The reference manual says that a stabilization time is needed after the powering the
525            // sensor, this time can be found in the datasheets.
526            // Here we are delaying for approximately 10us, considering 1.25 instructions per
527            // cycle. Do we support a chip which needs more than 10us ?
528            delay(self.sysclk.raw() / 80_000);
529            true
530        } else {
531            false
532        }
533    }
534
535    /// Disables the temperature / VREF sensor.
536    ///
537    /// `read_temp` and `read_vref` will still work with this disabled, but will take a
538    /// bit longer since you have to wait for the sensor to start up.
539    pub fn disable_temp_vref(&mut self) {
540        self.rb.cr2().modify(|_, w| w.tsvrefe().clear_bit());
541    }
542
543    pub fn is_temp_vref_enabled(&self) -> bool {
544        self.rb.cr2().read().tsvrefe().bit_is_set()
545    }
546
547    /// Temperature sensor is connected to channel 16 on ADC1. This sensor can be used
548    /// to measure ambient temperature of the device. However note that the returned
549    /// value is not an absolute temperature value.
550    ///
551    /// In particular, according to section 11.10 from Reference Manual RM0008 Rev 20:
552    /// "The temperature sensor output voltage changes linearly with temperature. The offset
553    /// of this line varies from chip to chip due to process variation (up to 45 °C from one
554    /// chip to another). The internal temperature sensor is more suited to applications
555    /// that detect temperature variations instead of absolute temperatures. If accurate
556    /// temperature readings are needed, an external temperature sensor part should be used."
557    ///
558    /// Formula to calculate temperature value is also taken from the section 11.10.
559    ///
560    /// If the temp/VREF sensor is disabled, this will still work but must wait
561    /// for the sensor to start up. Call `enable_temp_vref` to speed this up.
562    pub fn read_temp(&mut self) -> i32 {
563        /// According to section 5.3.18 "Temperature sensor characteristics"
564        /// from STM32F1xx datasheets, TS constants values are as follows:
565        ///   AVG_SLOPE - average slope
566        ///   V_25 - temperature sensor ADC voltage at 25°C
567        const AVG_SLOPE: i32 = 43;
568        const V_25: i32 = 1430;
569
570        let prev_cfg = self.save_cfg();
571
572        // recommended ADC sampling for temperature sensor is 17.1 usec,
573        // so use the following approximate settings
574        // to support all ADC frequencies
575        let sample_time = match self.adcclk.raw() {
576            0..=1_200_000 => SampleTime::T_1,
577            1_200_001..=1_500_000 => SampleTime::T_7,
578            1_500_001..=2_400_000 => SampleTime::T_13,
579            2_400_001..=3_100_000 => SampleTime::T_28,
580            3_100_001..=4_000_000 => SampleTime::T_41,
581            4_000_001..=5_000_000 => SampleTime::T_55,
582            5_000_001..=14_000_000 => SampleTime::T_71,
583            _ => SampleTime::T_239,
584        };
585
586        self.set_sample_time(sample_time);
587        let val_temp: i32 = self.read_aux(TEMP_CHANNEL).into();
588        let val_vref: i32 = self.read_aux(VREF_CHANNEL).into();
589        let v_sense = val_temp * 1200 / val_vref;
590
591        self.restore_cfg(prev_cfg);
592
593        (V_25 - v_sense) * 10 / AVG_SLOPE + 25
594    }
595
596    /// Internal reference voltage Vrefint is connected to channel 17 on ADC1.
597    /// According to section 5.3.4 "Embedded reference voltage" from STM32F1xx
598    /// datasheets, typical value of this reference voltage is 1200 mV.
599    ///
600    /// This value is useful when ADC readings need to be converted into voltages.
601    /// For instance, reading from any ADC channel can be converted into voltage (mV)
602    /// using the following formula:
603    ///     v_chan = adc.read(chan) * 1200 / adc.read_vref()
604    ///
605    /// If the temp/VREF sensor is disabled, this will still work but must wait
606    /// for the sensor to start up. Call `enable_temp_vref` to speed this up.
607    pub fn read_vref(&mut self) -> u16 {
608        self.read_aux(VREF_CHANNEL)
609    }
610}
611
612pub struct AdcPayload<ADC, PINS, MODE> {
613    adc: Adc<ADC>,
614    pins: PINS,
615    _mode: PhantomData<MODE>,
616}
617
618pub trait ChannelTimeSequence {
619    /// Set ADC sampling time for particular channel
620    fn set_channel_sample_time(&mut self, chan: u8, sample_time: SampleTime);
621    /// ADC Set a Regular Channel Conversion Sequence
622    ///
623    /// Define a sequence of channels to be converted as a regular group.
624    fn set_regular_sequence(&mut self, channels: &[u8]);
625    /// Set ADC continuous conversion
626    ///
627    /// When continuous conversion is enabled conversion does not stop at the last selected group channel but continues again from the first selected group channel.
628    fn set_continuous_mode(&mut self, continuous: bool);
629    /// Set ADC discontinuous mode
630    ///
631    /// It can be used to convert a short sequence of conversions (up to 8) which is a part of the regular sequence of conversions.
632    fn set_discontinuous_mode(&mut self, channels_count: Option<u8>);
633}
634
635/// Set channel sequence and sample times for custom pins
636///
637/// Example:
638/// ```rust, ignore
639/// pub struct AdcPins(PA0<Analog>, PA2<Analog>);
640/// impl SetChannels<AdcPins> for Adc<ADC1> {
641///     fn set_samples(&mut self) {
642///         self.set_channel_sample_time(0, adc::SampleTime::T_28);
643///         self.set_channel_sample_time(2, adc::SampleTime::T_28);
644///     }
645///     fn set_sequence(&mut self) {
646///         self.set_regular_sequence(&[0, 2, 0, 2]);
647///         // Optionally we can set continuous scan mode
648///         self.set_continuous_mode(true);
649///         // Also we can use discontinuous conversion (3 channels per conversion)
650///         self.set_discontinuous_mode(Some(3));
651///     }
652/// }
653/// ```
654pub trait SetChannels<PINS>: ChannelTimeSequence {
655    fn set_samples(&mut self);
656    fn set_sequence(&mut self);
657}
658
659pub type AdcDma<ADC, PINS, MODE, CHANNEL> = RxDma<AdcPayload<ADC, PINS, MODE>, CHANNEL>;
660
661macro_rules! adcdma {
662    ($ADCX:ty: (
663        $rxdma:ident,
664        $dmarxch:ty,
665    )) => {
666        pub type $rxdma<PINS, MODE> = AdcDma<$ADCX, PINS, MODE, $dmarxch>;
667
668        impl<PINS, MODE> Receive for AdcDma<$ADCX, PINS, MODE, $dmarxch> {
669            type RxChannel = $dmarxch;
670            type TransmittedWord = u16;
671        }
672
673        impl<PINS> TransferPayload for AdcDma<$ADCX, PINS, Continuous, $dmarxch> {
674            fn start(&mut self) {
675                self.channel.start();
676                self.payload.adc.rb.cr2().modify(|_, w| w.cont().set_bit());
677                self.payload.adc.rb.cr2().modify(|_, w| w.adon().set_bit());
678            }
679            fn stop(&mut self) {
680                self.channel.stop();
681                self.payload
682                    .adc
683                    .rb
684                    .cr2()
685                    .modify(|_, w| w.cont().clear_bit());
686            }
687        }
688
689        impl<PINS> TransferPayload for AdcDma<$ADCX, PINS, Scan, $dmarxch> {
690            fn start(&mut self) {
691                self.channel.start();
692                self.payload.adc.rb.cr2().modify(|_, w| w.adon().set_bit());
693            }
694            fn stop(&mut self) {
695                self.channel.stop();
696            }
697        }
698
699        impl Adc<$ADCX> {
700            pub fn with_dma<PIN>(
701                mut self,
702                pins: PIN,
703                dma_ch: $dmarxch,
704            ) -> AdcDma<$ADCX, PIN, Continuous, $dmarxch>
705            where
706                PIN: Channel<$ADCX, ID = u8>,
707            {
708                self.rb.cr1().modify(|_, w| w.discen().clear_bit());
709                self.rb
710                    .cr2()
711                    .modify(|_, w| w.align().variant(self.align.into()));
712                self.set_channel_sample_time(PIN::channel(), self.sample_time);
713                self.rb
714                    .sqr3()
715                    .modify(|_, w| unsafe { w.sq1().bits(PIN::channel()) });
716                self.rb.cr2().modify(|_, w| w.dma().set_bit());
717
718                let payload = AdcPayload {
719                    adc: self,
720                    pins,
721                    _mode: PhantomData,
722                };
723                RxDma {
724                    payload,
725                    channel: dma_ch,
726                }
727            }
728
729            pub fn with_scan_dma<PINS>(
730                mut self,
731                pins: PINS,
732                dma_ch: $dmarxch,
733            ) -> AdcDma<$ADCX, PINS, Scan, $dmarxch>
734            where
735                Self: SetChannels<PINS>,
736            {
737                self.rb.cr2().modify(|_, w| {
738                    w.adon().clear_bit();
739                    w.dma().clear_bit();
740                    w.cont().clear_bit();
741                    w.align().variant(self.align.into())
742                });
743                self.rb
744                    .cr1()
745                    .modify(|_, w| w.scan().set_bit().discen().clear_bit());
746                self.set_samples();
747                self.set_sequence();
748                self.rb
749                    .cr2()
750                    .modify(|_, w| w.dma().set_bit().adon().set_bit());
751
752                let payload = AdcPayload {
753                    adc: self,
754                    pins,
755                    _mode: PhantomData,
756                };
757                RxDma {
758                    payload,
759                    channel: dma_ch,
760                }
761            }
762        }
763
764        impl<PINS> AdcDma<$ADCX, PINS, Continuous, $dmarxch>
765        where
766            Self: TransferPayload,
767        {
768            pub fn split(mut self) -> (Adc<$ADCX>, PINS, $dmarxch) {
769                self.stop();
770
771                let AdcDma { payload, channel } = self;
772                payload.adc.rb.cr2().modify(|_, w| w.dma().clear_bit());
773                payload.adc.rb.cr1().modify(|_, w| w.discen().set_bit());
774
775                (payload.adc, payload.pins, channel)
776            }
777        }
778
779        impl<PINS> AdcDma<$ADCX, PINS, Scan, $dmarxch>
780        where
781            Self: TransferPayload,
782        {
783            pub fn split(mut self) -> (Adc<$ADCX>, PINS, $dmarxch) {
784                self.stop();
785
786                let AdcDma { payload, channel } = self;
787                payload.adc.rb.cr2().modify(|_, w| w.dma().clear_bit());
788                payload.adc.rb.cr1().modify(|_, w| w.discen().set_bit());
789                payload.adc.rb.cr1().modify(|_, w| w.scan().clear_bit());
790
791                (payload.adc, payload.pins, channel)
792            }
793        }
794
795        impl<B, PINS, MODE> crate::dma::CircReadDma<B, u16> for AdcDma<$ADCX, PINS, MODE, $dmarxch>
796        where
797            Self: TransferPayload,
798            &'static mut [B; 2]: WriteBuffer<Word = u16>,
799            B: 'static,
800        {
801            fn circ_read(mut self, mut buffer: &'static mut [B; 2]) -> CircBuffer<B, Self> {
802                // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
803                // until the end of the transfer.
804                let (ptr, len) = unsafe { buffer.write_buffer() };
805                self.channel.set_peripheral_address(
806                    unsafe { (*<$ADCX>::ptr()).dr().as_ptr() as u32 },
807                    false,
808                );
809                self.channel.set_memory_address(ptr as u32, true);
810                self.channel.set_transfer_length(len);
811
812                atomic::compiler_fence(Ordering::Release);
813
814                self.channel.ch().cr().modify(|_, w| {
815                    w.mem2mem().clear_bit();
816                    w.pl().medium();
817                    w.msize().bits16();
818                    w.psize().bits16();
819                    w.circ().set_bit();
820                    w.dir().clear_bit()
821                });
822
823                self.start();
824
825                CircBuffer::new(buffer, self)
826            }
827        }
828
829        impl<B, PINS, MODE> crate::dma::ReadDma<B, u16> for AdcDma<$ADCX, PINS, MODE, $dmarxch>
830        where
831            Self: TransferPayload,
832            B: WriteBuffer<Word = u16>,
833        {
834            fn read(mut self, mut buffer: B) -> Transfer<W, B, Self> {
835                // NOTE(unsafe) We own the buffer now and we won't call other `&mut` on it
836                // until the end of the transfer.
837                let (ptr, len) = unsafe { buffer.write_buffer() };
838                self.channel.set_peripheral_address(
839                    unsafe { (*<$ADCX>::ptr()).dr().as_ptr() as u32 },
840                    false,
841                );
842                self.channel.set_memory_address(ptr as u32, true);
843                self.channel.set_transfer_length(len);
844
845                atomic::compiler_fence(Ordering::Release);
846                self.channel.ch().cr().modify(|_, w| {
847                    w.mem2mem().clear_bit();
848                    w.pl().medium();
849                    w.msize().bits16();
850                    w.psize().bits16();
851                    w.circ().clear_bit();
852                    w.dir().clear_bit()
853                });
854                self.start();
855
856                Transfer::w(buffer, self)
857            }
858        }
859    };
860}
861
862adcdma! {
863    pac::ADC1: (
864        AdcDma1,
865        dma1::C1,
866    )
867}
868
869#[cfg(all(feature = "stm32f103", any(feature = "high", feature = "xl")))]
870adcdma! {
871    pac::ADC3: (
872        AdcDma3,
873        dma2::C5,
874    )
875}