Skip to content

Commit 723dce4

Browse files
committed
Add timer test
1 parent 62027bd commit 723dce4

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

testsuite/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ harness = false
1919
name = "rcc"
2020
harness = false
2121

22+
[[test]]
23+
name = "timer"
24+
harness = false
25+
2226
[[test]]
2327
name = "gpio_input"
2428
harness = false

testsuite/tests/timer.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use core::sync::atomic::{AtomicBool, Ordering};
5+
6+
use defmt_rtt as _;
7+
use panic_probe as _;
8+
9+
use stm32f3xx_hal as hal;
10+
11+
use hal::rcc::{Clocks, APB1};
12+
use hal::timer::{Event, Instance, MonoTimer, Timer};
13+
use hal::{interrupt, pac, prelude::*};
14+
15+
use pac::TIM2;
16+
17+
struct State {
18+
timer: Option<Timer<TIM2>>,
19+
mono_timer: MonoTimer,
20+
clocks: Clocks,
21+
apb1: APB1,
22+
}
23+
24+
static INTERRUPT_FIRED: AtomicBool = AtomicBool::new(false);
25+
26+
#[defmt_test::tests]
27+
mod tests {
28+
use super::*;
29+
use defmt::{self, assert, unwrap};
30+
use hal::time::fixed_point::FixedPoint;
31+
32+
#[init]
33+
fn init() -> State {
34+
let mut cp = unwrap!(pac::CorePeripherals::take());
35+
let dp = unwrap!(pac::Peripherals::take());
36+
37+
let mut rcc = dp.RCC.constrain();
38+
let mut flash = dp.FLASH.constrain();
39+
let clocks = rcc.cfgr.freeze(&mut flash.acr);
40+
41+
// Let's use a timer, which is avaliable for every chip
42+
let timer = Timer::new(dp.TIM2, 1.Hz(), clocks, &mut rcc.apb1);
43+
let mono_timer = MonoTimer::new(cp.DWT, clocks, &mut cp.DCB);
44+
45+
assert!(mono_timer.frequency() == clocks.hclk());
46+
47+
unsafe { cortex_m::peripheral::NVIC::unmask(timer.nvic()) };
48+
49+
State {
50+
timer: Some(timer),
51+
mono_timer,
52+
clocks,
53+
apb1: rcc.apb1,
54+
}
55+
}
56+
57+
#[test]
58+
fn test_stop_and_free(state: &mut State) {
59+
let timer = state.timer.take().unwrap().free();
60+
61+
let timer = Timer::new(timer, 100.Hz(), state.clocks, &mut state.apb1);
62+
63+
state.timer = Some(timer);
64+
}
65+
66+
#[test]
67+
fn test_delay(state: &mut State) {
68+
let mut timer = unwrap!(state.timer.take());
69+
defmt::trace!("{}", state.mono_timer);
70+
let freqcyc = state.mono_timer.frequency().integer();
71+
72+
let instant = state.mono_timer.now();
73+
timer.start(1.Hz());
74+
assert!(!timer.is_event_triggered(Event::Update));
75+
unwrap!(nb::block!(timer.wait()).ok());
76+
let elapsed = instant.elapsed();
77+
78+
defmt::info!("elapsed: {}", elapsed);
79+
// TODO: Test multiple frequencies and change the cycle counter window to a percentage
80+
// to measure the overhead of start?
81+
assert!(((freqcyc - 1000)..(freqcyc + 1000)).contains(&elapsed));
82+
83+
state.timer = Some(timer);
84+
}
85+
86+
// TODO(Sh3Rm4n): For that we have to introduce a new API. (Maybe Centihertz or Something?)
87+
// #[test]
88+
// fn test_delay_longer_then_second(state: &mut State) {
89+
90+
// }
91+
92+
#[test]
93+
fn test_interrupt(state: &mut State) {
94+
let mut timer = unwrap!(state.timer.take());
95+
96+
assert!(!INTERRUPT_FIRED.load(Ordering::SeqCst));
97+
timer.enable_interrupt(Event::Update);
98+
timer.start(100_000.Hz());
99+
100+
while !INTERRUPT_FIRED.load(Ordering::SeqCst) {}
101+
102+
assert!(timer.is_event_triggered(Event::Update));
103+
timer.clear_event(Event::Update);
104+
assert!(!timer.is_event_triggered(Event::Update));
105+
106+
state.timer = Some(timer);
107+
}
108+
}
109+
110+
#[interrupt]
111+
fn TIM2() {
112+
INTERRUPT_FIRED.store(true, Ordering::SeqCst);
113+
114+
// Make it easy on ourselfs and just disable all interrupts.
115+
// This way, the interrupt rountine dooes not have to have access to the timer peripheral,
116+
// which would mean to access the internally managed state of the test module,
117+
// which can't be accessed right now.
118+
//
119+
// This is all needed, to clear the fired interrupt.
120+
assert!(cortex_m::peripheral::NVIC::is_active(
121+
<pac::TIM2 as Instance>::INTERRUPT
122+
));
123+
cortex_m::peripheral::NVIC::mask(<pac::TIM2 as Instance>::INTERRUPT);
124+
}

0 commit comments

Comments
 (0)