@@ -6,11 +6,16 @@ use core::sync::atomic::{AtomicBool, Ordering};
6
6
use defmt_rtt as _;
7
7
use panic_probe as _;
8
8
9
+ use num_traits:: float:: FloatCore ;
10
+
9
11
use stm32f3xx_hal as hal;
10
12
13
+ use hal:: delay:: Delay ;
14
+ use hal:: hal:: timer:: Cancel ;
11
15
use hal:: interrupts:: InterruptNumber ;
12
16
use hal:: rcc:: { Clocks , APB1 } ;
13
- use hal:: timer:: { Event , MonoTimer , Timer } ;
17
+ use hal:: time:: { duration, fixed_point:: FixedPoint } ;
18
+ use hal:: timer:: { AlreadyCancled , Event , MonoTimer , Timer } ;
14
19
use hal:: { interrupt, pac, prelude:: * } ;
15
20
16
21
use pac:: TIM2 ;
@@ -20,6 +25,7 @@ struct State {
20
25
mono_timer : MonoTimer ,
21
26
clocks : Clocks ,
22
27
apb1 : APB1 ,
28
+ delay : Delay ,
23
29
}
24
30
25
31
static INTERRUPT_FIRED : AtomicBool = AtomicBool :: new ( false ) ;
@@ -28,7 +34,6 @@ static INTERRUPT_FIRED: AtomicBool = AtomicBool::new(false);
28
34
mod tests {
29
35
use super :: * ;
30
36
use defmt:: { self , assert, unwrap} ;
31
- use hal:: time:: fixed_point:: FixedPoint ;
32
37
33
38
#[ init]
34
39
fn init ( ) -> State {
@@ -42,6 +47,7 @@ mod tests {
42
47
// Let's use a timer, which is avaliable for every chip
43
48
let timer = Timer :: new ( dp. TIM2 , clocks, & mut rcc. apb1 ) ;
44
49
let mono_timer = MonoTimer :: new ( cp. DWT , clocks, & mut cp. DCB ) ;
50
+ let delay = Delay :: new ( cp. SYST , clocks) ;
45
51
46
52
assert ! ( mono_timer. frequency( ) == clocks. hclk( ) ) ;
47
53
@@ -52,6 +58,7 @@ mod tests {
52
58
mono_timer,
53
59
clocks,
54
60
apb1 : rcc. apb1 ,
61
+ delay,
55
62
}
56
63
}
57
64
@@ -70,31 +77,57 @@ mod tests {
70
77
defmt:: trace!( "{}" , state. mono_timer) ;
71
78
let freqcyc = state. mono_timer . frequency ( ) . integer ( ) ;
72
79
73
- let instant = state. mono_timer . now ( ) ;
74
- timer. start ( 1 . seconds ( ) ) ;
75
- assert ! ( !timer. is_event_triggered( Event :: Update ) ) ;
76
- unwrap ! ( nb:: block!( timer. wait( ) ) . ok( ) ) ;
77
- let elapsed = instant. elapsed ( ) ;
80
+ let durations: [ duration:: Generic < u32 > ; 5 ] = [
81
+ 100 . microseconds ( ) . into ( ) ,
82
+ 1 . milliseconds ( ) . into ( ) ,
83
+ 100 . milliseconds ( ) . into ( ) ,
84
+ 1 . seconds ( ) . into ( ) ,
85
+ 10 . seconds ( ) . into ( ) ,
86
+ // 100.seconds().into(),
87
+ ] ;
88
+
89
+ for dur in durations {
90
+ defmt:: trace!( "Duration: {}" , defmt:: Debug2Format ( & dur) ) ;
91
+
92
+ timer. start ( dur) ;
93
+ assert ! ( !timer. is_event_triggered( Event :: Update ) ) ;
94
+ // call instant after start, because starting the timer is the last thing done in the
95
+ // start function, and therefor no overhead is added to the timing.
96
+ let instant = state. mono_timer . now ( ) ;
97
+ unwrap ! ( nb:: block!( timer. wait( ) ) . ok( ) ) ;
98
+ let elapsed = instant. elapsed ( ) ;
99
+
100
+ defmt:: debug!( "elapsed: {}" , elapsed) ;
101
+
102
+ let ratio = f64:: from ( elapsed) / f64:: from ( freqcyc)
103
+ * ( f64:: from ( * dur. scaling_factor ( ) . denominator ( ) ) )
104
+ / f64:: from ( dur. integer ( ) ) ;
105
+
106
+ let deviation = ( ratio - 1. ) . abs ( ) ;
107
+
108
+ // Deviation is high for smaller timer durations. Higher duratinons are pretty accurate.
109
+ // TODO: Maybe the allowed deviation should changed depending on the duration?
110
+ #[ cfg( not( debug_assertions) ) ]
111
+ defmt:: assert!( deviation < 15e-4 ) ;
112
+ #[ cfg( debug_assertions) ]
113
+ defmt:: assert!( deviation < 40e-4 ) ;
114
+ }
115
+ state. timer = Some ( timer) ;
116
+ }
78
117
79
- defmt:: info!( "elapsed: {}" , elapsed) ;
80
- // TODO: Test multiple frequencies and change the cycle counter window to a percentage
81
- // to measure the overhead of start?
118
+ #[ test]
119
+ fn test_cancel ( state : & mut State ) {
120
+ let mut timer = unwrap ! ( state. timer. take( ) ) ;
121
+ defmt:: trace!( "{}" , state. mono_timer) ;
82
122
83
- // Differentiate between releas and debug build.
84
- #[ cfg( not( debug_assertions) ) ]
85
- assert ! ( ( ( freqcyc - 500 ) ..( freqcyc + 500 ) ) . contains( & elapsed) ) ;
86
- #[ cfg( debug_assertions) ]
87
- assert ! ( ( ( freqcyc - 2000 ) ..( freqcyc + 2000 ) ) . contains( & elapsed) ) ;
123
+ timer. start ( 10 . milliseconds ( ) ) ;
124
+ state. delay . delay_ms ( 5u32 ) ;
88
125
126
+ assert ! ( matches!( timer. cancel( ) , Ok ( ( ) ) ) ) ;
127
+ assert ! ( matches!( timer. cancel( ) , Err ( AlreadyCancled ) ) ) ;
89
128
state. timer = Some ( timer) ;
90
129
}
91
130
92
- // TODO(Sh3Rm4n): For that we have to introduce a new API. (Maybe Centihertz or Something?)
93
- // #[test]
94
- // fn test_delay_longer_then_second(state: &mut State) {
95
-
96
- // }
97
-
98
131
#[ test]
99
132
fn test_interrupt ( state : & mut State ) {
100
133
let mut timer = unwrap ! ( state. timer. take( ) ) ;
0 commit comments