1- #![ feature( asm_experimental_arch) ]
2-
3- #![ no_std]
4-
51#![ crate_name = "avr_delay" ]
2+ #![ no_std]
3+ #![ feature( asm_experimental_arch) ]
4+ #![ feature( asm_const) ]
65
7- use core :: arch :: asm ;
6+ mod delay_cycles ;
87
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 ;
139
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+ }
2518
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.
2921#[ 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 ( )
5124}
5225
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.
5628#[ 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 ( )
6131}
6232
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.
6635#[ 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 ( )
7138}
7239
7340#[ cfg( test) ]
@@ -77,4 +44,3 @@ mod tests {
7744 assert_eq ! ( 2 + 2 , 4 ) ;
7845 }
7946}
80-
0 commit comments