aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-11-20 22:47:19 +0000
committerGitHub <[email protected]>2023-11-20 22:47:19 +0000
commit766ec77ec5a9a5a0e4af32651c9eb0b6c8e93fed (patch)
tree4b5648900e1ffbea3ef70fa46b808db02d8b6dbc
parent382949e1ffee384db8f7d4279829337381f073fc (diff)
parentd1af6966051486fd605aff902b347b0346d2d889 (diff)
Merge pull request #2198 from adamgreig/stm32-opamp
STM32: Don't enable opamps in new(), wait until configured
-rw-r--r--embassy-stm32/src/opamp.rs77
-rw-r--r--examples/stm32f334/src/bin/opamp.rs2
2 files changed, 41 insertions, 38 deletions
diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs
index 89db6d14d..e1eb031d1 100644
--- a/embassy-stm32/src/opamp.rs
+++ b/embassy-stm32/src/opamp.rs
@@ -31,12 +31,9 @@ impl From<OpAmpSpeed> for crate::pac::opamp::vals::OpampCsrOpahsm {
31 31
32/// OpAmp external outputs, wired to a GPIO pad. 32/// OpAmp external outputs, wired to a GPIO pad.
33/// 33///
34/// The GPIO output pad is held by this struct to ensure it cannot be used elsewhere.
35///
36/// This struct can also be used as an ADC input. 34/// This struct can also be used as an ADC input.
37pub struct OpAmpOutput<'d, 'p, T: Instance, P: OutputPin<T>> { 35pub struct OpAmpOutput<'d, T: Instance> {
38 _inner: &'d OpAmp<'d, T>, 36 _inner: &'d OpAmp<'d, T>,
39 _output: &'p mut P,
40} 37}
41 38
42/// OpAmp internal outputs, wired directly to ADC inputs. 39/// OpAmp internal outputs, wired directly to ADC inputs.
@@ -54,19 +51,12 @@ pub struct OpAmp<'d, T: Instance> {
54impl<'d, T: Instance> OpAmp<'d, T> { 51impl<'d, T: Instance> OpAmp<'d, T> {
55 /// Create a new driver instance. 52 /// Create a new driver instance.
56 /// 53 ///
57 /// Enables the OpAmp and configures the speed, but 54 /// Does not enable the opamp, but does set the speed mode on some families.
58 /// does not set any other configuration.
59 pub fn new(opamp: impl Peripheral<P = T> + 'd, #[cfg(opamp_g4)] speed: OpAmpSpeed) -> Self { 55 pub fn new(opamp: impl Peripheral<P = T> + 'd, #[cfg(opamp_g4)] speed: OpAmpSpeed) -> Self {
60 into_ref!(opamp); 56 into_ref!(opamp);
61 57
62 #[cfg(opamp_f3)]
63 T::regs().opampcsr().modify(|w| {
64 w.set_opampen(true);
65 });
66
67 #[cfg(opamp_g4)] 58 #[cfg(opamp_g4)]
68 T::regs().opamp_csr().modify(|w| { 59 T::regs().opamp_csr().modify(|w| {
69 w.set_opaen(true);
70 w.set_opahsm(speed.into()); 60 w.set_opahsm(speed.into());
71 }); 61 });
72 62
@@ -74,24 +64,23 @@ impl<'d, T: Instance> OpAmp<'d, T> {
74 } 64 }
75 65
76 /// Configure the OpAmp as a buffer for the provided input pin, 66 /// Configure the OpAmp as a buffer for the provided input pin,
77 /// outputting to the provided output pin. 67 /// outputting to the provided output pin, and enable the opamp.
78 /// 68 ///
79 /// The input pin is configured for analogue mode but not consumed, 69 /// The input pin is configured for analogue mode but not consumed,
80 /// so it may subsequently be used for ADC or comparator inputs. 70 /// so it may subsequently be used for ADC or comparator inputs.
81 /// 71 ///
82 /// The output pin is held within the returned [`OpAmpOutput`] struct, 72 /// The output pin is held within the returned [`OpAmpOutput`] struct,
83 /// preventing it being used elsewhere. The `OpAmpOutput` can then be 73 /// preventing it being used elsewhere. The `OpAmpOutput` can then be
84 /// directly used as an ADC input. 74 /// directly used as an ADC input. The opamp will be disabled when the
85 pub fn buffer_ext<'a, 'b, IP, OP>( 75 /// [`OpAmpOutput`] is dropped.
86 &'a mut self, 76 pub fn buffer_ext(
87 in_pin: &IP, 77 &'d mut self,
88 out_pin: &'b mut OP, 78 in_pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>,
79 out_pin: impl Peripheral<P = impl OutputPin<T> + crate::gpio::sealed::Pin> + 'd,
89 gain: OpAmpGain, 80 gain: OpAmpGain,
90 ) -> OpAmpOutput<'a, 'b, T, OP> 81 ) -> OpAmpOutput<'d, T> {
91 where 82 into_ref!(in_pin);
92 IP: NonInvertingPin<T> + crate::gpio::sealed::Pin, 83 into_ref!(out_pin);
93 OP: OutputPin<T> + crate::gpio::sealed::Pin,
94 {
95 in_pin.set_as_analog(); 84 in_pin.set_as_analog();
96 out_pin.set_as_analog(); 85 out_pin.set_as_analog();
97 86
@@ -122,24 +111,24 @@ impl<'d, T: Instance> OpAmp<'d, T> {
122 w.set_opaen(true); 111 w.set_opaen(true);
123 }); 112 });
124 113
125 OpAmpOutput { 114 OpAmpOutput { _inner: self }
126 _inner: self,
127 _output: out_pin,
128 }
129 } 115 }
130 116
131 /// Configure the OpAmp as a buffer for the provided input pin, 117 /// Configure the OpAmp as a buffer for the provided input pin,
132 /// with the output only used internally. 118 /// with the output only used internally, and enable the opamp.
133 /// 119 ///
134 /// The input pin is configured for analogue mode but not consumed, 120 /// The input pin is configured for analogue mode but not consumed,
135 /// so it may be subsequently used for ADC or comparator inputs. 121 /// so it may be subsequently used for ADC or comparator inputs.
136 /// 122 ///
137 /// The returned `OpAmpInternalOutput` struct may be used as an ADC input. 123 /// The returned `OpAmpInternalOutput` struct may be used as an ADC input.
124 /// The opamp output will be disabled when it is dropped.
138 #[cfg(opamp_g4)] 125 #[cfg(opamp_g4)]
139 pub fn buffer_int<'a, P>(&'a mut self, pin: &P, gain: OpAmpGain) -> OpAmpInternalOutput<'a, T> 126 pub fn buffer_int(
140 where 127 &'d mut self,
141 P: NonInvertingPin<T> + crate::gpio::sealed::Pin, 128 pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>,
142 { 129 gain: OpAmpGain,
130 ) -> OpAmpInternalOutput<'d, T> {
131 into_ref!(pin);
143 pin.set_as_analog(); 132 pin.set_as_analog();
144 133
145 let (vm_sel, pga_gain) = match gain { 134 let (vm_sel, pga_gain) = match gain {
@@ -163,7 +152,21 @@ impl<'d, T: Instance> OpAmp<'d, T> {
163 } 152 }
164} 153}
165 154
166impl<'d, T: Instance> Drop for OpAmp<'d, T> { 155impl<'d, T: Instance> Drop for OpAmpOutput<'d, T> {
156 fn drop(&mut self) {
157 #[cfg(opamp_f3)]
158 T::regs().opampcsr().modify(|w| {
159 w.set_opampen(false);
160 });
161
162 #[cfg(opamp_g4)]
163 T::regs().opamp_csr().modify(|w| {
164 w.set_opaen(false);
165 });
166 }
167}
168
169impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> {
167 fn drop(&mut self) { 170 fn drop(&mut self) {
168 #[cfg(opamp_f3)] 171 #[cfg(opamp_f3)]
169 T::regs().opampcsr().modify(|w| { 172 T::regs().opampcsr().modify(|w| {
@@ -203,16 +206,16 @@ macro_rules! impl_opamp_external_output {
203 ($inst:ident, $adc:ident, $ch:expr) => { 206 ($inst:ident, $adc:ident, $ch:expr) => {
204 foreach_adc!( 207 foreach_adc!(
205 ($adc, $common_inst:ident, $adc_clock:ident) => { 208 ($adc, $common_inst:ident, $adc_clock:ident) => {
206 impl<'d, 'p, P: OutputPin<crate::peripherals::$inst>> crate::adc::sealed::AdcPin<crate::peripherals::$adc> 209 impl<'d> crate::adc::sealed::AdcPin<crate::peripherals::$adc>
207 for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P> 210 for OpAmpOutput<'d, crate::peripherals::$inst>
208 { 211 {
209 fn channel(&self) -> u8 { 212 fn channel(&self) -> u8 {
210 $ch 213 $ch
211 } 214 }
212 } 215 }
213 216
214 impl<'d, 'p, P: OutputPin<crate::peripherals::$inst>> crate::adc::AdcPin<crate::peripherals::$adc> 217 impl<'d> crate::adc::AdcPin<crate::peripherals::$adc>
215 for OpAmpOutput<'d, 'p, crate::peripherals::$inst, P> 218 for OpAmpOutput<'d, crate::peripherals::$inst>
216 { 219 {
217 } 220 }
218 }; 221 };
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
index 137fc9e66..10e7b3543 100644
--- a/examples/stm32f334/src/bin/opamp.rs
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -39,7 +39,7 @@ async fn main(_spawner: Spawner) -> ! {
39 39
40 let mut vrefint = adc.enable_vref(&mut Delay); 40 let mut vrefint = adc.enable_vref(&mut Delay);
41 let mut temperature = adc.enable_temperature(); 41 let mut temperature = adc.enable_temperature();
42 let mut buffer = opamp.buffer_ext(&p.PA7, &mut p.PA6, OpAmpGain::Mul1); 42 let mut buffer = opamp.buffer_ext(&mut p.PA7, &mut p.PA6, OpAmpGain::Mul1);
43 43
44 loop { 44 loop {
45 let vref = adc.read(&mut vrefint).await; 45 let vref = adc.read(&mut vrefint).await;