1
- #![ feature( asm_experimental_arch) ]
2
-
3
- #![ no_std]
4
-
5
1
#![ crate_name = "avr_delay" ]
2
+ #![ no_std]
3
+ #![ feature( asm_experimental_arch) ]
4
+ #![ feature( asm_const) ]
6
5
7
- use core :: arch :: asm ;
6
+ mod delay_cycles ;
8
7
9
- /// This library is intended to provide a busy-wait delay
10
- /// similar to the one provided by the arduino c++ utilities
11
- /// If you need accurate time keeping you should consider a
12
- /// hardware timer.
8
+ use delay_cycles:: Delayer ;
13
9
14
- // This library does all of the busy-wait loop in rust.
15
- // We pack as much of the looping as possible into asm!
16
- // so that we can count cycles.
17
- //
18
- // Ignoring the overhead, which may be significant:
19
- // An arduino runs at 16MHZ. Each asm loop is 4 cycles.
20
- // so each loop is 0.25 us.
21
- //
22
- // the overhead of delay() seems to be about 13 cycles
23
- // initially, and then 11 cycles per outer loop. We ignore
24
- // all that.
10
+ /// Delay by the exact number of CYCLES.
11
+ /// The number of instructions generated goes up to 11. The higher the number of cycles, the higher
12
+ /// number of instructions, in a staircase effect.
13
+ /// Accepts 0 to 25_769_803_784 cycles (almost 18 minutes at 24Mhz).
14
+ #[ inline( always) ]
15
+ pub fn delay_cycles < const CYCLES : u64 > ( ) {
16
+ Delayer :: < CYCLES , 1 , 1 > :: delay_impl ( )
17
+ }
25
18
26
- /// Internal function to implement a variable busy-wait loop.
27
- /// # Arguments
28
- /// * 'count' - a u64, the number of times to cycle the loop.
19
+ /// Maximum value is (25_769_803_784 * 1_000_000 / CPU_FREQUENCY_HZ).
20
+ /// Almost 18 minutes at 24Mhz.
29
21
#[ inline( always) ]
30
- pub fn delay ( count : u64 ) {
31
- // Our asm busy-wait takes a 16 bit word as an argument,
32
- // so the max number of loops is 2^16
33
- let outer_count = count / 65536 ;
34
- let last_count = ( ( count % 65536 ) +1 ) as u16 ;
35
- for _ in 0 ..outer_count {
36
- // Each loop through should be 4 cycles.
37
- let zero = 0u16 ;
38
- unsafe {
39
- asm ! ( "1: sbiw {i}, 1" ,
40
- "brne 1b" ,
41
- i = inout( reg_iw) zero => _,
42
- )
43
- }
44
- }
45
- unsafe {
46
- asm ! ( "1: sbiw {i}, 1" ,
47
- "brne 1b" ,
48
- i = inout( reg_iw) last_count => _,
49
- )
50
- }
22
+ pub fn delay_us < const US : u64 > ( ) {
23
+ Delayer :: < US , { avr_config:: CPU_FREQUENCY_HZ as u64 } , 1_000_000 > :: delay_impl ( )
51
24
}
52
25
53
- ///delay for N milliseconds
54
- /// # Arguments
55
- /// * 'ms' - an u64, number of milliseconds to busy-wait
26
+ /// Maximum value is (25_769_803_784 * 1_000 / CPU_FREQUENCY_HZ).
27
+ /// Almost 18 minutes at 24Mhz.
56
28
#[ inline( always) ]
57
- pub fn delay_ms ( ms : u64 ) {
58
- // microseconds
59
- let us = ms * 1000 ;
60
- delay_us ( us) ;
29
+ pub fn delay_ms < const MS : u64 > ( ) {
30
+ Delayer :: < MS , { avr_config:: CPU_FREQUENCY_HZ as u64 } , 1_000 > :: delay_impl ( )
61
31
}
62
32
63
- ///delay for N microseconds
64
- /// # Arguments
65
- /// * 'us' - an u64, number of microseconds to busy-wait
33
+ /// Maximum value is (25_769_803_784 * 1 / CPU_FREQUENCY_HZ).
34
+ /// Almost 18 minutes at 24Mhz.
66
35
#[ inline( always) ]
67
- pub fn delay_us ( us : u64 ) {
68
- let us_in_loop = ( avr_config:: CPU_FREQUENCY_HZ / 1000000 / 4 ) as u64 ;
69
- let loops = us * us_in_loop;
70
- delay ( loops) ;
36
+ pub fn delay_sec < const SEC : u64 > ( ) {
37
+ Delayer :: < SEC , { avr_config:: CPU_FREQUENCY_HZ as u64 } , 1 > :: delay_impl ( )
71
38
}
72
39
73
40
#[ cfg( test) ]
@@ -77,4 +44,3 @@ mod tests {
77
44
assert_eq ! ( 2 + 2 , 4 ) ;
78
45
}
79
46
}
80
-
0 commit comments