Skip to content

Commit 56d66ff

Browse files
committed
Add hrtim Dac and adc trigger tests
1 parent 4c8b953 commit 56d66ff

File tree

1 file changed

+140
-23
lines changed

1 file changed

+140
-23
lines changed

tests/nucleo-g474_hrtim.rs

Lines changed: 140 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,21 @@ mod common;
1212

1313
use common::test_pwm;
1414
use fugit::{ExtU32, HertzU32, MicrosDurationU32};
15-
use stm32_hrtim::compare_register::HrCompareRegister;
16-
use stm32_hrtim::control::HrPwmControl;
17-
use stm32_hrtim::deadtime::DeadtimeConfig;
18-
use stm32_hrtim::output::HrOutput;
19-
use stm32_hrtim::timer::HrTimer;
20-
use stm32_hrtim::{HrParts, HrPwmAdvExt as _, Pscl64};
21-
use stm32g4xx_hal::delay::SYSTDelayExt;
22-
use stm32g4xx_hal::gpio::{GpioExt, PinExt};
23-
use stm32g4xx_hal::hrtim::HrControltExt;
24-
use stm32g4xx_hal::pwr::PwrExt;
25-
use stm32g4xx_hal::rcc::{self, Rcc, RccExt};
15+
use stm32_hrtim::{
16+
compare_register::HrCompareRegister,
17+
control::HrPwmControl,
18+
deadtime::DeadtimeConfig,
19+
output::{HrOutput, ToHrOut},
20+
timer::HrTimer,
21+
DacResetOnCounterReset, DacStepOnCmp2, HrParts, HrPwmAdvExt as _, Pscl64,
22+
};
23+
use stm32g4xx_hal::{
24+
delay::SYSTDelayExt,
25+
gpio::{GpioExt, PinExt},
26+
hrtim::{HrControltExt, HrtimPin},
27+
pwr::PwrExt,
28+
rcc::{self, Rcc, RccExt},
29+
};
2630

2731
use hal::stm32;
2832
use stm32g4xx_hal as hal;
@@ -35,6 +39,10 @@ type Timer = crate::common::Timer<CYCLES_PER_US>;
3539
#[embedded_test::tests]
3640
mod tests {
3741
use embedded_hal::delay::DelayNs;
42+
use stm32g4xx_hal::{
43+
adc::{self, temperature::Temperature, AdcClaim, AdcCommonExt},
44+
dac::{self, DacExt, DacOut, SawtoothConfig},
45+
};
3846

3947
#[test]
4048
fn simple() {
@@ -63,7 +71,7 @@ mod tests {
6371
..
6472
},
6573
mut hr_control,
66-
) = setup(pin, None, dp.HRTIM_TIMA, dp.HRTIM_COMMON, &mut rcc);
74+
) = setup_hrtim(pin, None, dp.HRTIM_TIMA, dp.HRTIM_COMMON, &mut rcc);
6775

6876
cr1.set_duty(PERIOD / 2);
6977
out.enable_rst_event(&cr1); // Set low on compare match with cr1
@@ -99,6 +107,104 @@ mod tests {
99107

100108
deadtime_test(1, 68);
101109
}
110+
111+
/// Test adc trigger and DAC trigger
112+
///
113+
/// Setup hrtim with DAC to generate a Sawtooth waveform. Use a compare register to accurately
114+
/// place the measurement point.
115+
///
116+
/// | /| /| /|
117+
/// | * / | / | / |
118+
/// | * / | / | / |
119+
/// | X | / | / |
120+
/// | / * | / | / |
121+
/// |/ * |/ |/ |
122+
/// |--->*
123+
/// cr3 indicates where in waveform to trigger ADC
124+
///
125+
#[test]
126+
fn adc_trigger() {
127+
use super::*;
128+
129+
let mut cp = stm32::CorePeripherals::take().unwrap();
130+
let dp = stm32::Peripherals::take().unwrap();
131+
132+
// Set system frequency to 16MHz * 15/1/2 = 120MHz
133+
// This would lead to HrTim running at 120MHz * 32 = 3.84...
134+
let mut rcc = setup_rcc_120MHz(dp.PWR, dp.RCC);
135+
assert_eq!(rcc.clocks.sys_clk, F_SYS);
136+
let mut delay = cp.SYST.delay(&rcc.clocks);
137+
138+
let gpioa = dp.GPIOA.split(&mut rcc);
139+
let pa1 = gpioa.pa1.into_analog();
140+
let pa4 = gpioa.pa4;
141+
let pin = gpioa.pa8;
142+
143+
let (mut hrtimer, mut hr_control) =
144+
setup_hrtim(pin, None, dp.HRTIM_TIMA, dp.HRTIM_COMMON, &mut rcc);
145+
146+
hrtimer.cr1.set_duty(PERIOD / 2);
147+
hrtimer.out.enable_rst_event(&hrtimer.cr1); // Set low on compare match with cr1
148+
hrtimer.out.enable_set_event(&hrtimer.timer); // Set high at new period
149+
150+
let dac_step_per_trigger = 16;
151+
let cr2_ticks_per_dac_trigger = dac_step_per_trigger;
152+
hrtimer.cr2.set_duty(cr2_ticks_per_dac_trigger);
153+
let dac1ch1 = dp.DAC1.constrain(pa4, &mut rcc);
154+
let mut ref_dac = dac1ch1.enable_sawtooth_generator(
155+
SawtoothConfig::with_slope(dac::CountingDirection::Decrement, dac_step_per_trigger)
156+
.inc_trigger(&hrtimer.cr2)
157+
.reset_trigger(&hrtimer.timer),
158+
&mut rcc,
159+
);
160+
161+
hr_control.adc_trigger1.enable_source(&hrtimer.cr3);
162+
163+
defmt::debug!("Setup Adc1");
164+
let mut adc12_common = dp
165+
.ADC12_COMMON
166+
.claim(adc::config::ClockMode::AdcHclkDiv4, &mut rcc);
167+
let mut adc = adc12_common.claim(dp.ADC1, &mut delay);
168+
169+
adc.set_external_trigger((
170+
adc::config::TriggerMode::RisingEdge,
171+
(&hr_control.adc_trigger1).into(),
172+
));
173+
adc12_common.enable_temperature();
174+
adc.set_continuous(hal::adc::config::Continuous::Discontinuous);
175+
adc.reset_sequence();
176+
adc.configure_channel(
177+
&pa1,
178+
adc::config::Sequence::One,
179+
adc::config::SampleTime::Cycles_12_5,
180+
);
181+
let mut adc = adc.enable().into_dynamic_adc();
182+
hrtimer.timer.start(&mut hr_control.control);
183+
184+
ref_dac.set_value(4095);
185+
186+
defmt::debug!("Awaiting first dac rst trigger");
187+
while ref_dac.get_value() == 0 {}
188+
189+
//out.enable();
190+
191+
adc.start_conversion();
192+
193+
for _ in 0..2 {
194+
let margin = 256;
195+
for sampling_point in (margin..(PERIOD - margin)).step_by(16) {
196+
hrtimer.cr3.set_duty(sampling_point); // Set sampling point
197+
let sampling_point_as_12bit = sampling_point >> 4;
198+
199+
// Dac generates a sawtooth with negative slope which starts at 4095 every new period
200+
let expected_dac_value = 4095 - sampling_point_as_12bit;
201+
adc.wait_for_conversion_sequence();
202+
let adc_value = adc.current_sample();
203+
let diff = adc_value.abs_diff(expected_dac_value);
204+
assert!(diff < 20);
205+
}
206+
}
207+
}
102208
}
103209

104210
#[allow(non_snake_case)]
@@ -120,16 +226,26 @@ fn setup_rcc_120MHz(pwr: stm32::PWR, rcc: stm32::RCC) -> Rcc {
120226
)
121227
}
122228

123-
fn setup<P: stm32g4xx_hal::hrtim::HrtimPin<stm32::HRTIM_TIMA>>(
229+
fn setup_hrtim<P>(
124230
pins: P,
125231
deadtime_cfg: Option<DeadtimeConfig>,
126232
hrtim_tima: stm32::HRTIM_TIMA,
127233
hrtim_common: stm32::HRTIM_COMMON,
128234
rcc: &mut Rcc,
129235
) -> (
130-
HrParts<stm32::HRTIM_TIMA, Pscl64, P::Out<Pscl64>>,
236+
HrParts<
237+
stm32::HRTIM_TIMA,
238+
Pscl64,
239+
<P as ToHrOut<stm32::HRTIM_TIMA, DacResetOnCounterReset, DacStepOnCmp2>>::Out<Pscl64>,
240+
DacResetOnCounterReset,
241+
DacStepOnCmp2,
242+
>,
131243
HrPwmControl,
132-
) {
244+
)
245+
where
246+
P: HrtimPin<stm32::HRTIM_TIMA>
247+
+ ToHrOut<stm32::HRTIM_TIMA, DacResetOnCounterReset, DacStepOnCmp2>,
248+
{
133249
use stm32g4xx_hal::hrtim::HrPwmBuilderExt;
134250
let (hr_control, ..) = hrtim_common.hr_control(rcc).wait_for_calibration();
135251
let mut hr_control = hr_control.constrain();
@@ -138,19 +254,20 @@ fn setup<P: stm32g4xx_hal::hrtim::HrtimPin<stm32::HRTIM_TIMA>>(
138254
// With a period of 60_000 set, this would be 60MHz/60_000 = 1kHz
139255
let prescaler = Pscl64;
140256

141-
let mut hr_tim_builder: stm32_hrtim::HrPwmBuilder<
142-
stm32::HRTIM_TIMA,
143-
Pscl64,
144-
stm32_hrtim::PreloadSource,
145-
P,
146-
> = hrtim_tima
257+
let mut hr_tim_builder = hrtim_tima
147258
.pwm_advanced(pins)
148259
.prescaler(prescaler)
149260
.period(PERIOD);
261+
150262
if let Some(dt) = deadtime_cfg {
151263
hr_tim_builder = hr_tim_builder.deadtime(dt);
152264
}
153-
(hr_tim_builder.finalize(&mut hr_control), hr_control)
265+
(
266+
hr_tim_builder
267+
.dac_trigger_cfg(DacResetOnCounterReset, DacStepOnCmp2)
268+
.finalize(&mut hr_control),
269+
hr_control,
270+
)
154271
}
155272

156273
fn deadtime_test(deadtime_rising_us: u32, deadtime_falling_us: u32) {
@@ -189,7 +306,7 @@ fn deadtime_test(deadtime_rising_us: u32, deadtime_falling_us: u32) {
189306
..
190307
},
191308
mut hr_control,
192-
) = setup(
309+
) = setup_hrtim(
193310
(pin, complementary_pin),
194311
Some(deadtime_cfg),
195312
dp.HRTIM_TIMA,

0 commit comments

Comments
 (0)