Skip to content

Commit abbfe68

Browse files
committed
Add more tests
1 parent 910046d commit abbfe68

File tree

1 file changed

+190
-43
lines changed

1 file changed

+190
-43
lines changed

tests/tests.rs

Lines changed: 190 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,51 @@
44
#[path = "../examples/utils/mod.rs"]
55
mod utils;
66

7-
use utils::logger::println;
7+
use utils::logger::debug;
88

99
use core::ops::FnMut;
1010
use core::result::Result;
11-
use fugit::{ExtU32, MicrosDurationU32};
12-
use hal::delay::{DelayExt, SystDelay};
11+
use fugit::{ExtU32, HertzU32, MicrosDurationU32};
12+
use hal::delay::DelayExt;
1313
use hal::stm32;
1414
use stm32g4xx_hal as hal;
1515

16+
pub const F_SYS: HertzU32 = HertzU32::MHz(16);
17+
pub const CYCLES_PER_US: u32 = F_SYS.raw() / 1_000_000;
18+
19+
pub fn enable_timer(cp: &mut stm32::CorePeripherals) {
20+
cp.DCB.enable_trace();
21+
cp.DWT.enable_cycle_counter();
22+
}
23+
24+
pub fn now() -> MicrosDurationU32 {
25+
(stm32::DWT::cycle_count() / CYCLES_PER_US).micros()
26+
}
27+
1628
#[defmt_test::tests]
1729
mod tests {
1830
use embedded_hal::{
31+
delay::DelayNs,
1932
digital::{InputPin, OutputPin},
2033
pwm::SetDutyCycle,
2134
};
35+
use fixed::types::I1F15;
2236
use fugit::RateExtU32;
2337
use stm32g4xx_hal::{
38+
adc::{self, AdcClaim, Temperature, Vref},
39+
cordic::{
40+
op::{dynamic::Mode, Magnitude, SinCos, Sqrt},
41+
prec::P60,
42+
scale::N0,
43+
types::{Q15, Q31},
44+
Ext,
45+
},
46+
dac::{DacExt, DacOut},
2447
delay::SYSTDelayExt,
2548
gpio::{GpioExt, AF6},
2649
pwm::PwmExt,
2750
rcc::RccExt,
51+
signature::{VrefCal, VDDA_CALIB},
2852
stm32::GPIOA,
2953
};
3054

@@ -37,6 +61,7 @@ mod tests {
3761
let dp = unsafe { stm32::Peripherals::steal() };
3862
let mut rcc = dp.RCC.constrain();
3963
let mut delay = cp.SYST.delay(&rcc.clocks);
64+
defmt::dbg!(rcc.clocks.sys_clk);
4065

4166
let gpioa = dp.GPIOA.split(&mut rcc);
4267
let mut pin = gpioa.pa8.into_push_pull_output();
@@ -46,15 +71,15 @@ mod tests {
4671
assert!(pin.is_high().unwrap());
4772
{
4873
let gpioa = unsafe { &*GPIOA::PTR };
49-
assert!(!is_pa8_low(gpioa));
74+
assert!(!is_pax_low(gpioa, 8));
5075
}
5176

5277
pin.set_low().unwrap();
5378
delay.delay(1.millis()); // Give the pin plenty of time to go low
5479
assert!(pin.is_low().unwrap());
5580
{
5681
let gpioa = unsafe { &*GPIOA::PTR };
57-
assert!(is_pa8_low(gpioa));
82+
assert!(is_pax_low(gpioa, 8));
5883
}
5984
}
6085

@@ -82,15 +107,15 @@ mod tests {
82107
assert!(pin.is_high().unwrap());
83108
{
84109
let gpioa = unsafe { &*GPIOA::PTR };
85-
assert!(!is_pa8_low(gpioa));
110+
assert!(!is_pax_low(gpioa, 8));
86111
}
87112

88113
pin.set_low().unwrap();
89114
delay.delay(1.millis()); // Give the pin plenty of time to go low
90115
assert!(pin.is_low().unwrap());
91116
{
92117
let gpioa = unsafe { &*GPIOA::PTR };
93-
assert!(is_pa8_low(gpioa));
118+
assert!(is_pax_low(gpioa, 8));
94119
}
95120
}
96121

@@ -99,10 +124,12 @@ mod tests {
99124
use super::*;
100125

101126
// TODO: Is it ok to steal these?
102-
let cp = unsafe { stm32::CorePeripherals::steal() };
127+
let mut cp = unsafe { stm32::CorePeripherals::steal() };
103128
let dp = unsafe { stm32::Peripherals::steal() };
129+
enable_timer(&mut cp);
130+
104131
let mut rcc = dp.RCC.constrain();
105-
let mut delay = cp.SYST.delay(&rcc.clocks);
132+
assert_eq!(rcc.clocks.sys_clk, F_SYS);
106133

107134
let gpioa = dp.GPIOA.split(&mut rcc);
108135
let pin: stm32g4xx_hal::gpio::gpioa::PA8<stm32g4xx_hal::gpio::Alternate<AF6>> =
@@ -115,75 +142,195 @@ mod tests {
115142

116143
let gpioa = unsafe { &*GPIOA::PTR };
117144

118-
//let get_pin_state = || unsafe { (0x4800_0004 as *const u32).read_volatile() };
119-
120-
// TODO: This is a very bad way to measure time
121-
let min: MicrosDurationU32 = 490u32.micros(); // Some extra on min for cpu overhead
145+
let min: MicrosDurationU32 = 495u32.micros();
122146
let max: MicrosDurationU32 = 505u32.micros();
123147

124-
{
125-
println!("Awaiting first rising edge...");
126-
let duration_until_lo = await_lo(&gpioa, &mut delay, max).unwrap();
127-
println!("Low..., Waited ~{} until low", duration_until_lo);
128-
let lo_duration = await_hi(&gpioa, &mut delay, max).unwrap();
129-
println!("High..., Low half period: {}", lo_duration);
130-
}
148+
debug!("Awaiting first rising edge...");
149+
let duration_until_lo = await_lo(&gpioa, max).unwrap();
150+
let first_lo_duration = await_hi(&gpioa, max).unwrap();
151+
152+
let mut hi_duration = 0.micros();
153+
let mut lo_duration = 0.micros();
131154

132155
for _ in 0..10 {
133-
// Make sure the timer half periods are within 490-505us
156+
// Make sure the timer half periods are within 495-505us
157+
158+
hi_duration = await_lo(&gpioa, max).unwrap();
159+
assert!(
160+
hi_duration > min && hi_duration < max,
161+
"hi: {} < {} < {}",
162+
min,
163+
hi_duration,
164+
max
165+
);
166+
167+
lo_duration = await_hi(&gpioa, max).unwrap();
168+
assert!(
169+
lo_duration > min && lo_duration < max,
170+
"lo: {} < {} < {}",
171+
min,
172+
lo_duration,
173+
max
174+
);
175+
}
176+
177+
// Prints deferred until here to not mess up timing
178+
debug!("Waited ~{} until low", duration_until_lo);
179+
debug!("First low half period: {}", first_lo_duration);
134180

135-
let hi_duration = await_lo(&gpioa, &mut delay, max).unwrap();
136-
println!("Low..., High half period: {}", hi_duration);
137-
assert!(hi_duration > min, "{} > {}", hi_duration, min);
181+
debug!("High half period: {}", hi_duration);
182+
debug!("Low half period: {}", lo_duration);
138183

139-
let lo_duration = await_hi(&gpioa, &mut delay, max).unwrap();
140-
println!("High..., Low half period: {}", lo_duration);
141-
assert!(lo_duration > min, "{} > {}", lo_duration, min);
184+
debug!("Done!");
185+
186+
pwm.disable();
187+
}
188+
189+
#[test]
190+
fn cordic() {
191+
fn is_almost_equals(a: f32, b: f32) -> bool {
192+
(a - b).abs() < 0.001
142193
}
143194

144-
println!("Done!");
145-
for i in (0..5).rev() {
146-
println!("{}", i);
147-
delay.delay(1000.millis());
195+
use super::*;
196+
197+
let dp = unsafe { stm32::Peripherals::steal() };
198+
let mut rcc = dp.RCC.constrain();
199+
200+
let mut cordic = dp
201+
.CORDIC
202+
.constrain(&mut rcc)
203+
.freeze::<Q15, Q31, P60, SinCos>(); // 16 bit arguments, 32 bit results, compute sine and cosine, 60 iterations
204+
205+
// static operation (zero overhead)
206+
207+
cordic.start(I1F15::from_num(-0.25 /* -45 degreees */));
208+
209+
let (sin, cos) = cordic.result();
210+
211+
debug!("sin: {}, cos: {}", sin.to_num::<f32>(), cos.to_num::<f32>());
212+
assert!(is_almost_equals(sin.to_num::<f32>(), -0.707));
213+
assert!(is_almost_equals(cos.to_num::<f32>(), 0.707));
214+
215+
// dynamic operation
216+
217+
let mut cordic = cordic.into_dynamic();
218+
219+
let sqrt = cordic.run::<Sqrt<N0>>(I1F15::from_num(0.25));
220+
debug!("sqrt: {}", sqrt.to_num::<f32>());
221+
assert!(is_almost_equals(sqrt.to_num::<f32>(), 0.5));
222+
let magnitude = cordic.run::<Magnitude>((I1F15::from_num(0.25), I1F15::from_num(0.5)));
223+
debug!("magnitude: {}", magnitude.to_num::<f32>());
224+
assert!(is_almost_equals(magnitude.to_num::<f32>(), 0.559));
225+
}
226+
227+
#[test]
228+
fn adc() {
229+
use super::*;
230+
231+
// TODO: Is it ok to steal these?
232+
let cp = unsafe { stm32::CorePeripherals::steal() };
233+
let dp = unsafe { stm32::Peripherals::steal() };
234+
let rcc = dp.RCC.constrain();
235+
let mut delay = cp.SYST.delay(&rcc.clocks);
236+
237+
let mut adc = dp
238+
.ADC1
239+
.claim(adc::ClockSource::SystemClock, &rcc, &mut delay, true);
240+
241+
adc.enable_temperature(&dp.ADC12_COMMON);
242+
adc.enable_vref(&dp.ADC12_COMMON);
243+
let sample_time = adc::config::SampleTime::Cycles_640_5;
244+
245+
let vref = adc.convert(&Vref, sample_time);
246+
let vref_cal = VrefCal::get().read();
247+
let vdda = VDDA_CALIB * vref_cal as u32 / vref as u32;
248+
debug!("vdda: {}mV", vdda);
249+
assert!((3200..3400).contains(&vdda));
250+
251+
let vref = Vref::sample_to_millivolts_ext(vref, vdda, adc::config::Resolution::Twelve);
252+
debug!("vref: {}mV", vref);
253+
assert!((1182..1232).contains(&vref)); // From G474 datasheet
254+
255+
let temperature_reading = adc.convert(&Temperature, sample_time);
256+
let temp = Temperature::temperature_to_degrees_centigrade(
257+
temperature_reading,
258+
vdda as f32 / 1000.,
259+
adc::config::Resolution::Twelve,
260+
);
261+
debug!("temp: {}°C", temp);
262+
assert!((20.0..30.0).contains(&temp), "20.0 < {} < 30.0", temp);
263+
}
264+
265+
// TODO: This does not seem to work
266+
#[test]
267+
fn dac() {
268+
use super::*;
269+
270+
// TODO: Is it ok to steal these?
271+
let cp = unsafe { stm32::CorePeripherals::steal() };
272+
let dp = unsafe { stm32::Peripherals::steal() };
273+
let mut rcc = dp.RCC.constrain();
274+
let mut delay = cp.SYST.delay(&rcc.clocks);
275+
276+
let gpioa = dp.GPIOA.split(&mut rcc);
277+
let dac1ch1 = dp.DAC1.constrain(gpioa.pa4, &mut rcc);
278+
279+
let gpioa = unsafe { &*GPIOA::PTR };
280+
281+
// dac_manual will have its value set manually
282+
let mut dac = dac1ch1.calibrate_buffer(&mut delay).enable();
283+
284+
dac.set_value(0);
285+
delay.delay_ms(100);
286+
assert!(is_pax_low(&gpioa, 4));
287+
288+
/*for i in (0..=4095).step_by(10) {
289+
dac.set_value(i);
290+
delay.delay_ms(1);
291+
defmt::println!("i: {}, is_pax_low: {}", i, gpioa.idr().read().bits());
148292
}
149293
150-
pwm.disable();
294+
delay.delay_ms(100);
295+
assert!(!is_pax_low(&gpioa, 4)); // TODO: <---- Why does this not work?
296+
*/
151297
}
152298
}
153299

154-
fn is_pa8_low(gpioa: &stm32::gpioa::RegisterBlock) -> bool {
155-
gpioa.idr().read().idr(8).is_low()
300+
fn is_pax_low(gpioa: &stm32::gpioa::RegisterBlock, x: u8) -> bool {
301+
gpioa.idr().read().idr(x).is_low()
156302
}
157303

158304
#[derive(Debug, defmt::Format)]
159305
struct ErrorTimedOut;
160306

161307
fn await_lo(
162308
gpioa: &stm32::gpioa::RegisterBlock,
163-
delay: &mut SystDelay,
164309
timeout: MicrosDurationU32,
165310
) -> Result<MicrosDurationU32, ErrorTimedOut> {
166-
await_p(|| is_pa8_low(gpioa), delay, timeout)
311+
await_p(|| is_pax_low(gpioa, 8), timeout)
167312
}
168313

169314
fn await_hi(
170315
gpioa: &stm32::gpioa::RegisterBlock,
171-
delay: &mut SystDelay,
172316
timeout: MicrosDurationU32,
173317
) -> Result<MicrosDurationU32, ErrorTimedOut> {
174-
await_p(|| !is_pa8_low(gpioa), delay, timeout)
318+
await_p(|| !is_pax_low(gpioa, 8), timeout)
175319
}
176320

177321
fn await_p(
178322
mut p: impl FnMut() -> bool,
179-
delay: &mut SystDelay,
180323
timeout: MicrosDurationU32,
181324
) -> Result<MicrosDurationU32, ErrorTimedOut> {
182-
for i in 0..timeout.ticks() {
325+
let before = now();
326+
327+
loop {
328+
let passed_time = now() - before;
183329
if p() {
184-
return Ok(i.micros());
330+
return Ok(passed_time);
331+
}
332+
if passed_time > timeout {
333+
return Err(ErrorTimedOut);
185334
}
186-
delay.delay(1_u32.micros());
187335
}
188-
Err(ErrorTimedOut)
189336
}

0 commit comments

Comments
 (0)