kernel/arch/riscv64/
timer.rs

1use core::arch::asm;
2
3use crate::{arch::{get_cpu, instruction::sbi::sbi_set_timer}, environment::RISCV_STIMER_FREQ, interrupt::InterruptManager};
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        InterruptManager::with_manager(|manager| {
28            let cpu_id = get_cpu().get_cpuid() as u32;
29            if manager.set_timer(cpu_id, self.get_next_event()).is_err() {
30                panic!("Failed to set timer for CPU {}", cpu_id);
31            }
32        });
33
34        let mut sie: usize;
35        unsafe {
36            asm!(
37                "csrr {0}, sie",
38                out(reg) sie,
39            );
40            /* Enable timer interrupt */
41            sie |= 1 << 5;
42            asm!(
43                "csrw sie, {0}",
44                in(reg) sie,
45            );
46        }
47    }
48
49    pub fn stop(&mut self) {
50        self.running = false;
51        InterruptManager::with_manager(|manager| {
52            let cpu_id = get_cpu().get_cpuid() as u32;
53            if manager.set_timer(cpu_id, 0xFFFFFFFFFFFFFFFF).is_err() {
54                panic!("Failed to stop timer for CPU {}", cpu_id);
55            }
56        });
57
58        let mut sie: usize;
59        unsafe {
60            asm!(
61                "csrr {0}, sie",
62                out(reg) sie,
63            );
64            /* Disable timer interrupt */
65            sie &= !(1 << 5);
66            asm!(
67                "csrw sie, {0}",
68                in(reg) sie,
69            );
70        }
71    }
72
73    pub fn is_running(&self) -> bool {
74        self.running
75    }
76
77    fn get_next_event(&self) -> u64 {
78        self.next_event
79    }
80
81    pub fn get_time_us(&self) -> u64 {
82        self.get_time() / RISCV_STIMER_FREQ
83    }
84
85    fn get_time(&self) -> u64 {
86        let time: u64;
87        unsafe {
88            asm!(
89                "rdtime {0}",
90                out(reg) time,
91            );
92        }
93        time
94    }
95
96    fn set_next_event(&mut self, next_event: u64) {
97        self.next_event = next_event;
98    }
99}