From 12b59dc610fb659a4d51ccc364865a7e154379d6 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 10 Nov 2025 09:56:42 -0600 Subject: adc: remove sample_time from struct --- embassy-stm32/src/adc/adc4.rs | 18 ++++---------- embassy-stm32/src/adc/c0.rs | 15 ++++-------- embassy-stm32/src/adc/f1.rs | 13 +++------- embassy-stm32/src/adc/f3.rs | 13 +++------- embassy-stm32/src/adc/f3_v1_1.rs | 5 ++-- embassy-stm32/src/adc/g4.rs | 22 +++++------------ embassy-stm32/src/adc/mod.rs | 2 -- embassy-stm32/src/adc/v1.rs | 13 +++------- embassy-stm32/src/adc/v2.rs | 17 ++++--------- embassy-stm32/src/adc/v3.rs | 36 ++++++++-------------------- embassy-stm32/src/adc/v4.rs | 23 ++++-------------- embassy-stm32/src/adc/watchdog_v1.rs | 6 ++--- examples/stm32c0/src/bin/adc.rs | 8 +++---- examples/stm32f0/src/bin/adc-watchdog.rs | 6 ++--- examples/stm32f0/src/bin/adc.rs | 5 ++-- examples/stm32f1/src/bin/adc.rs | 6 ++--- examples/stm32f334/src/bin/adc.rs | 8 +++---- examples/stm32f334/src/bin/opamp.rs | 8 +++---- examples/stm32f4/src/bin/adc.rs | 10 ++++---- examples/stm32f4/src/bin/adc_dma.rs | 8 +++---- examples/stm32f7/src/bin/adc.rs | 6 ++--- examples/stm32g0/src/bin/adc.rs | 5 ++-- examples/stm32g0/src/bin/adc_oversampling.rs | 3 +-- examples/stm32g4/src/bin/adc.rs | 3 +-- examples/stm32g4/src/bin/adc_differential.rs | 3 +-- examples/stm32g4/src/bin/adc_oversampling.rs | 3 +-- examples/stm32h5/src/bin/adc.rs | 6 ++--- examples/stm32h7/src/bin/adc.rs | 6 ++--- examples/stm32l0/src/bin/adc.rs | 5 ++-- examples/stm32l4/src/bin/adc.rs | 4 ++-- examples/stm32l4/src/bin/adc_dma.rs | 10 +++----- examples/stm32u0/src/bin/adc.rs | 4 ++-- examples/stm32u5/src/bin/adc.rs | 18 ++++++-------- examples/stm32wba/src/bin/adc.rs | 6 ++--- examples/stm32wba6/src/bin/adc.rs | 5 ++-- examples/stm32wl/src/bin/adc.rs | 6 ++--- examples/stm32wle5/src/bin/adc.rs | 5 ++-- tests/stm32/src/bin/dac.rs | 9 ++++--- tests/stm32/src/bin/dac_l1.rs | 11 ++++++--- 39 files changed, 131 insertions(+), 229 deletions(-) diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs index 2608160a3..befa8ed4a 100644 --- a/embassy-stm32/src/adc/adc4.rs +++ b/embassy-stm32/src/adc/adc4.rs @@ -327,18 +327,6 @@ impl<'d, T: Instance> Adc4<'d, T> { Dac {} } - /// Set the ADC sample time. - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - T::regs().smpr().modify(|w| { - w.set_smp(0, sample_time); - }); - } - - /// Get the ADC sample time. - pub fn sample_time(&self) -> SampleTime { - T::regs().smpr().read().smp(0) - } - /// Set the ADC resolution. pub fn set_resolution(&mut self, resolution: Resolution) { T::regs().cfgr1().modify(|w| w.set_res(resolution.into())); @@ -387,7 +375,11 @@ impl<'d, T: Instance> Adc4<'d, T> { } /// Read an ADC channel. - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + T::regs().smpr().modify(|w| { + w.set_smp(0, sample_time); + }); + channel.setup(); // Select channel diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs index fc28df346..70302ef96 100644 --- a/embassy-stm32/src/adc/c0.rs +++ b/embassy-stm32/src/adc/c0.rs @@ -156,7 +156,7 @@ pub enum Averaging { impl<'d, T: Instance> Adc<'d, T> { /// Create a new ADC driver. - pub fn new(adc: Peri<'d, T>, sample_time: SampleTime, resolution: Resolution) -> Self { + pub fn new(adc: Peri<'d, T>, resolution: Resolution) -> Self { rcc::enable_and_reset::(); T::regs().cfgr2().modify(|w| w.set_ckmode(Ckmode::SYSCLK)); @@ -174,10 +174,7 @@ impl<'d, T: Instance> Adc<'d, T> { ); } - let mut s = Self { - adc, - sample_time: SampleTime::from_bits(0), - }; + let mut s = Self { adc }; s.power_up(); @@ -189,8 +186,6 @@ impl<'d, T: Instance> Adc<'d, T> { s.configure_default(); - s.set_sample_time_all_channels(sample_time); - s } @@ -258,8 +253,6 @@ impl<'d, T: Instance> Adc<'d, T> { /// Set the ADC sample time. /// Shall only be called when ADC is not converting. pub fn set_sample_time_all_channels(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - // Set all channels to use SMP1 field as source. T::regs().smpr().modify(|w| { w.smpsel(0); @@ -288,7 +281,9 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().dr().read().data() as u16 } - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + self.set_sample_time_all_channels(sample_time); + Self::configure_channel(channel); T::regs().cfgr1().write(|reg| { reg.set_chselrmod(false); diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index f9c23d72b..32e330d76 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs @@ -71,10 +71,7 @@ impl<'d, T: Instance> Adc<'d, T> { T::Interrupt::unpend(); unsafe { T::Interrupt::enable() }; - Self { - adc, - sample_time: SampleTime::from_bits(0), - } + Self { adc } } fn freq() -> Hertz { @@ -108,10 +105,6 @@ impl<'d, T: Instance> Adc<'d, T> { Temperature {} } - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - } - /// Perform a single conversion. async fn convert(&mut self) -> u16 { T::regs().cr2().modify(|reg| { @@ -134,8 +127,8 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().dr().read().0 as u16 } - pub async fn read(&mut self, channel: &mut impl AdcChannel) -> u16 { - Self::set_channel_sample_time(channel.channel(), self.sample_time); + pub async fn read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + Self::set_channel_sample_time(channel.channel(), sample_time); T::regs().cr1().modify(|reg| { reg.set_scan(false); reg.set_discen(false); diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs index 73ceb087a..cf31aa81b 100644 --- a/embassy-stm32/src/adc/f3.rs +++ b/embassy-stm32/src/adc/f3.rs @@ -90,10 +90,7 @@ impl<'d, T: Instance> Adc<'d, T> { T::Interrupt::enable(); } - Self { - adc, - sample_time: SampleTime::from_bits(0), - } + Self { adc } } fn freq() -> Hertz { @@ -124,10 +121,6 @@ impl<'d, T: Instance> Adc<'d, T> { Temperature {} } - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - } - /// Perform a single conversion. async fn convert(&mut self) -> u16 { T::regs().isr().write(|_| {}); @@ -150,8 +143,8 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().dr().read().rdata() } - pub async fn read(&mut self, channel: &mut impl AdcChannel) -> u16 { - Self::set_channel_sample_time(channel.channel(), self.sample_time); + pub async fn read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + Self::set_channel_sample_time(channel.channel(), sample_time); // Configure the channel to sample T::regs().sqr1().write(|w| w.set_sq(0, channel.channel())); diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs index cd5de54f5..919ac3cc0 100644 --- a/embassy-stm32/src/adc/f3_v1_1.rs +++ b/embassy-stm32/src/adc/f3_v1_1.rs @@ -79,7 +79,7 @@ impl Vref { } pub async fn calibrate(&mut self, adc: &mut Adc<'_, T>) -> Calibration { - let vref_val = adc.read(self).await; + let vref_val = adc.read(self, SampleTime::from(0)).await; Calibration { vref_cal: self.calibrated_value(), vref_val, @@ -270,7 +270,8 @@ impl<'d, T: Instance> Adc<'d, T> { } } - pub async fn read(&mut self, channel: &mut impl AdcChannel) -> u16 { + pub async fn read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + self.set_sample_time(channel, sample_time).await; self.set_sample_sequence(&[channel.channel()]).await; self.convert().await } diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 3767820cf..5066aeec0 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -168,10 +168,7 @@ impl<'d, T: Instance> Adc<'d, T> { ); } - let mut s = Self { - adc, - sample_time: SampleTime::from_bits(0), - }; + let mut s = Self { adc }; s.power_up(); s.configure_differential_inputs(); @@ -297,7 +294,7 @@ impl<'d, T: Instance> Adc<'d, T> { /// channel on the other ADC unusable. The only exception is when ADC master and the slave /// operate in interleaved mode. #[cfg(stm32g4)] - pub fn set_differential_channel(&mut self, ch: usize, enable: bool) { + fn set_differential_channel(&mut self, ch: usize, enable: bool) { T::regs().cr().modify(|w| w.set_aden(false)); // disable adc T::regs().difsel().modify(|w| { w.set_difsel( @@ -350,11 +347,6 @@ impl<'d, T: Instance> Adc<'d, T> { // T::regs().cfgr2().modify(|reg| reg.set_jovse(enable)); // } - /// Set the ADC sample time. - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - } - /// Set the ADC resolution. pub fn set_resolution(&mut self, resolution: Resolution) { T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); @@ -380,10 +372,10 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Read an ADC pin. - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { channel.setup(); - self.read_channel(channel) + self.read_channel(channel, sample_time) } /// Start regular adc conversion @@ -755,12 +747,10 @@ impl<'d, T: Instance> Adc<'d, T> { ( Self { adc: self.adc.clone_unchecked(), - sample_time: self.sample_time, } .into_ring_buffered(dma, dma_buf, regular_sequence, regular_conversion_mode), Self { adc: self.adc.clone_unchecked(), - sample_time: self.sample_time, } .setup_injected_conversions(injected_sequence, injected_trigger, injected_interrupt), ) @@ -805,8 +795,8 @@ impl<'d, T: Instance> Adc<'d, T> { Self::set_channel_sample_time(channel.channel(), sample_time); } - fn read_channel(&mut self, channel: &mut impl AdcChannel) -> u16 { - Self::configure_channel(channel, self.sample_time); + fn read_channel(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + Self::configure_channel(channel, sample_time); #[cfg(stm32h7)] { T::regs().cfgr2().modify(|w| w.set_lshift(0)); diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index ea7341f75..a6b796fb9 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -47,8 +47,6 @@ dma_trait!(RxDma4, adc4::Instance); pub struct Adc<'d, T: Instance> { #[allow(unused)] adc: crate::Peri<'d, T>, - #[cfg(not(any(adc_f3v3, adc_f3v2, adc_wba)))] - sample_time: SampleTime, } #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index a5869d110..3838cc12a 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -114,10 +114,7 @@ impl<'d, T: Instance> Adc<'d, T> { T::Interrupt::enable(); } - Self { - adc, - sample_time: SampleTime::from_bits(0), - } + Self { adc } } #[cfg(not(adc_l0))] @@ -149,10 +146,6 @@ impl<'d, T: Instance> Adc<'d, T> { Temperature } - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - } - pub fn set_resolution(&mut self, resolution: Resolution) { T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); } @@ -163,12 +156,13 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode)); } - pub async fn read(&mut self, channel: &mut impl AdcChannel) -> u16 { + pub async fn read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { let ch_num = channel.channel(); channel.setup(); // A.7.5 Single conversion sequence code example - Software trigger T::regs().chselr().write(|reg| reg.set_chsel_x(ch_num as usize, true)); + T::regs().smpr().modify(|reg| reg.set_smp(sample_time.into())); self.convert().await } @@ -179,7 +173,6 @@ impl<'d, T: Instance> Adc<'d, T> { reg.set_eosmp(true); }); - T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into())); T::regs().ier().modify(|w| w.set_eocie(true)); T::regs().cr().modify(|reg| reg.set_adstart(true)); diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 90c6294d2..67721770a 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -117,10 +117,7 @@ where blocking_delay_us(3); - Self { - adc, - sample_time: SampleTime::from_bits(0), - } + Self { adc } } /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. @@ -137,7 +134,7 @@ where self, dma: Peri<'d, impl RxDma>, dma_buf: &'d mut [u16], - sequence: impl ExactSizeIterator, SampleTime)>, + sequence: impl ExactSizeIterator, SampleTime)>, ) -> RingBufferedAdc<'d, T> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); @@ -150,7 +147,7 @@ where r.set_l((sequence.len() - 1).try_into().unwrap()); }); - for (i, (channel, sample_time)) in sequence.enumerate() { + for (i, (mut channel, sample_time)) in sequence.enumerate() { // Set this GPIO as an analog input. channel.setup(); @@ -215,10 +212,6 @@ where }); } - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - } - pub fn set_resolution(&mut self, resolution: Resolution) { T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); } @@ -278,7 +271,7 @@ where T::regs().dr().read().0 as u16 } - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { channel.setup(); // Configure ADC @@ -288,7 +281,7 @@ where T::regs().sqr3().write(|reg| reg.set_sq(0, channel)); // Configure channel - Self::set_channel_sample_time(channel, self.sample_time); + Self::set_channel_sample_time(channel, sample_time); self.convert() } diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 170b08a25..bbbaf73c8 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -218,10 +218,7 @@ impl<'d, T: Instance> Adc<'d, T> { pub fn new(adc: Peri<'d, T>) -> Self { Self::init_regulator(); Self::init_calibrate(); - Self { - adc, - sample_time: SampleTime::from_bits(0), - } + Self { adc } } #[cfg(adc_g0)] @@ -257,10 +254,7 @@ impl<'d, T: Instance> Adc<'d, T> { Self::init_calibrate(); - Self { - adc, - sample_time: SampleTime::from_bits(0), - } + Self { adc } } // Enable ADC only when it is not already running. @@ -342,16 +336,6 @@ impl<'d, T: Instance> Adc<'d, T> { Vbat {} } - /// Set the ADC sample time. - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - } - - /// Get the ADC sample time. - pub fn sample_time(&self) -> SampleTime { - self.sample_time - } - /// Set the ADC resolution. pub fn set_resolution(&mut self, resolution: Resolution) { #[cfg(not(any(adc_g0, adc_u0)))] @@ -413,8 +397,8 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Read an ADC channel. - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { - self.read_channel(channel) + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + self.read_channel(channel, sample_time) } /// Read one or multiple ADC channels using DMA. @@ -616,7 +600,7 @@ impl<'d, T: Instance> Adc<'d, T> { &mut self, dma: Peri<'a, impl RxDma>, dma_buf: &'a mut [u16], - sequence: impl ExactSizeIterator, SampleTime)>, + sequence: impl ExactSizeIterator, SampleTime)>, ) -> RingBufferedAdc<'a, T> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); @@ -665,8 +649,8 @@ impl<'d, T: Instance> Adc<'d, T> { let mut channel_mask = 0; // Configure channels and ranks - for (_i, (channel, sample_time)) in sequence.enumerate() { - Self::configure_channel(channel, sample_time); + for (_i, (mut channel, sample_time)) in sequence.enumerate() { + Self::configure_channel(&mut channel, sample_time); // Each channel is sampled according to sequence #[cfg(not(any(adc_g0, adc_u0)))] @@ -745,13 +729,13 @@ impl<'d, T: Instance> Adc<'d, T> { Self::set_channel_sample_time(channel.channel(), sample_time); } - fn read_channel(&mut self, channel: &mut impl AdcChannel) -> u16 { + fn read_channel(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { self.enable(); #[cfg(not(adc_g0))] - Self::configure_channel(channel, self.sample_time); + Self::configure_channel(channel, sample_time); #[cfg(adc_g0)] T::regs().smpr().write(|reg| { - reg.set_sample_time(0, self.sample_time); + reg.set_sample_time(0, sample_time); reg.set_smpsel(channel.channel().into(), Smpsel::SMP1); }); // Select channel diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index c7d0103a6..cc3f8b34e 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -190,10 +190,7 @@ impl<'d, T: Instance> Adc<'d, T> { }; T::regs().cr().modify(|w| w.set_boost(boost)); } - let mut s = Self { - adc, - sample_time: SampleTime::from_bits(0), - }; + let mut s = Self { adc }; s.power_up(); s.configure_differential_inputs(); @@ -277,16 +274,6 @@ impl<'d, T: Instance> Adc<'d, T> { Vbat {} } - /// Set the ADC sample time. - pub fn set_sample_time(&mut self, sample_time: SampleTime) { - self.sample_time = sample_time; - } - - /// Get the ADC sample time. - pub fn sample_time(&self) -> SampleTime { - self.sample_time - } - /// Set the ADC resolution. pub fn set_resolution(&mut self, resolution: Resolution) { T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); @@ -335,8 +322,8 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Read an ADC channel. - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel) -> u16 { - self.read_channel(channel) + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + self.read_channel(channel, sample_time) } /// Read one or multiple ADC channels using DMA. @@ -472,8 +459,8 @@ impl<'d, T: Instance> Adc<'d, T> { } } - fn read_channel(&mut self, channel: &mut impl AdcChannel) -> u16 { - Self::configure_channel(channel, self.sample_time); + fn read_channel(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + Self::configure_channel(channel, sample_time); T::regs().sqr1().modify(|reg| { reg.set_sq(0, channel.channel()); diff --git a/embassy-stm32/src/adc/watchdog_v1.rs b/embassy-stm32/src/adc/watchdog_v1.rs index bbe8e1971..b12e0d333 100644 --- a/embassy-stm32/src/adc/watchdog_v1.rs +++ b/embassy-stm32/src/adc/watchdog_v1.rs @@ -1,7 +1,7 @@ use core::future::poll_fn; use core::task::Poll; -use stm32_metapac::adc::vals::{Align, Awdsgl, Res}; +use stm32_metapac::adc::vals::{Align, Awdsgl, Res, SampleTime}; use crate::adc::{Adc, AdcChannel, Instance}; @@ -67,7 +67,7 @@ impl<'d, T: Instance> Adc<'d, T> { /// let v_high = adc.monitor_watchdog().await; /// info!("ADC sample is high {}", v_high); /// ``` - pub async fn monitor_watchdog(&mut self) -> u16 { + pub async fn monitor_watchdog(&mut self, sample_time: SampleTime) -> u16 { assert!( match T::regs().cfgr1().read().awdsgl() { Awdsgl::SINGLE_CHANNEL => T::regs().cfgr1().read().awdch() != 0, @@ -76,7 +76,7 @@ impl<'d, T: Instance> Adc<'d, T> { "`set_channel` should be called before `monitor`", ); assert!(T::regs().chselr().read().0 != 0); - T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into())); + T::regs().smpr().modify(|reg| reg.set_smp(sample_time.into())); Self::start_awd(); let sample = poll_fn(|cx| { diff --git a/examples/stm32c0/src/bin/adc.rs b/examples/stm32c0/src/bin/adc.rs index 1f54b0b18..b52c9e7f8 100644 --- a/examples/stm32c0/src/bin/adc.rs +++ b/examples/stm32c0/src/bin/adc.rs @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { info!("ADC STM32C0 example."); // We need to set certain sample time to be able to read temp sensor. - let mut adc = Adc::new(p.ADC1, SampleTime::CYCLES12_5, Resolution::BITS12); + let mut adc = Adc::new(p.ADC1, Resolution::BITS12); let mut temp = adc.enable_temperature().degrade_adc(); let mut vref = adc.enable_vrefint().degrade_adc(); let mut pin0 = p.PA0.degrade_adc(); @@ -27,9 +27,9 @@ async fn main(_spawner: Spawner) { loop { info!("============================"); - let blocking_temp = adc.blocking_read(&mut temp); - let blocking_vref = adc.blocking_read(&mut vref); - let blocing_pin0 = adc.blocking_read(&mut pin0); + let blocking_temp = adc.blocking_read(&mut temp, SampleTime::CYCLES12_5); + let blocking_vref = adc.blocking_read(&mut vref, SampleTime::CYCLES12_5); + let blocing_pin0 = adc.blocking_read(&mut pin0, SampleTime::CYCLES12_5); info!( "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", blocking_vref, blocking_temp, blocing_pin0 diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs index ff98aac8e..6879dd10a 100644 --- a/examples/stm32f0/src/bin/adc-watchdog.rs +++ b/examples/stm32f0/src/bin/adc-watchdog.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::adc::{self, Adc, WatchdogChannels}; +use embassy_stm32::adc::{self, Adc, SampleTime, WatchdogChannels}; use embassy_stm32::bind_interrupts; use embassy_stm32::peripherals::ADC1; use {defmt_rtt as _, panic_probe as _}; @@ -23,12 +23,12 @@ async fn main(_spawner: Spawner) { loop { // Wait for pin to go high adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); - let v_high = adc.monitor_watchdog().await; + let v_high = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; info!("ADC sample is high {}", v_high); // Wait for pin to go low adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); - let v_low = adc.monitor_watchdog().await; + let v_low = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; info!("ADC sample is low {}", v_low); } } diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs index 8825e2687..fafeeffaf 100644 --- a/examples/stm32f0/src/bin/adc.rs +++ b/examples/stm32f0/src/bin/adc.rs @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut adc = Adc::new(p.ADC1, Irqs); - adc.set_sample_time(SampleTime::CYCLES71_5); let mut pin = p.PA1; let mut vrefint = adc.enable_vref(); - let vrefint_sample = adc.read(&mut vrefint).await; + let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; let convert_to_millivolts = |sample| { // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf // 6.3.4 Embedded reference voltage @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { }; loop { - let v = adc.read(&mut pin).await; + let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; info!("--> {} - {} mV", v, convert_to_millivolts(v)); Timer::after_millis(100).await; } diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs index 541ff159e..2451aee3d 100644 --- a/examples/stm32f1/src/bin/adc.rs +++ b/examples/stm32f1/src/bin/adc.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::adc::Adc; +use embassy_stm32::adc::{Adc, SampleTime}; use embassy_stm32::peripherals::ADC1; use embassy_stm32::{adc, bind_interrupts}; use embassy_time::Timer; @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) { let mut pin = p.PB1; let mut vrefint = adc.enable_vref(); - let vrefint_sample = adc.read(&mut vrefint).await; + let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; let convert_to_millivolts = |sample| { // From http://www.st.com/resource/en/datasheet/CD00161566.pdf // 5.3.4 Embedded reference voltage @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { }; loop { - let v = adc.read(&mut pin).await; + let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; info!("--> {} - {} mV", v, convert_to_millivolts(v)); Timer::after_millis(100).await; } diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs index a993b00ca..a420c8876 100644 --- a/examples/stm32f334/src/bin/adc.rs +++ b/examples/stm32f334/src/bin/adc.rs @@ -40,21 +40,19 @@ async fn main(_spawner: Spawner) -> ! { let mut adc = Adc::new(p.ADC1, Irqs); - adc.set_sample_time(SampleTime::CYCLES601_5); - info!("enable vrefint..."); let mut vrefint = adc.enable_vref(); let mut temperature = adc.enable_temperature(); loop { - let vref = adc.read(&mut vrefint).await; + let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; info!("read vref: {} (should be {})", vref, vrefint.value()); - let temp = adc.read(&mut temperature).await; + let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; info!("read temperature: {}", temp); - let pin = adc.read(&mut p.PA0).await; + let pin = adc.read(&mut p.PA0, SampleTime::CYCLES601_5).await; info!("read pin: {}", pin); let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs index 3e621f2a1..ddefdd03d 100644 --- a/examples/stm32f334/src/bin/opamp.rs +++ b/examples/stm32f334/src/bin/opamp.rs @@ -42,8 +42,6 @@ async fn main(_spawner: Spawner) -> ! { let mut adc = Adc::new(p.ADC2, Irqs); let mut opamp = OpAmp::new(p.OPAMP2); - adc.set_sample_time(SampleTime::CYCLES601_5); - info!("enable vrefint..."); let mut vrefint = adc.enable_vref(); @@ -51,13 +49,13 @@ async fn main(_spawner: Spawner) -> ! { let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); loop { - let vref = adc.read(&mut vrefint).await; + let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; info!("read vref: {} (should be {})", vref, vrefint.value()); - let temp = adc.read(&mut temperature).await; + let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; info!("read temperature: {}", temp); - let buffer = adc.read(&mut buffer).await; + let buffer = adc.read(&mut buffer, SampleTime::CYCLES601_5).await; info!("read buffer: {}", buffer); let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs index 423d29225..5628cb827 100644 --- a/examples/stm32f4/src/bin/adc.rs +++ b/examples/stm32f4/src/bin/adc.rs @@ -4,7 +4,7 @@ use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::adc::{Adc, Temperature, VrefInt}; +use embassy_stm32::adc::{Adc, SampleTime, Temperature, VrefInt}; use embassy_time::{Delay, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { // Startup delay can be combined to the maximum of either delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); - let vrefint_sample = adc.blocking_read(&mut vrefint); + let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); let convert_to_millivolts = |sample| { // From http://www.st.com/resource/en/datasheet/DM00071990.pdf @@ -50,16 +50,16 @@ async fn main(_spawner: Spawner) { loop { // Read pin - let v = adc.blocking_read(&mut pin); + let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); // Read internal temperature - let v = adc.blocking_read(&mut temp); + let v = adc.blocking_read(&mut temp, SampleTime::CYCLES112); let celcius = convert_to_celcius(v); info!("Internal temp: {} ({} C)", v, celcius); // Read internal voltage reference - let v = adc.blocking_read(&mut vrefint); + let v = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); info!("VrefInt: {}", v); Timer::after_millis(100).await; diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs index f8da91336..01b881c79 100644 --- a/examples/stm32f4/src/bin/adc_dma.rs +++ b/examples/stm32f4/src/bin/adc_dma.rs @@ -27,8 +27,8 @@ async fn adc_task(p: Peripherals) { p.DMA2_CH0, adc_data, [ - (&mut p.PA0.degrade_adc(), SampleTime::CYCLES112), - (&mut p.PA2.degrade_adc(), SampleTime::CYCLES112), + (p.PA0.degrade_adc(), SampleTime::CYCLES112), + (p.PA2.degrade_adc(), SampleTime::CYCLES112), ] .into_iter(), ); @@ -36,8 +36,8 @@ async fn adc_task(p: Peripherals) { p.DMA2_CH2, adc_data2, [ - (&mut p.PA1.degrade_adc(), SampleTime::CYCLES112), - (&mut p.PA3.degrade_adc(), SampleTime::CYCLES112), + (p.PA1.degrade_adc(), SampleTime::CYCLES112), + (p.PA3.degrade_adc(), SampleTime::CYCLES112), ] .into_iter(), ); diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs index 6689e3b5d..0f226d34e 100644 --- a/examples/stm32f7/src/bin/adc.rs +++ b/examples/stm32f7/src/bin/adc.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::adc::Adc; +use embassy_stm32::adc::{Adc, SampleTime}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { let mut pin = p.PA3; let mut vrefint = adc.enable_vrefint(); - let vrefint_sample = adc.blocking_read(&mut vrefint); + let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); let convert_to_millivolts = |sample| { // From http://www.st.com/resource/en/datasheet/DM00273119.pdf // 6.3.27 Reference voltage @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) { }; loop { - let v = adc.blocking_read(&mut pin); + let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); info!("--> {} - {} mV", v, convert_to_millivolts(v)); Timer::after_millis(100).await; } diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs index 7d8653ef2..972e43b55 100644 --- a/examples/stm32g0/src/bin/adc.rs +++ b/examples/stm32g0/src/bin/adc.rs @@ -13,11 +13,10 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); - adc.set_sample_time(SampleTime::CYCLES79_5); let mut pin = p.PA1; let mut vrefint = adc.enable_vrefint(); - let vrefint_sample = adc.blocking_read(&mut vrefint); + let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); let convert_to_millivolts = |sample| { // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf // 6.3.3 Embedded internal reference voltage @@ -27,7 +26,7 @@ async fn main(_spawner: Spawner) { }; loop { - let v = adc.blocking_read(&mut pin); + let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); info!("--> {} - {} mV", v, convert_to_millivolts(v)); Timer::after_millis(100).await; } diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs index 834d1cd4a..f6979889d 100644 --- a/examples/stm32g0/src/bin/adc_oversampling.rs +++ b/examples/stm32g0/src/bin/adc_oversampling.rs @@ -17,7 +17,6 @@ async fn main(_spawner: Spawner) { info!("Adc oversample test"); let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); - adc.set_sample_time(SampleTime::CYCLES1_5); let mut pin = p.PA1; adc.set_oversampling_ratio(Ovsr::MUL16); @@ -25,7 +24,7 @@ async fn main(_spawner: Spawner) { adc.oversampling_enable(true); loop { - let v = adc.blocking_read(&mut pin); + let v = adc.blocking_read(&mut pin, SampleTime::CYCLES1_5); info!("--> {} ", v); //max 65520 = 0xFFF0 Timer::after_millis(100).await; } diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs index 920142a18..695f37115 100644 --- a/examples/stm32g4/src/bin/adc.rs +++ b/examples/stm32g4/src/bin/adc.rs @@ -29,10 +29,9 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut adc = Adc::new(p.ADC2); - adc.set_sample_time(SampleTime::CYCLES24_5); loop { - let measured = adc.blocking_read(&mut p.PA7); + let measured = adc.blocking_read(&mut p.PA7, SampleTime::CYCLES24_5); info!("measured: {}", measured); Timer::after_millis(500).await; } diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs index 301f0da84..a6e2f7d33 100644 --- a/examples/stm32g4/src/bin/adc_differential.rs +++ b/examples/stm32g4/src/bin/adc_differential.rs @@ -33,14 +33,13 @@ async fn main(_spawner: Spawner) { let mut p = embassy_stm32::init(config); let mut adc = Adc::new(p.ADC1); - adc.set_sample_time(SampleTime::CYCLES247_5); adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1 // can also use // adc.set_differential_channel(1, true); info!("adc initialized"); loop { - let measured = adc.blocking_read(&mut p.PA0); + let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES247_5); info!("data: {}", measured); Timer::after_millis(500).await; } diff --git a/examples/stm32g4/src/bin/adc_oversampling.rs b/examples/stm32g4/src/bin/adc_oversampling.rs index 1e464183a..cb99ab2a7 100644 --- a/examples/stm32g4/src/bin/adc_oversampling.rs +++ b/examples/stm32g4/src/bin/adc_oversampling.rs @@ -33,7 +33,6 @@ async fn main(_spawner: Spawner) { let mut p = embassy_stm32::init(config); let mut adc = Adc::new(p.ADC1); - adc.set_sample_time(SampleTime::CYCLES6_5); // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf // page652 Oversampler // Table 172. Maximum output results vs N and M. Grayed values indicates truncation @@ -50,7 +49,7 @@ async fn main(_spawner: Spawner) { adc.enable_regular_oversampling_mode(Rovsm::RESUMED, Trovs::AUTOMATIC, true); loop { - let measured = adc.blocking_read(&mut p.PA0); + let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES6_5); info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 Timer::after_millis(500).await; } diff --git a/examples/stm32h5/src/bin/adc.rs b/examples/stm32h5/src/bin/adc.rs index 0566320d4..c919b1a95 100644 --- a/examples/stm32h5/src/bin/adc.rs +++ b/examples/stm32h5/src/bin/adc.rs @@ -45,14 +45,12 @@ async fn main(_spawner: Spawner) { let mut adc = Adc::new(p.ADC1); - adc.set_sample_time(SampleTime::CYCLES24_5); - let mut vrefint_channel = adc.enable_vrefint(); loop { - let vrefint = adc.blocking_read(&mut vrefint_channel); + let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES24_5); info!("vrefint: {}", vrefint); - let measured = adc.blocking_read(&mut p.PA0); + let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES24_5); info!("measured: {}", measured); Timer::after_millis(500).await; } diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs index a53c9d8d5..fc45541bf 100644 --- a/examples/stm32h7/src/bin/adc.rs +++ b/examples/stm32h7/src/bin/adc.rs @@ -46,14 +46,12 @@ async fn main(_spawner: Spawner) { let mut adc = Adc::new(p.ADC3); - adc.set_sample_time(SampleTime::CYCLES32_5); - let mut vrefint_channel = adc.enable_vrefint(); loop { - let vrefint = adc.blocking_read(&mut vrefint_channel); + let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES32_5); info!("vrefint: {}", vrefint); - let measured = adc.blocking_read(&mut p.PC0); + let measured = adc.blocking_read(&mut p.PC0, SampleTime::CYCLES32_5); info!("measured: {}", measured); Timer::after_millis(500).await; } diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs index 9dd09bc45..83be74ed9 100644 --- a/examples/stm32l0/src/bin/adc.rs +++ b/examples/stm32l0/src/bin/adc.rs @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut adc = Adc::new(p.ADC1, Irqs); - adc.set_sample_time(SampleTime::CYCLES79_5); let mut pin = p.PA1; let mut vrefint = adc.enable_vref(); - let vrefint_sample = adc.read(&mut vrefint).await; + let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES79_5).await; let convert_to_millivolts = |sample| { // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf // 6.3.3 Embedded internal reference voltage @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { }; loop { - let v = adc.read(&mut pin).await; + let v = adc.read(&mut pin, SampleTime::CYCLES79_5).await; info!("--> {} - {} mV", v, convert_to_millivolts(v)); Timer::after_millis(100).await; } diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs index 40e907940..835bf5411 100644 --- a/examples/stm32l4/src/bin/adc.rs +++ b/examples/stm32l4/src/bin/adc.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_stm32::Config; -use embassy_stm32::adc::{Adc, Resolution}; +use embassy_stm32::adc::{Adc, Resolution, SampleTime}; use {defmt_rtt as _, panic_probe as _}; #[cortex_m_rt::entry] @@ -23,7 +23,7 @@ fn main() -> ! { let mut channel = p.PC0; loop { - let v = adc.blocking_read(&mut channel); + let v = adc.blocking_read(&mut channel, SampleTime::from_bits(0)); info!("--> {}", v); } } diff --git a/examples/stm32l4/src/bin/adc_dma.rs b/examples/stm32l4/src/bin/adc_dma.rs index 7a9200edd..ab1e9d2e9 100644 --- a/examples/stm32l4/src/bin/adc_dma.rs +++ b/examples/stm32l4/src/bin/adc_dma.rs @@ -21,18 +21,14 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); let mut adc = Adc::new(p.ADC1); - let mut adc_pin0 = p.PA0.degrade_adc(); - let mut adc_pin1 = p.PA1.degrade_adc(); + let adc_pin0 = p.PA0.degrade_adc(); + let adc_pin1 = p.PA1.degrade_adc(); let mut adc_dma_buf = [0u16; DMA_BUF_LEN]; let mut measurements = [0u16; DMA_BUF_LEN / 2]; let mut ring_buffered_adc = adc.into_ring_buffered( p.DMA1_CH1, &mut adc_dma_buf, - [ - (&mut adc_pin0, SampleTime::CYCLES640_5), - (&mut adc_pin1, SampleTime::CYCLES640_5), - ] - .into_iter(), + [(adc_pin0, SampleTime::CYCLES640_5), (adc_pin1, SampleTime::CYCLES640_5)].into_iter(), ); info!("starting measurement loop"); diff --git a/examples/stm32u0/src/bin/adc.rs b/examples/stm32u0/src/bin/adc.rs index 32a54299d..4fbc6f17f 100644 --- a/examples/stm32u0/src/bin/adc.rs +++ b/examples/stm32u0/src/bin/adc.rs @@ -3,7 +3,7 @@ use defmt::*; use embassy_stm32::Config; -use embassy_stm32::adc::{Adc, Resolution}; +use embassy_stm32::adc::{Adc, Resolution, SampleTime}; use embassy_time::Duration; use {defmt_rtt as _, panic_probe as _}; @@ -23,7 +23,7 @@ fn main() -> ! { let mut channel = p.PC0; loop { - let v = adc.blocking_read(&mut channel); + let v = adc.blocking_read(&mut channel, SampleTime::CYCLES12_5); info!("--> {}", v); embassy_time::block_for(Duration::from_millis(200)); } diff --git a/examples/stm32u5/src/bin/adc.rs b/examples/stm32u5/src/bin/adc.rs index 91e33053e..99944f7c7 100644 --- a/examples/stm32u5/src/bin/adc.rs +++ b/examples/stm32u5/src/bin/adc.rs @@ -2,8 +2,7 @@ #![no_main] use defmt::*; -use embassy_stm32::adc; -use embassy_stm32::adc::{AdcChannel, adc4}; +use embassy_stm32::adc::{self, AdcChannel, SampleTime, adc4}; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -18,7 +17,6 @@ async fn main(_spawner: embassy_executor::Spawner) { let mut adc1_pin2 = p.PA2; // A1 adc1.set_resolution(adc::Resolution::BITS14); adc1.set_averaging(adc::Averaging::Samples1024); - adc1.set_sample_time(adc::SampleTime::CYCLES160_5); let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); // **** ADC2 init **** @@ -27,7 +25,6 @@ async fn main(_spawner: embassy_executor::Spawner) { let mut adc2_pin2 = p.PB0; // A3 adc2.set_resolution(adc::Resolution::BITS14); adc2.set_averaging(adc::Averaging::Samples1024); - adc2.set_sample_time(adc::SampleTime::CYCLES160_5); let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); // **** ADC4 init **** @@ -36,33 +33,32 @@ async fn main(_spawner: embassy_executor::Spawner) { let mut adc4_pin2 = p.PC0; // A5 adc4.set_resolution(adc4::Resolution::BITS12); adc4.set_averaging(adc4::Averaging::Samples256); - adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); // **** ADC1 blocking read **** - let raw: u16 = adc1.blocking_read(&mut adc1_pin1); + let raw: u16 = adc1.blocking_read(&mut adc1_pin1, SampleTime::CYCLES160_5); let volt: f32 = 3.3 * raw as f32 / max1 as f32; info!("Read adc1 pin 1 {}", volt); - let raw: u16 = adc1.blocking_read(&mut adc1_pin2); + let raw: u16 = adc1.blocking_read(&mut adc1_pin2, SampleTime::CYCLES160_5); let volt: f32 = 3.3 * raw as f32 / max1 as f32; info!("Read adc1 pin 2 {}", volt); // **** ADC2 blocking read **** - let raw: u16 = adc2.blocking_read(&mut adc2_pin1); + let raw: u16 = adc2.blocking_read(&mut adc2_pin1, SampleTime::CYCLES160_5); let volt: f32 = 3.3 * raw as f32 / max2 as f32; info!("Read adc2 pin 1 {}", volt); - let raw: u16 = adc2.blocking_read(&mut adc2_pin2); + let raw: u16 = adc2.blocking_read(&mut adc2_pin2, SampleTime::CYCLES160_5); let volt: f32 = 3.3 * raw as f32 / max2 as f32; info!("Read adc2 pin 2 {}", volt); // **** ADC4 blocking read **** - let raw: u16 = adc4.blocking_read(&mut adc4_pin1); + let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); let volt: f32 = 3.3 * raw as f32 / max4 as f32; info!("Read adc4 pin 1 {}", volt); - let raw: u16 = adc4.blocking_read(&mut adc4_pin2); + let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); let volt: f32 = 3.3 * raw as f32 / max4 as f32; info!("Read adc4 pin 2 {}", volt); diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs index 8c80470b8..177aab3f3 100644 --- a/examples/stm32wba/src/bin/adc.rs +++ b/examples/stm32wba/src/bin/adc.rs @@ -17,15 +17,15 @@ async fn main(_spawner: embassy_executor::Spawner) { let mut adc4_pin2 = p.PA1; // A5 adc4.set_resolution(adc4::Resolution::BITS12); adc4.set_averaging(adc4::Averaging::Samples256); - adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); + let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); // **** ADC4 blocking read **** - let raw: u16 = adc4.blocking_read(&mut adc4_pin1); + let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); let volt: f32 = 3.0 * raw as f32 / max4 as f32; info!("Read adc4 pin 1 {}", volt); - let raw: u16 = adc4.blocking_read(&mut adc4_pin2); + let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); let volt: f32 = 3.3 * raw as f32 / max4 as f32; info!("Read adc4 pin 2 {}", volt); diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs index 8c80470b8..0887e124c 100644 --- a/examples/stm32wba6/src/bin/adc.rs +++ b/examples/stm32wba6/src/bin/adc.rs @@ -17,15 +17,14 @@ async fn main(_spawner: embassy_executor::Spawner) { let mut adc4_pin2 = p.PA1; // A5 adc4.set_resolution(adc4::Resolution::BITS12); adc4.set_averaging(adc4::Averaging::Samples256); - adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); // **** ADC4 blocking read **** - let raw: u16 = adc4.blocking_read(&mut adc4_pin1); + let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); let volt: f32 = 3.0 * raw as f32 / max4 as f32; info!("Read adc4 pin 1 {}", volt); - let raw: u16 = adc4.blocking_read(&mut adc4_pin2); + let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); let volt: f32 = 3.3 * raw as f32 / max4 as f32; info!("Read adc4 pin 2 {}", volt); diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs index 6b21b086b..adabe0df8 100644 --- a/examples/stm32wl/src/bin/adc.rs +++ b/examples/stm32wl/src/bin/adc.rs @@ -18,11 +18,11 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); - adc.set_sample_time(SampleTime::CYCLES79_5); + let mut pin = p.PB2; let mut vrefint = adc.enable_vrefint(); - let vrefint_sample = adc.blocking_read(&mut vrefint); + let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); let convert_to_millivolts = |sample| { // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf // 6.3.3 Embedded internal reference voltage @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { }; loop { - let v = adc.blocking_read(&mut pin); + let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); info!("--> {} - {} mV", v, convert_to_millivolts(v)); Timer::after_millis(100).await; } diff --git a/examples/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs index 8b830a1e6..4e0574d97 100644 --- a/examples/stm32wle5/src/bin/adc.rs +++ b/examples/stm32wle5/src/bin/adc.rs @@ -73,11 +73,10 @@ async fn async_main(_spawner: Spawner) { info!("Hello World!"); let mut adc = Adc::new(p.ADC1); - adc.set_sample_time(SampleTime::CYCLES79_5); let mut pin = p.PA10; let mut vrefint = adc.enable_vrefint(); - let vrefint_sample = adc.blocking_read(&mut vrefint); + let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); let convert_to_millivolts = |sample| { // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf // 6.3.3 Embedded internal reference voltage @@ -87,7 +86,7 @@ async fn async_main(_spawner: Spawner) { }; loop { - let v = adc.blocking_read(&mut pin); + let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); info!("--> {} - {} mV", v, convert_to_millivolts(v)); Timer::after_secs(1).await; } diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs index d34bbb255..747b11e7f 100644 --- a/tests/stm32/src/bin/dac.rs +++ b/tests/stm32/src/bin/dac.rs @@ -10,7 +10,7 @@ use core::f32::consts::PI; use common::*; use defmt::assert; use embassy_executor::Spawner; -use embassy_stm32::adc::Adc; +use embassy_stm32::adc::{Adc, SampleTime}; use embassy_stm32::dac::{DacCh1, Value}; use embassy_time::Timer; use micromath::F32Ext; @@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) { dac.set(Value::Bit8(0)); // Now wait a little to obtain a stable value Timer::after_millis(30).await; - let offset = adc.blocking_read(&mut adc_pin); + let offset = adc.blocking_read(&mut adc_pin, SampleTime::from_bits(0)); for v in 0..=255 { // First set the DAC output value @@ -48,7 +48,10 @@ async fn main(_spawner: Spawner) { Timer::after_millis(30).await; // Need to steal the peripherals here because PA4 is obviously in use already - let measured = adc.blocking_read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); + let measured = adc.blocking_read( + &mut unsafe { embassy_stm32::Peripherals::steal() }.PA4, + SampleTime::from_bits(0), + ); // Calibrate and normalize the measurement to get close to the dac_output_val let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; diff --git a/tests/stm32/src/bin/dac_l1.rs b/tests/stm32/src/bin/dac_l1.rs index e6400f28e..2fe0cf1f1 100644 --- a/tests/stm32/src/bin/dac_l1.rs +++ b/tests/stm32/src/bin/dac_l1.rs @@ -10,7 +10,7 @@ use core::f32::consts::PI; use common::*; use defmt::assert; use embassy_executor::Spawner; -use embassy_stm32::adc::Adc; +use embassy_stm32::adc::{Adc, SampleTime}; use embassy_stm32::dac::{DacCh1, Value}; use embassy_stm32::{bind_interrupts, peripherals}; use embassy_time::Timer; @@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) { dac.set(Value::Bit8(0)); // Now wait a little to obtain a stable value Timer::after_millis(30).await; - let offset = adc.read(&mut adc_pin).await; + let offset = adc.read(&mut adc_pin, SampleTime::from_bits(0)).await; for v in 0..=255 { // First set the DAC output value @@ -58,7 +58,12 @@ async fn main(_spawner: Spawner) { Timer::after_millis(30).await; // Need to steal the peripherals here because PA4 is obviously in use already - let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4).await; + let measured = adc + .read( + &mut unsafe { embassy_stm32::Peripherals::steal() }.PA4, + SampleTime::from_bits(0), + ) + .await; // Calibrate and normalize the measurement to get close to the dac_output_val let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; -- cgit From c90e4b3135283070bddc6a8e64df3139909ac8ce Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 10 Nov 2025 12:37:38 -0600 Subject: adc: use common vref scheme --- embassy-stm32/src/adc/c0.rs | 32 ++++---------- embassy-stm32/src/adc/f1.rs | 24 ++++------ embassy-stm32/src/adc/f3.rs | 26 ++++------- embassy-stm32/src/adc/g4.rs | 85 ++++++++++-------------------------- embassy-stm32/src/adc/mod.rs | 41 ++++++++++++++++++ embassy-stm32/src/adc/v1.rs | 40 +++++++---------- embassy-stm32/src/adc/v2.rs | 47 ++++++++------------ embassy-stm32/src/adc/v3.rs | 101 +++++++++++++++++++++---------------------- embassy-stm32/src/adc/v4.rs | 61 +++++++++++--------------- 9 files changed, 195 insertions(+), 262 deletions(-) diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs index 70302ef96..1869993a5 100644 --- a/embassy-stm32/src/adc/c0.rs +++ b/embassy-stm32/src/adc/c0.rs @@ -19,33 +19,17 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(25); const TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US: u32 = 20; -const TEMP_CHANNEL: u8 = 9; -const VREF_CHANNEL: u8 = 10; - const NUM_HW_CHANNELS: u8 = 22; const CHSELR_SQ_SIZE: usize = 8; const CHSELR_SQ_MAX_CHANNEL: u8 = 14; const CHSELR_SQ_SEQUENCE_END_MARKER: u8 = 0b1111; -// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, -// this currently cannot be modeled with stm32-data, -// so these are available from the software on all ADCs. -/// Internal voltage reference channel. -pub struct VrefInt; -impl AdcChannel for VrefInt {} -impl SealedAdcChannel for VrefInt { - fn channel(&self) -> u8 { - VREF_CHANNEL - } +impl super::VrefConverter for T { + const CHANNEL: u8 = 10; } -/// Internal temperature channel. -pub struct Temperature; -impl AdcChannel for Temperature {} -impl SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - TEMP_CHANNEL - } +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 9; } #[derive(Copy, Clone, Debug)] @@ -232,22 +216,22 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Enable reading the voltage reference internal channel. - pub fn enable_vrefint(&self) -> VrefInt { + pub fn enable_vrefint(&self) -> super::VrefInt { T::common_regs().ccr().modify(|reg| { reg.set_vrefen(true); }); - VrefInt {} + super::VrefInt {} } /// Enable reading the temperature internal channel. - pub fn enable_temperature(&self) -> Temperature { + pub fn enable_temperature(&self) -> super::Temperature { debug!("Ensure that sample time is set to more than temperature sensor T_start from the datasheet!"); T::common_regs().ccr().modify(|reg| { reg.set_tsen(true); }); - Temperature {} + super::Temperature {} } /// Set the ADC sample time. diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index 32e330d76..835cc8c63 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs @@ -28,20 +28,12 @@ impl interrupt::typelevel::Handler for InterruptHandl } } -pub struct Vref; -impl AdcChannel for Vref {} -impl super::SealedAdcChannel for Vref { - fn channel(&self) -> u8 { - 17 - } +impl super::VrefConverter for T { + const CHANNEL: u8 = 17; } -pub struct Temperature; -impl AdcChannel for Temperature {} -impl super::SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - 16 - } +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 16; } impl<'d, T: Instance> Adc<'d, T> { @@ -91,18 +83,18 @@ impl<'d, T: Instance> Adc<'d, T> { } } - pub fn enable_vref(&self) -> Vref { + pub fn enable_vref(&self) -> super::VrefInt { T::regs().cr2().modify(|reg| { reg.set_tsvrefe(true); }); - Vref {} + super::VrefInt {} } - pub fn enable_temperature(&self) -> Temperature { + pub fn enable_temperature(&self) -> super::Temperature { T::regs().cr2().modify(|reg| { reg.set_tsvrefe(true); }); - Temperature {} + super::Temperature {} } /// Perform a single conversion. diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs index cf31aa81b..da185e875 100644 --- a/embassy-stm32/src/adc/f3.rs +++ b/embassy-stm32/src/adc/f3.rs @@ -29,27 +29,19 @@ impl interrupt::typelevel::Handler for InterruptHandl } } -pub struct Vref; -impl AdcChannel for Vref {} -impl super::SealedAdcChannel for Vref { - fn channel(&self) -> u8 { - 18 - } +impl super::VrefConverter for T { + const CHANNEL: u8 = 18; } -impl Vref { +impl super::VrefInt { /// The value that vref would be if vdda was at 3300mv pub fn value(&self) -> u16 { crate::pac::VREFINTCAL.data().read() } } -pub struct Temperature; -impl AdcChannel for Temperature {} -impl super::SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - 16 - } +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 16; } impl<'d, T: Instance> Adc<'d, T> { @@ -109,16 +101,16 @@ impl<'d, T: Instance> Adc<'d, T> { } } - pub fn enable_vref(&self) -> Vref { + pub fn enable_vref(&self) -> super::VrefInt { T::common_regs().ccr().modify(|w| w.set_vrefen(true)); - Vref {} + super::VrefInt {} } - pub fn enable_temperature(&self) -> Temperature { + pub fn enable_temperature(&self) -> super::Temperature { T::common_regs().ccr().modify(|w| w.set_tsen(true)); - Temperature {} + super::Temperature {} } /// Perform a single conversion. diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 5066aeec0..2138a82b4 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -35,34 +35,6 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60); #[cfg(stm32h7)] const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); -// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs -/// Internal voltage reference channel. -pub struct VrefInt; -impl AdcChannel for VrefInt {} -impl super::SealedAdcChannel for VrefInt { - fn channel(&self) -> u8 { - T::CHANNEL - } -} - -/// Internal temperature channel. -pub struct Temperature; -impl AdcChannel for Temperature {} -impl super::SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - T::CHANNEL - } -} - -/// Internal battery voltage channel. -pub struct Vbat; -impl AdcChannel for Vbat {} -impl super::SealedAdcChannel for Vbat { - fn channel(&self) -> u8 { - T::CHANNEL - } -} - // NOTE (unused): The prescaler enum closely copies the hardware capabilities, // but high prescaling doesn't make a lot of sense in the current implementation and is ommited. #[allow(unused)] @@ -250,39 +222,39 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Enable reading the voltage reference internal channel. - pub fn enable_vrefint(&self) -> VrefInt + pub fn enable_vrefint(&self) -> super::VrefInt where - T: VrefChannel, + T: super::VrefConverter, { T::common_regs().ccr().modify(|reg| { reg.set_vrefen(true); }); - VrefInt {} + super::VrefInt {} } /// Enable reading the temperature internal channel. - pub fn enable_temperature(&self) -> Temperature + pub fn enable_temperature(&self) -> super::Temperature where - T: TemperatureChannel, + T: super::TemperatureConverter, { T::common_regs().ccr().modify(|reg| { reg.set_vsenseen(true); }); - Temperature {} + super::Temperature {} } /// Enable reading the vbat internal channel. - pub fn enable_vbat(&self) -> Vbat + pub fn enable_vbat(&self) -> super::Vbat where - T: VBatChannel, + T: super::VBatConverter, { T::common_regs().ccr().modify(|reg| { reg.set_vbaten(true); }); - Vbat {} + super::Vbat {} } /// Enable differential channel. @@ -850,62 +822,49 @@ impl InjectedAdc { } } -/// Implemented for ADCs that have a Temperature channel -pub trait TemperatureChannel { - const CHANNEL: u8; -} -/// Implemented for ADCs that have a Vref channel -pub trait VrefChannel { - const CHANNEL: u8; -} -/// Implemented for ADCs that have a VBat channel -pub trait VBatChannel { - const CHANNEL: u8; -} - #[cfg(stm32g4)] mod g4 { - pub use super::*; + use crate::adc::{TemperatureConverter, VBatConverter, VrefConverter}; - impl TemperatureChannel for crate::peripherals::ADC1 { + impl TemperatureConverter for crate::peripherals::ADC1 { const CHANNEL: u8 = 16; } - impl VrefChannel for crate::peripherals::ADC1 { + impl VrefConverter for crate::peripherals::ADC1 { const CHANNEL: u8 = 18; } - impl VBatChannel for crate::peripherals::ADC1 { + impl VBatConverter for crate::peripherals::ADC1 { const CHANNEL: u8 = 17; } #[cfg(peri_adc3_common)] - impl VrefChannel for crate::peripherals::ADC3 { + impl VrefConverter for crate::peripherals::ADC3 { const CHANNEL: u8 = 18; } #[cfg(peri_adc3_common)] - impl VBatChannel for crate::peripherals::ADC3 { + impl VBatConverter for crate::peripherals::ADC3 { const CHANNEL: u8 = 17; } #[cfg(not(stm32g4x1))] - impl VrefChannel for crate::peripherals::ADC4 { + impl VrefConverter for crate::peripherals::ADC4 { const CHANNEL: u8 = 18; } #[cfg(not(stm32g4x1))] - impl TemperatureChannel for crate::peripherals::ADC5 { + impl TemperatureConverter for crate::peripherals::ADC5 { const CHANNEL: u8 = 4; } #[cfg(not(stm32g4x1))] - impl VrefChannel for crate::peripherals::ADC5 { + impl VrefConverter for crate::peripherals::ADC5 { const CHANNEL: u8 = 18; } #[cfg(not(stm32g4x1))] - impl VBatChannel for crate::peripherals::ADC5 { + impl VBatConverter for crate::peripherals::ADC5 { const CHANNEL: u8 = 17; } } @@ -913,13 +872,13 @@ mod g4 { // TODO this should look at each ADC individually and impl the correct channels #[cfg(stm32h7)] mod h7 { - impl TemperatureChannel for T { + impl TemperatureConverter for T { const CHANNEL: u8 = 18; } - impl VrefChannel for T { + impl VrefConverter for T { const CHANNEL: u8 = 19; } - impl VBatChannel for T { + impl VBatConverter for T { // TODO this should be 14 for H7a/b/35 const CHANNEL: u8 = 17; } diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index a6b796fb9..a5ca6277f 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -100,6 +100,47 @@ pub(crate) fn blocking_delay_us(us: u32) { } } +/// Implemented for ADCs that have a Temperature channel +pub trait TemperatureConverter { + const CHANNEL: u8; +} +/// Implemented for ADCs that have a Vref channel +pub trait VrefConverter { + const CHANNEL: u8; +} +/// Implemented for ADCs that have a VBat channel +pub trait VBatConverter { + const CHANNEL: u8; +} + +// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs +/// Internal voltage reference channel. +pub struct VrefInt; +impl AdcChannel for VrefInt {} +impl SealedAdcChannel for VrefInt { + fn channel(&self) -> u8 { + T::CHANNEL + } +} + +/// Internal temperature channel. +pub struct Temperature; +impl AdcChannel for Temperature {} +impl SealedAdcChannel for Temperature { + fn channel(&self) -> u8 { + T::CHANNEL + } +} + +/// Internal battery voltage channel. +pub struct Vbat; +impl AdcChannel for Vbat {} +impl SealedAdcChannel for Vbat { + fn channel(&self) -> u8 { + T::CHANNEL + } +} + /// ADC instance. #[cfg(not(any( adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index 3838cc12a..97557ee8a 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -5,10 +5,11 @@ use core::task::Poll; #[cfg(adc_l0)] use stm32_metapac::adc::vals::Ckmode; -use super::blocking_delay_us; +#[cfg(not(adc_l0))] +use super::Vbat; +use super::{Temperature, VrefInt, blocking_delay_us}; use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime}; use crate::interrupt::typelevel::Interrupt; -use crate::peripherals::ADC1; use crate::{Peri, interrupt, rcc}; mod watchdog_v1; @@ -42,32 +43,23 @@ impl interrupt::typelevel::Handler for InterruptHandl } #[cfg(not(adc_l0))] -pub struct Vbat; - -#[cfg(not(adc_l0))] -impl AdcChannel for Vbat {} +impl super::VBatConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 18; +} #[cfg(not(adc_l0))] -impl super::SealedAdcChannel for Vbat { - fn channel(&self) -> u8 { - 18 - } +impl super::VrefConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 17; } -pub struct Vref; -impl AdcChannel for Vref {} -impl super::SealedAdcChannel for Vref { - fn channel(&self) -> u8 { - 17 - } +#[cfg(adc_l0)] +impl super::VrefConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 18; } -pub struct Temperature; -impl AdcChannel for Temperature {} -impl super::SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - if cfg!(adc_l0) { 18 } else { 16 } - } +#[cfg(not(adc_l0))] +impl super::TemperatureConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 16; } impl<'d, T: Instance> Adc<'d, T> { @@ -127,12 +119,12 @@ impl<'d, T: Instance> Adc<'d, T> { Vbat } - pub fn enable_vref(&self) -> Vref { + pub fn enable_vref(&self) -> VrefInt { // Table 28. Embedded internal reference voltage // tstart = 10μs T::regs().ccr().modify(|reg| reg.set_vrefen(true)); blocking_delay_us(10); - Vref + VrefInt } pub fn enable_temperature(&self) -> Temperature { diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 67721770a..af5d486d9 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -1,10 +1,9 @@ use core::mem; use core::sync::atomic::{Ordering, compiler_fence}; -use super::blocking_delay_us; +use super::{Temperature, Vbat, VrefInt, blocking_delay_us}; use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; use crate::pac::adc::vals; -use crate::peripherals::ADC1; use crate::time::Hertz; use crate::{Peri, rcc}; @@ -23,12 +22,22 @@ pub const VREF_DEFAULT_MV: u32 = 3300; /// VREF voltage used for factory calibration of VREFINTCAL register. pub const VREF_CALIB_MV: u32 = 3300; -pub struct VrefInt; -impl AdcChannel for VrefInt {} -impl super::SealedAdcChannel for VrefInt { - fn channel(&self) -> u8 { - 17 - } +impl super::VrefConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 17; +} + +#[cfg(any(stm32f2, stm32f40x, stm32f41x))] +impl super::TemperatureConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 16; +} + +#[cfg(not(any(stm32f2, stm32f40x, stm32f41x)))] +impl super::TemperatureConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 18; +} + +impl super::VBatConverter for crate::peripherals::ADC1 { + const CHANNEL: u8 = 18; } impl VrefInt { @@ -38,20 +47,6 @@ impl VrefInt { } } -pub struct Temperature; -impl AdcChannel for Temperature {} -impl super::SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - cfg_if::cfg_if! { - if #[cfg(any(stm32f2, stm32f40x, stm32f41x))] { - 16 - } else { - 18 - } - } - } -} - impl Temperature { /// Time needed for temperature sensor readings to stabilize pub fn start_time_us() -> u32 { @@ -59,14 +54,6 @@ impl Temperature { } } -pub struct Vbat; -impl AdcChannel for Vbat {} -impl super::SealedAdcChannel for Vbat { - fn channel(&self) -> u8 { - 18 - } -} - enum Prescaler { Div2, Div4, diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index bbbaf73c8..0822fbb69 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -9,8 +9,11 @@ use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs}; #[cfg(adc_g0)] pub use pac::adc::vals::{Ovsr, Ovss, Presc}; +#[allow(unused_imports)] +use super::SealedAdcChannel; use super::{ - Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, + Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, Temperature, Vbat, VrefInt, + blocking_delay_us, }; #[cfg(any(adc_v3, adc_g0, adc_u0))] @@ -32,61 +35,55 @@ pub const VREF_CALIB_MV: u32 = 3000; // TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable const SAMPLE_TIMES_CAPACITY: usize = 2; -pub struct VrefInt; -impl AdcChannel for VrefInt {} -impl SealedAdcChannel for VrefInt { - fn channel(&self) -> u8 { - cfg_if! { - if #[cfg(adc_g0)] { - let val = 13; - } else if #[cfg(any(adc_h5, adc_h7rs))] { - let val = 17; - } else if #[cfg(adc_u0)] { - let val = 12; - } else { - let val = 0; - } - } - val - } +#[cfg(adc_g0)] +impl super::VrefConverter for T { + const CHANNEL: u8 = 13; +} +#[cfg(any(adc_h5, adc_h7rs))] +impl super::VrefConverter for T { + const CHANNEL: u8 = 17; +} +#[cfg(adc_u0)] +impl super::VrefConverter for T { + const CHANNEL: u8 = 12; +} +#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] +impl super::VrefConverter for T { + const CHANNEL: u8 = 0; } -pub struct Temperature; -impl AdcChannel for Temperature {} -impl SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - cfg_if! { - if #[cfg(adc_g0)] { - let val = 12; - } else if #[cfg(any(adc_h5, adc_h7rs))] { - let val = 16; - } else if #[cfg(adc_u0)] { - let val = 11; - } else { - let val = 17; - } - } - val - } +#[cfg(adc_g0)] +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 12; +} +#[cfg(any(adc_h5, adc_h7rs))] +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 16; +} +#[cfg(adc_u0)] +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 11; +} +#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 17; } -pub struct Vbat; -impl AdcChannel for Vbat {} -impl SealedAdcChannel for Vbat { - fn channel(&self) -> u8 { - cfg_if! { - if #[cfg(adc_g0)] { - let val = 14; - } else if #[cfg(any(adc_h5, adc_h7rs))] { - let val = 2; - } else if #[cfg(any(adc_h5, adc_h7rs))] { - let val = 13; - } else { - let val = 18; - } - } - val - } +#[cfg(adc_g0)] +impl super::VBatConverter for T { + const CHANNEL: u8 = 14; +} +#[cfg(any(adc_h5, adc_h7rs))] +impl super::VBatConverter for T { + const CHANNEL: u8 = 2; +} +#[cfg(adc_u0)] +impl super::VBatConverter for T { + const CHANNEL: u8 = 13; +} +#[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] +impl super::VBatConverter for T { + const CHANNEL: u8 = 18; } cfg_if! { diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index cc3f8b34e..2f7baf3bf 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -5,7 +5,8 @@ use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel}; use pac::adccommon::vals::Presc; use super::{ - Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, + Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, Temperature, Vbat, + VrefInt, blocking_delay_us, }; use crate::dma::Transfer; use crate::time::Hertz; @@ -25,52 +26,40 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); #[cfg(stm32g4)] -const VREF_CHANNEL: u8 = 18; +impl super::VrefConverter for T { + const CHANNEL: u8 = 18; +} #[cfg(stm32g4)] -const TEMP_CHANNEL: u8 = 16; +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 16; +} #[cfg(stm32h7)] -const VREF_CHANNEL: u8 = 19; +impl super::VrefConverter for T { + const CHANNEL: u8 = 19; +} #[cfg(stm32h7)] -const TEMP_CHANNEL: u8 = 18; +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 18; +} // TODO this should be 14 for H7a/b/35 #[cfg(not(stm32u5))] -const VBAT_CHANNEL: u8 = 17; +impl super::VBatConverter for T { + const CHANNEL: u8 = 17; +} #[cfg(stm32u5)] -const VREF_CHANNEL: u8 = 0; -#[cfg(stm32u5)] -const TEMP_CHANNEL: u8 = 19; -#[cfg(stm32u5)] -const VBAT_CHANNEL: u8 = 18; - -// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs -/// Internal voltage reference channel. -pub struct VrefInt; -impl AdcChannel for VrefInt {} -impl SealedAdcChannel for VrefInt { - fn channel(&self) -> u8 { - VREF_CHANNEL - } +impl super::VrefConverter for T { + const CHANNEL: u8 = 0; } - -/// Internal temperature channel. -pub struct Temperature; -impl AdcChannel for Temperature {} -impl SealedAdcChannel for Temperature { - fn channel(&self) -> u8 { - TEMP_CHANNEL - } +#[cfg(stm32u5)] +impl super::TemperatureConverter for T { + const CHANNEL: u8 = 19; } - -/// Internal battery voltage channel. -pub struct Vbat; -impl AdcChannel for Vbat {} -impl SealedAdcChannel for Vbat { - fn channel(&self) -> u8 { - VBAT_CHANNEL - } +#[cfg(stm32u5)] +impl super::VBatConverter for T { + const CHANNEL: u8 = 18; } // NOTE (unused): The prescaler enum closely copies the hardware capabilities, -- cgit From ff1fb2dd6b9ebc0dd3c7b642f70fbb80a1fd030d Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 10 Nov 2025 12:49:23 -0600 Subject: adc: exact cal --- embassy-stm32/src/adc/f3.rs | 7 ------- embassy-stm32/src/adc/mod.rs | 8 ++++++++ examples/stm32f334/src/bin/adc.rs | 4 ++-- examples/stm32f334/src/bin/opamp.rs | 4 ++-- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs index da185e875..f6a4e1209 100644 --- a/embassy-stm32/src/adc/f3.rs +++ b/embassy-stm32/src/adc/f3.rs @@ -33,13 +33,6 @@ impl super::VrefConverter for T { const CHANNEL: u8 = 18; } -impl super::VrefInt { - /// The value that vref would be if vdda was at 3300mv - pub fn value(&self) -> u16 { - crate::pac::VREFINTCAL.data().read() - } -} - impl super::TemperatureConverter for T { const CHANNEL: u8 = 16; } diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index a5ca6277f..3bf893a35 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -123,6 +123,14 @@ impl SealedAdcChannel for VrefInt { } } +impl VrefInt { + #[cfg(any(adc_f3v1, adc_f3v2))] + /// The value that vref would be if vdda was at 3300mv + pub fn calibrated_value(&self) -> u16 { + crate::pac::VREFINTCAL.data().read() + } +} + /// Internal temperature channel. pub struct Temperature; impl AdcChannel for Temperature {} diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs index a420c8876..486f160ec 100644 --- a/examples/stm32f334/src/bin/adc.rs +++ b/examples/stm32f334/src/bin/adc.rs @@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) -> ! { loop { let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; - info!("read vref: {} (should be {})", vref, vrefint.value()); + info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; info!("read temperature: {}", temp); @@ -55,7 +55,7 @@ async fn main(_spawner: Spawner) -> ! { let pin = adc.read(&mut p.PA0, SampleTime::CYCLES601_5).await; info!("read pin: {}", pin); - let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; + let pin_mv = (pin as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; info!("computed pin mv: {}", pin_mv); Timer::after_millis(500).await; diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs index ddefdd03d..9555fd35d 100644 --- a/examples/stm32f334/src/bin/opamp.rs +++ b/examples/stm32f334/src/bin/opamp.rs @@ -50,7 +50,7 @@ async fn main(_spawner: Spawner) -> ! { loop { let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; - info!("read vref: {} (should be {})", vref, vrefint.value()); + info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; info!("read temperature: {}", temp); @@ -58,7 +58,7 @@ async fn main(_spawner: Spawner) -> ! { let buffer = adc.read(&mut buffer, SampleTime::CYCLES601_5).await; info!("read buffer: {}", buffer); - let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; + let pin_mv = (buffer as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; info!("computed pin mv: {}", pin_mv); Timer::after_millis(500).await; -- cgit From d89d8d9e2bb201fe5f1d8212d317abb12a91666f Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 10 Nov 2025 13:48:24 -0600 Subject: adc: consolidate functions --- embassy-stm32/src/adc/g4.rs | 125 ++++++++++++-------------- embassy-stm32/src/adc/injected.rs | 2 +- embassy-stm32/src/adc/ringbuffered.rs | 2 +- embassy-stm32/src/adc/v2.rs | 164 +++++++++++++++++----------------- embassy-stm32/src/adc/v3.rs | 2 +- 5 files changed, 140 insertions(+), 155 deletions(-) diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 2138a82b4..5d9c6ff74 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -147,7 +147,7 @@ impl<'d, T: Instance> Adc<'d, T> { s.calibrate(); blocking_delay_us(1); - s.enable(); + Self::enable(); s.configure(); s @@ -192,7 +192,7 @@ impl<'d, T: Instance> Adc<'d, T> { blocking_delay_us(20); } - fn enable(&mut self) { + fn enable() { // Make sure bits are off while T::regs().cr().read().addis() { // spin @@ -363,7 +363,7 @@ impl<'d, T: Instance> Adc<'d, T> { } /// Teardown method for stopping regular ADC conversions - pub(super) fn teardown_adc() { + pub(super) fn teardown_dma() { Self::stop_regular_conversions(); // Disable dma control @@ -418,39 +418,13 @@ impl<'d, T: Instance> Adc<'d, T> { // Ensure no conversions are ongoing and ADC is enabled. Self::stop_regular_conversions(); - self.enable(); + Self::enable(); - // Set sequence length - T::regs().sqr1().modify(|w| { - w.set_l(sequence.len() as u8 - 1); - }); - // Configure channels and ranks - for (_i, (channel, sample_time)) in sequence.enumerate() { - Self::configure_channel(channel, sample_time); - match _i { - 0..=3 => { - T::regs().sqr1().modify(|w| { - w.set_sq(_i, channel.channel()); - }); - } - 4..=8 => { - T::regs().sqr2().modify(|w| { - w.set_sq(_i - 4, channel.channel()); - }); - } - 9..=13 => { - T::regs().sqr3().modify(|w| { - w.set_sq(_i - 9, channel.channel()); - }); - } - 14..=15 => { - T::regs().sqr4().modify(|w| { - w.set_sq(_i - 14, channel.channel()); - }); - } - _ => unreachable!(), - } - } + Self::configure_sequence(sequence.map(|(channel, sample_time)| { + channel.setup(); + + (channel.channel, sample_time) + })); // Set continuous mode with oneshot dma. // Clear overrun flag before starting transfer. @@ -493,6 +467,47 @@ impl<'d, T: Instance> Adc<'d, T> { }); } + pub(super) fn configure_sequence(sequence: impl ExactSizeIterator) { + // Set sequence length + T::regs().sqr1().modify(|w| { + w.set_l(sequence.len() as u8 - 1); + }); + + // Configure channels and ranks + for (_i, (ch, sample_time)) in sequence.enumerate() { + let sample_time = sample_time.into(); + if ch <= 9 { + T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time)); + } else { + T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); + } + + match _i { + 0..=3 => { + T::regs().sqr1().modify(|w| { + w.set_sq(_i, ch); + }); + } + 4..=8 => { + T::regs().sqr2().modify(|w| { + w.set_sq(_i - 4, ch); + }); + } + 9..=13 => { + T::regs().sqr3().modify(|w| { + w.set_sq(_i - 9, ch); + }); + } + 14..=15 => { + T::regs().sqr4().modify(|w| { + w.set_sq(_i - 14, ch); + }); + } + _ => unreachable!(), + } + } + } + /// Set external trigger for regular conversion sequence fn set_regular_conversion_trigger(&mut self, trigger: ConversionTrigger) { T::regs().cfgr().modify(|r| { @@ -546,43 +561,15 @@ impl<'d, T: Instance> Adc<'d, T> { ); // reset conversions and enable the adc Self::stop_regular_conversions(); - self.enable(); + Self::enable(); //adc side setup - // Set sequence length - T::regs().sqr1().modify(|w| { - w.set_l(sequence.len() as u8 - 1); - }); - - // Configure channels and ranks - for (_i, (mut channel, sample_time)) in sequence.enumerate() { - Self::configure_channel(&mut channel, sample_time); + Self::configure_sequence(sequence.map(|(mut channel, sample_time)| { + channel.setup(); - match _i { - 0..=3 => { - T::regs().sqr1().modify(|w| { - w.set_sq(_i, channel.channel()); - }); - } - 4..=8 => { - T::regs().sqr2().modify(|w| { - w.set_sq(_i - 4, channel.channel()); - }); - } - 9..=13 => { - T::regs().sqr3().modify(|w| { - w.set_sq(_i - 9, channel.channel()); - }); - } - 14..=15 => { - T::regs().sqr4().modify(|w| { - w.set_sq(_i - 14, channel.channel()); - }); - } - _ => unreachable!(), - } - } + (channel.channel, sample_time) + })); // Clear overrun flag before starting transfer. T::regs().isr().modify(|reg| { @@ -655,7 +642,7 @@ impl<'d, T: Instance> Adc<'d, T> { ); Self::stop_regular_conversions(); - self.enable(); + Self::enable(); T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs index 0e4fe5847..f9f1bba2a 100644 --- a/embassy-stm32/src/adc/injected.rs +++ b/embassy-stm32/src/adc/injected.rs @@ -38,7 +38,7 @@ impl InjectedAdc { impl Drop for InjectedAdc { fn drop(&mut self) { - Adc::::teardown_adc(); + Adc::::teardown_dma(); compiler_fence(Ordering::SeqCst); } } diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs index 971c8195c..024c6acdc 100644 --- a/embassy-stm32/src/adc/ringbuffered.rs +++ b/embassy-stm32/src/adc/ringbuffered.rs @@ -172,7 +172,7 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> { impl Drop for RingBufferedAdc<'_, T> { fn drop(&mut self) { - Adc::::teardown_adc(); + Adc::::teardown_dma(); compiler_fence(Ordering::SeqCst); diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index af5d486d9..88a8b96ed 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -125,57 +125,14 @@ where ) -> RingBufferedAdc<'d, T> { assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); - T::regs().cr2().modify(|reg| { - reg.set_adon(true); - }); - - // Check the sequence is long enough - T::regs().sqr1().modify(|r| { - r.set_l((sequence.len() - 1).try_into().unwrap()); - }); - - for (i, (mut channel, sample_time)) in sequence.enumerate() { - // Set this GPIO as an analog input. + Self::configure_sequence(sequence.map(|(mut channel, sample_time)| { channel.setup(); - // Set the channel in the right sequence field. - T::regs().sqr3().modify(|w| w.set_sq(i, channel.channel())); - - Self::set_channel_sample_time(channel.channel(), sample_time); - } - + (channel.channel, sample_time) + })); compiler_fence(Ordering::SeqCst); - let r = T::regs(); - - // Clear all interrupts - r.sr().modify(|regs| { - regs.set_eoc(false); - regs.set_ovr(false); - regs.set_strt(false); - }); - - r.cr1().modify(|w| { - // Enable interrupt for end of conversion - w.set_eocie(true); - // Enable interrupt for overrun - w.set_ovrie(true); - // Scanning converisons of multiple channels - w.set_scan(true); - // Continuous conversion mode - w.set_discen(false); - }); - - r.cr2().modify(|w| { - // Enable DMA mode - w.set_dma(true); - // Enable continuous conversions - w.set_cont(true); - // DMA requests are issues as long as DMA=1 and data are converted. - w.set_dds(vals::Dds::CONTINUOUS); - // EOC flag is set at the end of each conversion. - w.set_eocs(vals::Eocs::EACH_CONVERSION); - }); + Self::setup_dma(); // Don't disable the clock mem::forget(self); @@ -183,24 +140,14 @@ where RingBufferedAdc::new(dma, dma_buf) } - pub(super) fn start() { - // Begin ADC conversions - T::regs().cr2().modify(|reg| { - reg.set_adon(true); - reg.set_swstart(true); - }); - } + pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { + channel.setup(); - pub(super) fn stop() { - // Stop ADC - T::regs().cr2().modify(|reg| { - // Stop ADC - reg.set_swstart(false); - }); - } + // Configure ADC + let channel = channel.channel(); - pub fn set_resolution(&mut self, resolution: Resolution) { - T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); + Self::configure_sequence([(channel, sample_time)].into_iter()); + Self::blocking_convert() } /// Enables internal voltage reference and returns [VrefInt], which can be used in @@ -236,8 +183,27 @@ where Vbat {} } - /// Perform a single conversion. - fn convert(&mut self) -> u16 { + pub(super) fn start() { + // Begin ADC conversions + T::regs().cr2().modify(|reg| { + reg.set_adon(true); + reg.set_swstart(true); + }); + } + + pub(super) fn stop() { + // Stop ADC + T::regs().cr2().modify(|reg| { + // Stop ADC + reg.set_swstart(false); + }); + } + + pub fn set_resolution(&mut self, resolution: Resolution) { + T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); + } + + pub(super) fn blocking_convert() -> u16 { // clear end of conversion flag T::regs().sr().modify(|reg| { reg.set_eoc(false); @@ -258,31 +224,63 @@ where T::regs().dr().read().0 as u16 } - pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { - channel.setup(); + pub(super) fn configure_sequence(sequence: impl ExactSizeIterator) { + T::regs().cr2().modify(|reg| { + reg.set_adon(true); + }); - // Configure ADC - let channel = channel.channel(); + // Check the sequence is long enough + T::regs().sqr1().modify(|r| { + r.set_l((sequence.len() - 1).try_into().unwrap()); + }); - // Select channel - T::regs().sqr3().write(|reg| reg.set_sq(0, channel)); + for (i, (ch, sample_time)) in sequence.enumerate() { + // Set the channel in the right sequence field. + T::regs().sqr3().modify(|w| w.set_sq(i, ch)); + + let sample_time = sample_time.into(); + if ch <= 9 { + T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); + } else { + T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); + } + } + } - // Configure channel - Self::set_channel_sample_time(channel, sample_time); + pub(super) fn setup_dma() { + let r = T::regs(); - self.convert() - } + // Clear all interrupts + r.sr().modify(|regs| { + regs.set_eoc(false); + regs.set_ovr(false); + regs.set_strt(false); + }); - fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { - let sample_time = sample_time.into(); - if ch <= 9 { - T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); - } else { - T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); - } + r.cr1().modify(|w| { + // Enable interrupt for end of conversion + w.set_eocie(true); + // Enable interrupt for overrun + w.set_ovrie(true); + // Scanning converisons of multiple channels + w.set_scan(true); + // Continuous conversion mode + w.set_discen(false); + }); + + r.cr2().modify(|w| { + // Enable DMA mode + w.set_dma(true); + // Enable continuous conversions + w.set_cont(true); + // DMA requests are issues as long as DMA=1 and data are converted. + w.set_dds(vals::Dds::CONTINUOUS); + // EOC flag is set at the end of each conversion. + w.set_eocs(vals::Eocs::EACH_CONVERSION); + }); } - pub(super) fn teardown_adc() { + pub(super) fn teardown_dma() { let r = T::regs(); // Stop ADC diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 0822fbb69..e816907d1 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -198,7 +198,7 @@ impl<'d, T: Instance> Adc<'d, T> { } #[cfg(any(adc_v3, adc_g0, adc_u0))] - pub(super) fn teardown_adc() { + pub(super) fn teardown_dma() { //disable dma control #[cfg(not(any(adc_g0, adc_u0)))] T::regs().cfgr().modify(|reg| { -- cgit From b806d7a98d7bd01a8038573748fbc03c587ba62b Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 10 Nov 2025 14:00:05 -0600 Subject: changelog --- embassy-stm32/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 595778748..8a53c9f03 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - feat: stm32/dsi support zero parameter commands in `write_cmd` ([#4847](https://github.com/embassy-rs/embassy/pull/4847)) - feat: stm32/spi: added support for slave mode ([#4388](https://github.com/embassy-rs/embassy/pull/4388)) - chore: Updated stm32-metapac and stm32-data dependencies +- adc: reogranize and cleanup somewhat. require sample_time to be passed on conversion ## 0.4.0 - 2025-08-26 -- cgit