From aecff11b662c8232e7c848962c6c9ccda0cd9bf3 Mon Sep 17 00:00:00 2001 From: xoviat Date: Tue, 11 Nov 2025 09:37:20 -0600 Subject: adc: cleanup g4 --- embassy-stm32/src/adc/g4.rs | 125 ++++++++++----------------- examples/stm32g4/src/bin/adc_differential.rs | 6 +- 2 files changed, 51 insertions(+), 80 deletions(-) diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index c0fb7c733..e622e2a23 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs @@ -241,35 +241,6 @@ impl<'d, T: Instance> Adc<'d, T> { super::Vbat {} } - /// Enable differential channel. - /// Caution: - /// : When configuring the channel ā€œiā€ in differential input mode, its negative input voltage VINN[i] - /// is connected to another channel. As a consequence, this channel is no longer usable in - /// single-ended mode or in differential mode and must never be configured to be converted. - /// Some channels are shared between ADC1/ADC2/ADC3/ADC4/ADC5: this can make the - /// channel on the other ADC unusable. The only exception is when ADC master and the slave - /// operate in interleaved mode. - #[cfg(stm32g4)] - 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( - ch, - if enable { - Difsel::DIFFERENTIAL - } else { - Difsel::SINGLE_ENDED - }, - ); - }); - T::regs().cr().modify(|w| w.set_aden(true)); - } - - #[cfg(stm32g4)] - pub fn set_differential(&mut self, channel: &mut impl AdcChannel, enable: bool) { - self.set_differential_channel(channel.channel() as usize, enable); - } - /// Set oversampling shift. #[cfg(stm32g4)] pub fn set_oversampling_shift(&mut self, shift: u8) { @@ -331,7 +302,17 @@ impl<'d, T: Instance> Adc<'d, T> { pub fn blocking_read(&mut self, channel: &mut impl AdcChannel, sample_time: SampleTime) -> u16 { channel.setup(); - self.read_channel(channel, sample_time) + Self::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter()); + + #[cfg(stm32h7)] + { + T::regs().cfgr2().modify(|w| w.set_lshift(0)); + T::regs() + .pcsel() + .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED)); + } + + self.convert() } /// Start regular adc conversion @@ -404,11 +385,9 @@ impl<'d, T: Instance> Adc<'d, T> { Self::stop_regular_conversions(); Self::enable(); - Self::configure_sequence(sequence.map(|(channel, sample_time)| { - channel.setup(); - - (channel.channel, sample_time) - })); + Self::configure_sequence( + sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), + ); // Set continuous mode with oneshot dma. // Clear overrun flag before starting transfer. @@ -451,14 +430,14 @@ impl<'d, T: Instance> Adc<'d, T> { }); } - pub(super) fn configure_sequence(sequence: impl ExactSizeIterator) { + 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() { + for (_i, ((ch, is_differential), 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)); @@ -489,6 +468,24 @@ impl<'d, T: Instance> Adc<'d, T> { } _ => unreachable!(), } + + #[cfg(stm32g4)] + { + T::regs().cr().modify(|w| w.set_aden(false)); // disable adc + + T::regs().difsel().modify(|w| { + w.set_difsel( + ch.into(), + if is_differential { + Difsel::DIFFERENTIAL + } else { + Difsel::SINGLE_ENDED + }, + ); + }); + + T::regs().cr().modify(|w| w.set_aden(true)); // enable adc + } } } @@ -548,12 +545,9 @@ impl<'d, T: Instance> Adc<'d, T> { Self::enable(); //adc side setup - - Self::configure_sequence(sequence.map(|(mut channel, sample_time)| { - channel.setup(); - - (channel.channel, sample_time) - })); + Self::configure_sequence( + sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)), + ); // Clear overrun flag before starting transfer. T::regs().isr().modify(|reg| { @@ -630,8 +624,17 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); - for (n, (mut channel, sample_time)) in sequence.into_iter().enumerate() { - Self::configure_channel(&mut channel, sample_time); + for (n, (channel, sample_time)) in sequence.into_iter().enumerate() { + let sample_time = sample_time.into(); + if channel.channel() <= 9 { + T::regs() + .smpr() + .modify(|reg| reg.set_smp(channel.channel() as _, sample_time)); + } else { + T::regs() + .smpr2() + .modify(|reg| reg.set_smp((channel.channel() - 10) as _, sample_time)); + } let idx = match n { 0..=3 => n, @@ -733,38 +736,6 @@ impl<'d, T: Instance> Adc<'d, T> { T::regs().ier().modify(|r| r.set_jeosie(enable)); } - fn configure_channel(channel: &mut impl AdcChannel, sample_time: SampleTime) { - // Configure channel - Self::set_channel_sample_time(channel.channel(), 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)); - T::regs() - .pcsel() - .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED)); - } - - T::regs().sqr1().write(|reg| { - reg.set_sq(0, channel.channel()); - reg.set_l(0); - }); - - self.convert() - } - - fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { - 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)); - } - } - // Stop regular conversions fn stop_regular_conversions() { if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs index a6e2f7d33..2773723e9 100644 --- a/examples/stm32g4/src/bin/adc_differential.rs +++ b/examples/stm32g4/src/bin/adc_differential.rs @@ -30,16 +30,16 @@ async fn main(_spawner: Spawner) { config.rcc.mux.adc12sel = mux::Adcsel::SYS; config.rcc.sys = Sysclk::PLL1_R; } - let mut p = embassy_stm32::init(config); + let p = embassy_stm32::init(config); let mut adc = Adc::new(p.ADC1); - adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1 + let mut differential_channel = (p.PA0, p.PA1); // can also use // adc.set_differential_channel(1, true); info!("adc initialized"); loop { - let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES247_5); + let measured = adc.blocking_read(&mut differential_channel, SampleTime::CYCLES247_5); info!("data: {}", measured); Timer::after_millis(500).await; } -- cgit