Skip to content

Commit 5b72eac

Browse files
committed
Expose various delay functions using delay_cycles.
1 parent 754dba7 commit 5b72eac

File tree

2 files changed

+26
-60
lines changed

2 files changed

+26
-60
lines changed

examples/milliseconds.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ extern crate avr_std_stub;
55

66
#[no_mangle]
77
fn main() {
8-
avr_delay::delay_ms(4500);
8+
avr_delay::delay_ms::<4500>();
99
}

src/lib.rs

Lines changed: 25 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,40 @@
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

Comments
 (0)