Skip to content

Commit 1b80d08

Browse files
committed
Make use of frozen pins
1 parent 2cf31fc commit 1b80d08

File tree

7 files changed

+525
-517
lines changed

7 files changed

+525
-517
lines changed

examples/comp_w_dac.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn main() -> ! {
3030
// Set up DAC to output to pa4 and to internal signal Dac1IntSig1
3131
// which just so happens is compatible with comp1
3232
let dac1ch1 = dp.DAC1.constrain((gpioa.pa4, Dac1IntSig1), &mut rcc);
33-
let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable();
33+
let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable().freeze();
3434

3535
let (comp1, _comp2, ..) = dp.COMP.split(&mut rcc);
3636
let pa1 = gpioa.pa1.into_analog();

examples/opamp.rs

+16-28
Original file line numberDiff line numberDiff line change
@@ -31,35 +31,25 @@ fn main() -> ! {
3131
let gpioa = dp.GPIOA.split(&mut rcc);
3232
let gpiob = dp.GPIOB.split(&mut rcc);
3333

34-
// setup opamps
35-
let (opamp1, opamp2, opamp3, ..) = dp.OPAMP.split(&mut rcc);
36-
37-
// Set up opamp1 and opamp2 in follower mode
38-
let opamp1 = opamp1.follower(gpioa.pa1, gpioa.pa2);
39-
let opamp2 = opamp2.follower(gpioa.pa7, InternalOutput);
40-
41-
// Set up opamp1 and opamp2 in open loop mode
42-
let opamp3 = opamp3.open_loop(gpiob.pb0, gpiob.pb2, gpiob.pb1);
34+
let pa1 = gpioa.pa1.into_analog();
35+
let pa2 = gpioa.pa2.into_analog();
36+
let pa7 = gpioa.pa7.into_analog();
4337

44-
// disable opamps
45-
let (opamp1, pa1, pa2) = opamp1.disable();
46-
let (opamp2, pa7) = opamp2.disable();
38+
let pb0 = gpiob.pb0.into_analog();
39+
let pb1 = gpiob.pb1.into_analog();
40+
let pb2 = gpiob.pb2.into_analog();
4741

48-
let (_opamp3, _pb0, _pb2, _pb1) = opamp3.disable();
42+
// setup opamps
43+
let (opamp1, opamp2, opamp3, ..) = dp.OPAMP.split(&mut rcc);
4944

5045
// Configure opamp1 with pa1 as non-inverting input and set gain to x2
51-
let _opamp1 = opamp1.pga(
52-
pa1,
53-
pa2, // Route output to pin pa2
54-
Gain::Gain2,
55-
);
56-
57-
// Configure op with pa7 as non-inverting input and set gain to x4
58-
let opamp2 = opamp2.pga(
59-
pa7,
60-
InternalOutput, // Do not route output to any external pin, use internal AD instead
61-
Gain::Gain4,
62-
);
46+
let _opamp1 = opamp1.pga(&pa1, pa2, Gain::Gain2);
47+
48+
// Set up opamp2 in follower mode with output routed to internal ADC
49+
let opamp2 = opamp2.follower(&pa7, InternalOutput);
50+
51+
// Set up opamp3 in open loop mode
52+
let _opamp3 = opamp3.open_loop(&pb0, pb2, pb1);
6353

6454
// Lock opamp2. After the opamp is locked its registers cannot be written
6555
// until the device is reset (even if using unsafe register accesses).
@@ -78,15 +68,13 @@ fn main() -> ! {
7868
);
7969

8070
let millivolts = adc.sample_to_millivolts(sample);
81-
info!("opamp2 thus 4x pa7: {}mV", millivolts);
71+
info!("opamp2 thus pa7: {}mV", millivolts);
8272

8373
delay.delay_ms(100);
8474
}
8575

8676
#[allow(unreachable_code)]
8777
{
88-
let (_opamp1, _pin) = _opamp1.disable();
89-
9078
loop {
9179
delay.delay_ms(100);
9280
}

src/comparator.rs

+87-33
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55
//! This code has been taken from the stm32g0xx-hal project and modified slightly to support
66
//! STM32G4xx MCUs.
77
8+
use core::borrow::Borrow;
89
use core::marker::PhantomData;
910

1011
use crate::dac;
1112
use crate::exti::{Event as ExtiEvent, ExtiExt};
13+
use crate::gpio::{FrozenPin, IsFrozen};
1214
use crate::gpio::{
1315
gpioa::{PA0, PA1, PA11, PA12, PA2, PA3, PA4, PA5, PA6, PA7},
1416
gpiob::{PB0, PB1, PB14, PB15, PB2, PB6, PB7, PB8, PB9},
1517
gpioc::PC2,
1618
gpiof::PF4,
17-
Analog, Alternate, AlternateOD, SignalEdge, AF2, AF3, AF8,
19+
Alternate, AlternateOD, Analog, SignalEdge, AF2, AF3, AF8,
1820
};
1921

2022
#[cfg(any(
@@ -139,12 +141,17 @@ pub enum Hysteresis {
139141
}
140142

141143
/// Comparator positive input
142-
pub trait PositiveInput<C> {
143-
fn setup(&self, comp: &C);
144+
pub trait PositiveInput<C>: crate::Sealed {
145+
/// Setup comaprator to use this as its positive input
146+
///
147+
/// # Safety
148+
///
149+
/// Internal use only
150+
unsafe fn setup(&self, comp: &mut C);
144151
}
145152

146153
/// Comparator negative input
147-
pub trait NegativeInput<C> {
154+
pub trait NegativeInput<C>: crate::Sealed {
148155
/// Does this input use the internal reference Vrefint
149156
///
150157
/// This only true for RefintInput
@@ -155,19 +162,36 @@ pub trait NegativeInput<C> {
155162
/// This is only relevant for `RefintInput` other than `RefintInput::VRefint`
156163
fn use_resistor_divider(&self) -> bool;
157164

158-
fn setup(&self, comp: &C);
165+
/// Setup comaprator to use this as its negative input
166+
///
167+
/// # Safety
168+
///
169+
/// Internal use only
170+
unsafe fn setup(&self, comp: &mut C);
159171
}
160172

161173
macro_rules! positive_input_pin {
162174
($COMP:ident, $pin_0:ident, $pin_1:ident) => {
163-
impl PositiveInput<$COMP> for &$pin_0<Analog> {
164-
fn setup(&self, comp: &$COMP) {
175+
impl PositiveInput<$COMP> for &$pin_0<Analog, IsFrozen> {
176+
unsafe fn setup(&self, comp: &mut $COMP) {
177+
comp.csr().modify(|_, w| w.inpsel().bit(false))
178+
}
179+
}
180+
181+
impl PositiveInput<$COMP> for $pin_0<Analog> {
182+
unsafe fn setup(&self, comp: &mut $COMP) {
165183
comp.csr().modify(|_, w| w.inpsel().bit(false))
166184
}
167185
}
168186

169-
impl PositiveInput<$COMP> for &$pin_1<Analog> {
170-
fn setup(&self, comp: &$COMP) {
187+
impl PositiveInput<$COMP> for &$pin_1<Analog, IsFrozen> {
188+
unsafe fn setup(&self, comp: &mut $COMP) {
189+
comp.csr().modify(|_, w| w.inpsel().bit(true))
190+
}
191+
}
192+
193+
impl PositiveInput<$COMP> for $pin_1<Analog> {
194+
unsafe fn setup(&self, comp: &mut $COMP) {
171195
comp.csr().modify(|_, w| w.inpsel().bit(true))
172196
}
173197
}
@@ -212,7 +236,7 @@ macro_rules! negative_input_pin_helper {
212236
false
213237
}
214238

215-
fn setup(&self, comp: &$COMP) {
239+
unsafe fn setup(&self, comp: &mut $COMP) {
216240
comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) })
217241
}
218242
}
@@ -257,6 +281,9 @@ pub enum RefintInput {
257281
VRefint = 0b011,
258282
}
259283

284+
impl FrozenPin<RefintInput> for RefintInput {}
285+
impl crate::Sealed for RefintInput {}
286+
260287
macro_rules! refint_input {
261288
($($COMP:ident, )+) => {$(
262289
impl NegativeInput<$COMP> for RefintInput {
@@ -266,7 +293,7 @@ macro_rules! refint_input {
266293
*self != RefintInput::VRefint
267294
}
268295

269-
fn setup(&self, comp: &$COMP) {
296+
unsafe fn setup(&self, comp: &mut $COMP) {
270297
comp.csr()
271298
.modify(|_, w| unsafe { w.inmsel().bits(*self as u8) })
272299
}
@@ -285,15 +312,27 @@ refint_input!(COMP1, COMP2, COMP3, COMP4,);
285312
refint_input!(COMP5, COMP6, COMP7,);
286313

287314
macro_rules! dac_input_helper {
288-
($COMP:ident: $channel:ident, $MODE:ident, $bits:expr) => {
289-
impl<ED> NegativeInput<$COMP> for &dac::$channel<{ dac::$MODE }, ED> {
315+
($COMP:ident: $channel:ident, $MODE:ident, $ED:ty, $bits:expr) => {
316+
impl NegativeInput<$COMP> for &dac::$channel<{ dac::$MODE }, $ED, IsFrozen> {
290317
const USE_VREFINT: bool = false;
291318

292319
fn use_resistor_divider(&self) -> bool {
293320
false
294321
}
295322

296-
fn setup(&self, comp: &$COMP) {
323+
unsafe fn setup(&self, comp: &mut $COMP) {
324+
comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) })
325+
}
326+
}
327+
328+
impl NegativeInput<$COMP> for dac::$channel<{ dac::$MODE }, $ED> {
329+
const USE_VREFINT: bool = false;
330+
331+
fn use_resistor_divider(&self) -> bool {
332+
false
333+
}
334+
335+
unsafe fn setup(&self, comp: &mut $COMP) {
297336
comp.csr().modify(|_, w| unsafe { w.inmsel().bits($bits) })
298337
}
299338
}
@@ -302,8 +341,10 @@ macro_rules! dac_input_helper {
302341

303342
macro_rules! dac_input {
304343
($COMP:ident: $channel:ident, $bits:expr) => {
305-
dac_input_helper!($COMP: $channel, M_MIX_SIG, $bits);
306-
dac_input_helper!($COMP: $channel, M_INT_SIG, $bits);
344+
dac_input_helper!($COMP: $channel, M_MIX_SIG, dac::Enabled, $bits);
345+
dac_input_helper!($COMP: $channel, M_MIX_SIG, dac::WaveGenerator, $bits);
346+
dac_input_helper!($COMP: $channel, M_INT_SIG, dac::Enabled, $bits);
347+
dac_input_helper!($COMP: $channel, M_INT_SIG, dac::WaveGenerator, $bits);
307348
};
308349
}
309350

@@ -371,37 +412,46 @@ pub struct Comparator<C, ED> {
371412

372413
pub trait ComparatorExt<COMP> {
373414
/// Initializes a comparator
374-
fn comparator<P: PositiveInput<COMP>, N: NegativeInput<COMP>>(
415+
fn comparator<PP, NP, P, N>(
375416
self,
376-
positive_input: P,
377-
negative_input: N,
417+
positive_input: PP,
418+
negative_input: NP,
378419
config: Config,
379420
clocks: &Clocks,
380-
) -> Comparator<COMP, Disabled>;
421+
) -> Comparator<COMP, Disabled>
422+
where
423+
PP: FrozenPin<P> + PositiveInput<COMP>,
424+
NP: FrozenPin<N> + NegativeInput<COMP>;
381425
}
382426

383427
macro_rules! impl_comparator {
384428
($COMP:ty, $comp:ident, $Event:expr) => {
385429
impl ComparatorExt<$COMP> for $COMP {
386-
fn comparator<P: PositiveInput<$COMP>, N: NegativeInput<$COMP>>(
387-
self,
388-
positive_input: P,
389-
negative_input: N,
430+
fn comparator<PP, NP, P, N>(
431+
mut self,
432+
positive_input: PP,
433+
negative_input: NP,
390434
config: Config,
391435
clocks: &Clocks,
392-
) -> Comparator<$COMP, Disabled> {
393-
positive_input.setup(&self);
394-
negative_input.setup(&self);
436+
) -> Comparator<$COMP, Disabled>
437+
where
438+
PP: FrozenPin<P> + PositiveInput<$COMP>,
439+
NP: FrozenPin<N> + NegativeInput<$COMP>
440+
{
441+
unsafe {
442+
positive_input.borrow().setup(&mut self);
443+
negative_input.borrow().setup(&mut self);
444+
}
395445
// Delay for scaler voltage bridge initialization for certain negative inputs
396446
let voltage_scaler_delay = clocks.sys_clk.raw() / (1_000_000 / 200); // 200us
397447
cortex_m::asm::delay(voltage_scaler_delay);
398448
self.csr().modify(|_, w| unsafe {
399449
w.hyst()
400450
.bits(config.hysteresis as u8)
401451
.scalen()
402-
.bit(N::USE_VREFINT)
452+
.bit(NP::USE_VREFINT)
403453
.brgen()
404-
.bit(negative_input.use_resistor_divider())
454+
.bit(negative_input.borrow().use_resistor_divider())
405455
.pol()
406456
.bit(config.inverted)
407457
});
@@ -415,13 +465,17 @@ macro_rules! impl_comparator {
415465

416466
impl Comparator<$COMP, Disabled> {
417467
/// Initializes a comparator
418-
pub fn $comp<P: PositiveInput<$COMP>, N: NegativeInput<$COMP>>(
468+
pub fn $comp<PP, NP, P, N>(
419469
comp: $COMP,
420-
positive_input: P,
421-
negative_input: N,
470+
positive_input: PP,
471+
negative_input: NP,
422472
config: Config,
423473
clocks: &Clocks,
424-
) -> Self {
474+
) -> Self
475+
where
476+
PP: FrozenPin<P> + PositiveInput<$COMP>,
477+
NP: FrozenPin<N> + NegativeInput<$COMP>
478+
{
425479
comp.comparator(positive_input, negative_input, config, clocks)
426480
}
427481

0 commit comments

Comments
 (0)