Skip to content

Commit a82524e

Browse files
committed
Add hrtim Dac and adc trigger tests
1 parent fb8dc1a commit a82524e

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
@@ -10,17 +10,21 @@ mod common;
1010

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

2529
use hal::stm32;
2630
use stm32g4xx_hal as hal;
@@ -33,6 +37,10 @@ type Timer = crate::common::Timer<CYCLES_PER_US>;
3337
#[embedded_test::tests]
3438
mod tests {
3539
use embedded_hal::delay::DelayNs;
40+
use stm32g4xx_hal::{
41+
adc::{self, temperature::Temperature, AdcClaim, AdcCommonExt},
42+
dac::{self, DacExt, DacOut, SawtoothConfig},
43+
};
3644

3745
#[test]
3846
fn simple() {
@@ -61,7 +69,7 @@ mod tests {
6169
..
6270
},
6371
mut hr_control,
64-
) = setup(pin, None, dp.HRTIM_TIMA, dp.HRTIM_COMMON, &mut rcc);
72+
) = setup_hrtim(pin, None, dp.HRTIM_TIMA, dp.HRTIM_COMMON, &mut rcc);
6573

6674
cr1.set_duty(PERIOD / 2);
6775
out.enable_rst_event(&cr1); // Set low on compare match with cr1
@@ -97,6 +105,104 @@ mod tests {
97105

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

102208
#[allow(non_snake_case)]
@@ -118,16 +224,26 @@ fn setup_rcc_120MHz(pwr: stm32::PWR, rcc: stm32::RCC) -> Rcc {
118224
)
119225
}
120226

121-
fn setup<P: stm32g4xx_hal::hrtim::HrtimPin<stm32::HRTIM_TIMA>>(
227+
fn setup_hrtim<P>(
122228
pins: P,
123229
deadtime_cfg: Option<DeadtimeConfig>,
124230
hrtim_tima: stm32::HRTIM_TIMA,
125231
hrtim_common: stm32::HRTIM_COMMON,
126232
rcc: &mut Rcc,
127233
) -> (
128-
HrParts<stm32::HRTIM_TIMA, Pscl64, P::Out<Pscl64>>,
234+
HrParts<
235+
stm32::HRTIM_TIMA,
236+
Pscl64,
237+
<P as ToHrOut<stm32::HRTIM_TIMA, DacResetOnCounterReset, DacStepOnCmp2>>::Out<Pscl64>,
238+
DacResetOnCounterReset,
239+
DacStepOnCmp2,
240+
>,
129241
HrPwmControl,
130-
) {
242+
)
243+
where
244+
P: HrtimPin<stm32::HRTIM_TIMA>
245+
+ ToHrOut<stm32::HRTIM_TIMA, DacResetOnCounterReset, DacStepOnCmp2>,
246+
{
131247
use stm32g4xx_hal::hrtim::HrPwmBuilderExt;
132248
let (hr_control, ..) = hrtim_common.hr_control(rcc).wait_for_calibration();
133249
let mut hr_control = hr_control.constrain();
@@ -136,19 +252,20 @@ fn setup<P: stm32g4xx_hal::hrtim::HrtimPin<stm32::HRTIM_TIMA>>(
136252
// With a period of 60_000 set, this would be 60MHz/60_000 = 1kHz
137253
let prescaler = Pscl64;
138254

139-
let mut hr_tim_builder: stm32_hrtim::HrPwmBuilder<
140-
stm32::HRTIM_TIMA,
141-
Pscl64,
142-
stm32_hrtim::PreloadSource,
143-
P,
144-
> = hrtim_tima
255+
let mut hr_tim_builder = hrtim_tima
145256
.pwm_advanced(pins)
146257
.prescaler(prescaler)
147258
.period(PERIOD);
259+
148260
if let Some(dt) = deadtime_cfg {
149261
hr_tim_builder = hr_tim_builder.deadtime(dt);
150262
}
151-
(hr_tim_builder.finalize(&mut hr_control), hr_control)
263+
(
264+
hr_tim_builder
265+
.dac_trigger_cfg(DacResetOnCounterReset, DacStepOnCmp2)
266+
.finalize(&mut hr_control),
267+
hr_control,
268+
)
152269
}
153270

154271
fn deadtime_test(deadtime_rising_us: u32, deadtime_falling_us: u32) {
@@ -187,7 +304,7 @@ fn deadtime_test(deadtime_rising_us: u32, deadtime_falling_us: u32) {
187304
..
188305
},
189306
mut hr_control,
190-
) = setup(
307+
) = setup_hrtim(
191308
(pin, complementary_pin),
192309
Some(deadtime_cfg),
193310
dp.HRTIM_TIMA,

0 commit comments

Comments
 (0)