From cbf61765f166edd7377e148291c102c61903efe8 Mon Sep 17 00:00:00 2001 From: Thomas Giesel Date: Mon, 9 Jun 2025 21:15:25 +0200 Subject: [PATCH 1/2] Generate pins for new opamp pin naming scheme The new code implements the corresponding traits for the common opamp pin naming scheme of all families, which is VINPx/VINMx. The same pin must not be used for multiple channels for the same opamp. For example, if VINM0 and VINM1 of the same opamp were assigned to the same pin, the channel would not be unique, meaning that the traits would be implemented in a conflicting manner. --- embassy-stm32/Cargo.toml | 4 ++-- embassy-stm32/build.rs | 33 +++++++++++++-------------------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 034f51df9..4ee43e600 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -81,7 +81,7 @@ futures-util = { version = "0.3.30", default-features = false } sdio-host = "0.9.0" critical-section = "1.1" #stm32-metapac = { version = "16" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a502cec14512a6b833beb8f6e15f4a7b5ee7c06" } vcell = "0.1.3" nb = "1.0.0" @@ -110,7 +110,7 @@ proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "16", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-27ef8fba3483187e852eaf3796d827259f61e8ec", default-features = false, features = ["metadata"] } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8a502cec14512a6b833beb8f6e15f4a7b5ee7c06", default-features = false, features = ["metadata"] } [features] default = ["rt"] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index bb5ef53d7..8143c9a23 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -1402,31 +1402,24 @@ fn main() { } if regs.kind == "opamp" { - if pin.signal.starts_with("VP") { - // Impl NonInvertingPin for the VP* signals (VP0, VP1, VP2, etc) - let peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); - let ch: u8 = pin.signal.strip_prefix("VP").unwrap().parse().unwrap(); - - g.extend(quote! { - impl_opamp_vp_pin!( #peri, #pin_name, #ch); - }) - } else if pin.signal.starts_with("VINM") { - // Impl NonInvertingPin for the VINM* signals ( VINM0, VINM1, etc) - // STM32G4 - let peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); - let ch: Result = pin.signal.strip_prefix("VINM").unwrap().parse(); - - if let Ok(ch) = ch { + let peri = format_ident!("{}", p.name); + let pin_name = format_ident!("{}", pin.pin); + if let Some(ch_str) = pin.signal.strip_prefix("VINP") { + // Impl NonInvertingPin for VINP0, VINP1 etc. + if let Ok(ch) = ch_str.parse::() { + g.extend(quote! { + impl_opamp_vp_pin!( #peri, #pin_name, #ch ); + }); + } + } else if let Some(ch_str) = pin.signal.strip_prefix("VINM") { + // Impl InvertingPin for VINM0, VINM1 etc. + if let Ok(ch) = ch_str.parse::() { g.extend(quote! { impl_opamp_vn_pin!( #peri, #pin_name, #ch); - }) + }); } } else if pin.signal == "VOUT" { // Impl OutputPin for the VOUT pin - let peri = format_ident!("{}", p.name); - let pin_name = format_ident!("{}", pin.pin); g.extend(quote! { impl_opamp_vout_pin!( #peri, #pin_name ); }) From ca14f5452959bb23499f057ca78cf21e0e69dccd Mon Sep 17 00:00:00 2001 From: Thomas Giesel Date: Wed, 25 Jun 2025 21:06:39 +0200 Subject: [PATCH 2/2] Adapt opamp driver to new opamp IP version numbers --- embassy-stm32/src/opamp.rs | 56 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index 2eb2e61c1..0467dbce3 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -7,7 +7,7 @@ use crate::pac::opamp::vals::*; use crate::Peri; /// Performs a busy-wait delay for a specified number of microseconds. -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] fn blocking_delay_ms(ms: u32) { #[cfg(feature = "time")] embassy_time::block_for(embassy_time::Duration::from_millis(ms as u64)); @@ -23,13 +23,13 @@ pub enum OpAmpGain { Mul4, Mul8, Mul16, - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] Mul32, - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] Mul64, } -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] enum OpAmpDifferentialPair { P, N, @@ -53,7 +53,7 @@ pub struct OpAmpOutput<'d, T: Instance> { /// OpAmp internal outputs, wired directly to ADC inputs. /// /// This struct can be used as an ADC input. -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] pub struct OpAmpInternalOutput<'d, T: Instance> { _inner: &'d OpAmp<'d, T>, } @@ -67,8 +67,8 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// Create a new driver instance. /// /// Does not enable the opamp, but does set the speed mode on some families. - pub fn new(opamp: Peri<'d, T>, #[cfg(opamp_g4)] speed: OpAmpSpeed) -> Self { - #[cfg(opamp_g4)] + pub fn new(opamp: Peri<'d, T>, #[cfg(opamp_v5)] speed: OpAmpSpeed) -> Self { + #[cfg(opamp_v5)] T::regs().csr().modify(|w| { w.set_opahsm(speed == OpAmpSpeed::HighSpeed); }); @@ -94,15 +94,15 @@ impl<'d, T: Instance> OpAmp<'d, T> { in_pin.set_as_analog(); out_pin.set_as_analog(); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] let vm_sel = VmSel::OUTPUT; - #[cfg(not(opamp_g4))] + #[cfg(not(opamp_v5))] let vm_sel = VmSel::from_bits(0b11); T::regs().csr().modify(|w| { w.set_vp_sel(VpSel::from_bits(in_pin.channel())); w.set_vm_sel(vm_sel); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] w.set_opaintoen(false); w.set_opampen(true); }); @@ -129,12 +129,12 @@ impl<'d, T: Instance> OpAmp<'d, T> { in_pin.set_as_analog(); out_pin.set_as_analog(); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] let vm_sel = VmSel::PGA; - #[cfg(not(opamp_g4))] + #[cfg(not(opamp_v5))] let vm_sel = VmSel::from_bits(0b10); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] let pga_gain = match gain { OpAmpGain::Mul2 => PgaGain::GAIN2, OpAmpGain::Mul4 => PgaGain::GAIN4, @@ -143,7 +143,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { OpAmpGain::Mul32 => PgaGain::GAIN32, OpAmpGain::Mul64 => PgaGain::GAIN64, }; - #[cfg(not(opamp_g4))] + #[cfg(not(opamp_v5))] let pga_gain = PgaGain::from_bits(match gain { OpAmpGain::Mul2 => 0b00, OpAmpGain::Mul4 => 0b01, @@ -155,7 +155,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { w.set_vp_sel(VpSel::from_bits(in_pin.channel())); w.set_vm_sel(vm_sel); w.set_pga_gain(pga_gain); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] w.set_opaintoen(false); w.set_opampen(true); }); @@ -170,7 +170,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// preventing it being used elsewhere. The `OpAmpOutput` can then be /// directly used as an ADC input. The opamp will be disabled when the /// [`OpAmpOutput`] is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn buffer_dac(&mut self, out_pin: Peri<'_, impl OutputPin + crate::gpio::Pin>) -> OpAmpOutput<'_, T> { out_pin.set_as_analog(); @@ -194,7 +194,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. /// The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn buffer_int( &mut self, pin: Peri<'_, impl NonInvertingPin + crate::gpio::Pin>, @@ -204,7 +204,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { T::regs().csr().modify(|w| { w.set_vp_sel(VpSel::from_bits(pin.channel())); w.set_vm_sel(VmSel::OUTPUT); - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] w.set_opaintoen(true); w.set_opampen(true); }); @@ -220,7 +220,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. /// The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn pga_int( &mut self, pin: Peri<'_, impl NonInvertingPin + crate::gpio::Pin>, @@ -257,7 +257,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpInternalOutput` struct may be used as an ADC /// input. The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_dac_int( &mut self, m_pin: Peri<'_, impl InvertingPin + crate::gpio::Pin>, @@ -285,7 +285,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// The output pin is held within the returned [`OpAmpOutput`] struct, /// preventing it being used elsewhere. The opamp will be disabled when /// the [`OpAmpOutput`] is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_dac_ext( &mut self, m_pin: Peri<'_, impl InvertingPin + crate::gpio::Pin>, @@ -315,7 +315,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// The output pin is held within the returned [`OpAmpOutput`] struct, /// preventing it being used elsewhere. The opamp will be disabled when /// the [`OpAmpOutput`] is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_ext( &mut self, p_pin: Peri<'d, impl NonInvertingPin + crate::gpio::Pin>, @@ -346,7 +346,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The returned `OpAmpOutput` struct may be used as an ADC /// input. The opamp output will be disabled when it is dropped. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn standalone_int( &mut self, p_pin: Peri<'d, impl NonInvertingPin + crate::gpio::Pin>, @@ -374,7 +374,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// while for high-speed mode, only the P differential pair is calibrated. /// /// Calibrating a differential pair requires waiting 12ms in the worst case (binary method). - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] pub fn calibrate(&mut self) { T::regs().csr().modify(|w| { w.set_opampen(true); @@ -403,7 +403,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// The calibration range is from 0 to 31. /// /// The result is stored in the OPAMP_CSR register. - #[cfg(opamp_g4)] + #[cfg(opamp_v5)] fn calibrate_differential_pair(&mut self, pair: OpAmpDifferentialPair) { let mut low = 0; let mut high = 31; @@ -460,7 +460,7 @@ impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> { } } -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { fn drop(&mut self) { T::regs().csr().modify(|w| { @@ -545,7 +545,7 @@ foreach_peripheral!( }; ); -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] macro_rules! impl_opamp_internal_output { ($inst:ident, $adc:ident, $ch:expr) => { foreach_adc!( @@ -567,7 +567,7 @@ macro_rules! impl_opamp_internal_output { }; } -#[cfg(opamp_g4)] +#[cfg(opamp_v5)] foreach_peripheral!( (opamp, OPAMP1) => { impl_opamp_internal_output!(OPAMP1, ADC1, 13);