1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! # Delays
use crate::clock::Clocks;
use e310x::CLINT;
use embedded_hal::delay::DelayNs;
use riscv::register::mip;
/// Machine timer (mtime) as a busyloop delay provider
#[derive(Default)]
pub struct Delay;
const TICKS_PER_SECOND: u64 = 32768;
impl Delay {
/// Constructs a delay provider based on the machine timer (mtime)
pub fn new() -> Self {
Delay
}
}
impl DelayNs for Delay {
fn delay_ns(&mut self, ns: u32) {
let ticks = (ns as u64) * TICKS_PER_SECOND / 1_000_000_000;
let mtime = CLINT::mtimer().mtime;
let t = mtime.read() + ticks;
while mtime.read() < t {}
}
}
/// Machine timer (mtime) as a sleep delay provider using mtimecmp
pub struct Sleep {
clock_freq: u32,
}
impl Sleep {
/// Constructs a delay provider using mtimecmp register to sleep
pub fn new(clocks: Clocks) -> Self {
Sleep {
clock_freq: clocks.lfclk().0,
}
}
}
impl DelayNs for Sleep {
fn delay_ns(&mut self, ns: u32) {
let ticks = (ns as u64) * u64::from(self.clock_freq) / 1_000_000_000;
let t = CLINT::mtimer().mtime.read() + ticks;
CLINT::mtimecmp0().write(t);
// Enable timer interrupt
unsafe { CLINT::mtimer_enable() };
// Wait For Interrupt will put CPU to sleep until an interrupt hits
// in our case when internal timer mtime value >= mtimecmp value
// after which empty handler gets called and we go into the
// next iteration of this loop
loop {
riscv::asm::wfi();
// check if we got the right interrupt cause, otherwise just loop back to wfi
if mip::read().mtimer() {
break;
}
}
// Clear timer interrupt
CLINT::mtimer_disable();
}
}