From 814e096d226b05a439095e51008da83020a24f53 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Sat, 18 Nov 2023 19:37:56 +0000 Subject: [PATCH 1/3] STM32: Don't enable opamps in new(), wait until configured. --- embassy-stm32/src/opamp.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index 89db6d14..a8401083 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -54,19 +54,12 @@ pub struct OpAmp<'d, T: Instance> { impl<'d, T: Instance> OpAmp<'d, T> { /// Create a new driver instance. /// - /// Enables the OpAmp and configures the speed, but - /// does not set any other configuration. + /// Does not enable the opamp, but does set the speed mode on some families. pub fn new(opamp: impl Peripheral

+ 'd, #[cfg(opamp_g4)] speed: OpAmpSpeed) -> Self { into_ref!(opamp); - #[cfg(opamp_f3)] - T::regs().opampcsr().modify(|w| { - w.set_opampen(true); - }); - #[cfg(opamp_g4)] T::regs().opamp_csr().modify(|w| { - w.set_opaen(true); w.set_opahsm(speed.into()); }); @@ -74,7 +67,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { } /// Configure the OpAmp as a buffer for the provided input pin, - /// outputting to the provided output pin. + /// outputting to the provided output pin, and enable the opamp. /// /// The input pin is configured for analogue mode but not consumed, /// so it may subsequently be used for ADC or comparator inputs. @@ -129,7 +122,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { } /// Configure the OpAmp as a buffer for the provided input pin, - /// with the output only used internally. + /// with the output only used internally, and enable the opamp. /// /// The input pin is configured for analogue mode but not consumed, /// so it may be subsequently used for ADC or comparator inputs. From 2386619f1f8b9630166b0b55c275bb74125e4b9d Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Mon, 20 Nov 2023 21:17:09 +0000 Subject: [PATCH 2/3] STM32: Disable opamp when OpAmpOutput is dropped, not when the parent OpAmp is dropped --- embassy-stm32/src/opamp.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index a8401083..4a607e8a 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -74,7 +74,8 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// /// The output pin is held within the returned [`OpAmpOutput`] struct, /// preventing it being used elsewhere. The `OpAmpOutput` can then be - /// directly used as an ADC input. + /// directly used as an ADC input. The opamp will be disabled when the + /// [`OpAmpOutput`] is dropped. pub fn buffer_ext<'a, 'b, IP, OP>( &'a mut self, in_pin: &IP, @@ -128,6 +129,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// so it may be subsequently used for ADC or comparator inputs. /// /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. + /// The opamp output will be disabled when it is dropped. #[cfg(opamp_g4)] pub fn buffer_int<'a, P>(&'a mut self, pin: &P, gain: OpAmpGain) -> OpAmpInternalOutput<'a, T> where @@ -156,7 +158,21 @@ impl<'d, T: Instance> OpAmp<'d, T> { } } -impl<'d, T: Instance> Drop for OpAmp<'d, T> { +impl<'d, 'p, T: Instance, P: OutputPin> Drop for OpAmpOutput<'d, 'p, T, P> { + fn drop(&mut self) { + #[cfg(opamp_f3)] + T::regs().opampcsr().modify(|w| { + w.set_opampen(false); + }); + + #[cfg(opamp_g4)] + T::regs().opamp_csr().modify(|w| { + w.set_opaen(false); + }); + } +} + +impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { fn drop(&mut self) { #[cfg(opamp_f3)] T::regs().opampcsr().modify(|w| { From d1af6966051486fd605aff902b347b0346d2d889 Mon Sep 17 00:00:00 2001 From: Adam Greig Date: Mon, 20 Nov 2023 21:35:05 +0000 Subject: [PATCH 3/3] STM32 opamp: use impl Peripheral instead of directly taking pins --- embassy-stm32/src/opamp.rs | 46 +++++++++++++---------------- examples/stm32f334/src/bin/opamp.rs | 2 +- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index 4a607e8a..e1eb031d 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -31,12 +31,9 @@ impl From for crate::pac::opamp::vals::OpampCsrOpahsm { /// OpAmp external outputs, wired to a GPIO pad. /// -/// The GPIO output pad is held by this struct to ensure it cannot be used elsewhere. -/// /// This struct can also be used as an ADC input. -pub struct OpAmpOutput<'d, 'p, T: Instance, P: OutputPin> { +pub struct OpAmpOutput<'d, T: Instance> { _inner: &'d OpAmp<'d, T>, - _output: &'p mut P, } /// OpAmp internal outputs, wired directly to ADC inputs. @@ -76,16 +73,14 @@ 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. - pub fn buffer_ext<'a, 'b, IP, OP>( - &'a mut self, - in_pin: &IP, - out_pin: &'b mut OP, + pub fn buffer_ext( + &'d mut self, + in_pin: impl Peripheral

+ crate::gpio::sealed::Pin>, + out_pin: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, gain: OpAmpGain, - ) -> OpAmpOutput<'a, 'b, T, OP> - where - IP: NonInvertingPin + crate::gpio::sealed::Pin, - OP: OutputPin + crate::gpio::sealed::Pin, - { + ) -> OpAmpOutput<'d, T> { + into_ref!(in_pin); + into_ref!(out_pin); in_pin.set_as_analog(); out_pin.set_as_analog(); @@ -116,10 +111,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { w.set_opaen(true); }); - OpAmpOutput { - _inner: self, - _output: out_pin, - } + OpAmpOutput { _inner: self } } /// Configure the OpAmp as a buffer for the provided input pin, @@ -131,10 +123,12 @@ 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)] - pub fn buffer_int<'a, P>(&'a mut self, pin: &P, gain: OpAmpGain) -> OpAmpInternalOutput<'a, T> - where - P: NonInvertingPin + crate::gpio::sealed::Pin, - { + pub fn buffer_int( + &'d mut self, + pin: impl Peripheral

+ crate::gpio::sealed::Pin>, + gain: OpAmpGain, + ) -> OpAmpInternalOutput<'d, T> { + into_ref!(pin); pin.set_as_analog(); let (vm_sel, pga_gain) = match gain { @@ -158,7 +152,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { } } -impl<'d, 'p, T: Instance, P: OutputPin> Drop for OpAmpOutput<'d, 'p, T, P> { +impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> { fn drop(&mut self) { #[cfg(opamp_f3)] T::regs().opampcsr().modify(|w| { @@ -212,16 +206,16 @@ macro_rules! impl_opamp_external_output { ($inst:ident, $adc:ident, $ch:expr) => { foreach_adc!( ($adc, $common_inst:ident, $adc_clock:ident) => { - impl<'d, 'p, P: OutputPin> crate::adc::sealed::AdcPin - for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P> + impl<'d> crate::adc::sealed::AdcPin + for OpAmpOutput<'d, crate::peripherals::$inst> { fn channel(&self) -> u8 { $ch } } - impl<'d, 'p, P: OutputPin> crate::adc::AdcPin - for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P> + impl<'d> crate::adc::AdcPin + for OpAmpOutput<'d, crate::peripherals::$inst> { } }; diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs index 137fc9e6..10e7b354 100644 --- a/examples/stm32f334/src/bin/opamp.rs +++ b/examples/stm32f334/src/bin/opamp.rs @@ -39,7 +39,7 @@ async fn main(_spawner: Spawner) -> ! { let mut vrefint = adc.enable_vref(&mut Delay); let mut temperature = adc.enable_temperature(); - let mut buffer = opamp.buffer_ext(&p.PA7, &mut p.PA6, OpAmpGain::Mul1); + let mut buffer = opamp.buffer_ext(&mut p.PA7, &mut p.PA6, OpAmpGain::Mul1); loop { let vref = adc.read(&mut vrefint).await;