From dbf2e1232b4ecbeb2ff15e84c5ba1c98d5317457 Mon Sep 17 00:00:00 2001 From: Sh3Rm4n Date: Tue, 10 Aug 2021 21:52:47 +0200 Subject: [PATCH] Add cancel and more duartion tests --- testsuite/Cargo.toml | 1 + testsuite/tests/timer.rs | 75 +++++++++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 21 deletions(-) diff --git a/testsuite/Cargo.toml b/testsuite/Cargo.toml index 829f972a1..8881170dd 100644 --- a/testsuite/Cargo.toml +++ b/testsuite/Cargo.toml @@ -55,6 +55,7 @@ enumset = { version = "1.0.6" } stm32f3xx-hal = { path = "..", features = ["rt", "defmt-trace", "can", "ld", "enumset"]} panic-probe = { version = "0.2.0", features = ["print-defmt"] } nb = "1.0.0" +num-traits = { version = "0.2.14", default-features = false } [features] # enable all defmt logging levels diff --git a/testsuite/tests/timer.rs b/testsuite/tests/timer.rs index 25146e1a1..4a85d5c08 100644 --- a/testsuite/tests/timer.rs +++ b/testsuite/tests/timer.rs @@ -4,13 +4,18 @@ use core::sync::atomic::{AtomicBool, Ordering}; use defmt_rtt as _; +use hal::delay::Delay; use panic_probe as _; +use num_traits::float::FloatCore; + use stm32f3xx_hal as hal; +use hal::hal::timer::Cancel; use hal::interrupts::InterruptNumber; use hal::rcc::{Clocks, APB1}; -use hal::timer::{Event, MonoTimer, Timer}; +use hal::time::{duration, fixed_point::FixedPoint}; +use hal::timer::{AlreadyCancled, Event, MonoTimer, Timer}; use hal::{interrupt, pac, prelude::*}; use pac::TIM2; @@ -20,6 +25,7 @@ struct State { mono_timer: MonoTimer, clocks: Clocks, apb1: APB1, + delay: Delay, } static INTERRUPT_FIRED: AtomicBool = AtomicBool::new(false); @@ -28,7 +34,6 @@ static INTERRUPT_FIRED: AtomicBool = AtomicBool::new(false); mod tests { use super::*; use defmt::{self, assert, unwrap}; - use hal::time::fixed_point::FixedPoint; #[init] fn init() -> State { @@ -42,6 +47,7 @@ mod tests { // Let's use a timer, which is avaliable for every chip let timer = Timer::new(dp.TIM2, clocks, &mut rcc.apb1); let mono_timer = MonoTimer::new(cp.DWT, clocks, &mut cp.DCB); + let delay = Delay::new(cp.SYST, clocks); assert!(mono_timer.frequency() == clocks.hclk()); @@ -52,6 +58,7 @@ mod tests { mono_timer, clocks, apb1: rcc.apb1, + delay, } } @@ -70,31 +77,57 @@ mod tests { defmt::trace!("{}", state.mono_timer); let freqcyc = state.mono_timer.frequency().integer(); - let instant = state.mono_timer.now(); - timer.start(1.seconds()); - assert!(!timer.is_event_triggered(Event::Update)); - unwrap!(nb::block!(timer.wait()).ok()); - let elapsed = instant.elapsed(); + let durations: [duration::Generic; 5] = [ + 100.microseconds().into(), + 1.milliseconds().into(), + 100.milliseconds().into(), + 1.seconds().into(), + 10.seconds().into(), + // 100.seconds().into(), + ]; + + for dur in durations { + defmt::trace!("Duration: {}", defmt::Debug2Format(&dur)); + + timer.start(dur); + assert!(!timer.is_event_triggered(Event::Update)); + // call instant after start, becuase starting the timer is the last thing done in the + // start function, and therefor no overhead is added to the timing. + let instant = state.mono_timer.now(); + unwrap!(nb::block!(timer.wait()).ok()); + let elapsed = instant.elapsed(); + + defmt::debug!("elapsed: {}", elapsed); + + let ratio = f64::from(elapsed) / f64::from(freqcyc) + * (f64::from(*dur.scaling_factor().denominator())) + / f64::from(dur.integer()); + + let deviation = (ratio - 1.).abs(); + + // Deviation is high for smaller timer durations. Higher duratinons are pretty accurate. + // TODO: Maybe the allowed deviation should changed depending on the duration? + #[cfg(not(debug_assertions))] + defmt::assert!(deviation < 15e-4); + #[cfg(debug_assertions)] + defmt::assert!(deviation < 40e-4); + } + state.timer = Some(timer); + } - defmt::info!("elapsed: {}", elapsed); - // TODO: Test multiple frequencies and change the cycle counter window to a percentage - // to measure the overhead of start? + #[test] + fn test_cancel(state: &mut State) { + let mut timer = unwrap!(state.timer.take()); + defmt::trace!("{}", state.mono_timer); - // Differentiate between releas and debug build. - #[cfg(not(debug_assertions))] - assert!(((freqcyc - 500)..(freqcyc + 500)).contains(&elapsed)); - #[cfg(debug_assertions)] - assert!(((freqcyc - 2000)..(freqcyc + 2000)).contains(&elapsed)); + timer.start(10.milliseconds()); + state.delay.delay_ms(5u32); + assert!(matches!(timer.cancel(), Ok(()))); + assert!(matches!(timer.cancel(), Err(AlreadyCancled))); state.timer = Some(timer); } - // TODO(Sh3Rm4n): For that we have to introduce a new API. (Maybe Centihertz or Something?) - // #[test] - // fn test_delay_longer_then_second(state: &mut State) { - - // } - #[test] fn test_interrupt(state: &mut State) { let mut timer = unwrap!(state.timer.take());