kernel/arch/riscv64/
timer.rs

1use core::arch::asm;
2
3use crate::{arch::instruction::sbi::sbi_set_timer, environment::RISCV_STIMER_FREQ};
4
5pub type ArchTimer = Stimer;
6
7pub struct Stimer {
8    pub next_event: u64,
9    pub running: bool,
10}
11
12impl Stimer {
13    pub const fn new() -> Self {
14        Stimer {
15            next_event: 0,
16            running: false,
17        }
18    }
19
20    pub fn set_interval_us(&mut self, interval: u64) {
21        let current = self.get_time();
22        self.set_next_event(current + (interval * RISCV_STIMER_FREQ) / 1000000);
23    }
24
25    pub fn start(&mut self) {
26        self.running = true;
27        sbi_set_timer(self.next_event);
28        let mut sie: usize;
29        unsafe {
30            asm!(
31                "csrr {0}, sie",
32                out(reg) sie,
33            );
34            /* Enable timer interrupt */
35            sie |= 1 << 5;
36            asm!(
37                "csrw sie, {0}",
38                in(reg) sie,
39            );
40        }
41    }
42
43    pub fn stop(&mut self) {
44        self.running = false;
45        sbi_set_timer(0xffffffff_ffffffff);
46        let mut sie: usize;
47        unsafe {
48            asm!(
49                "csrr {0}, sie",
50                out(reg) sie,
51            );
52            /* Disable timer interrupt */
53            sie &= !(1 << 5);
54            asm!(
55                "csrw sie, {0}",
56                in(reg) sie,
57            );
58        }
59    }
60
61    pub fn is_running(&self) -> bool {
62        self.running
63    }
64
65    fn get_next_event(&self) -> u64 {
66        self.next_event
67    }
68
69    pub fn get_time_us(&self) -> u64 {
70        self.get_time() / RISCV_STIMER_FREQ
71    }
72
73    fn get_time(&self) -> u64 {
74        let time: u64;
75        unsafe {
76            asm!(
77                "rdtime {0}",
78                out(reg) time,
79            );
80        }
81        time
82    }
83
84    fn set_next_event(&mut self, next_event: u64) {
85        self.next_event = next_event;
86    }
87}