kernel/arch/riscv64/
timer.rs

1use core::arch::asm;
2
3use crate::{arch::get_cpu, interrupt::InterruptManager};
4
5pub type ArchTimer = Stimer;
6
7pub struct Stimer {
8    pub next_event: u64,
9    pub running: bool,
10    frequency: u64,
11}
12
13impl Stimer {
14    pub fn new() -> Self {
15        let freq = InterruptManager::with_manager(|manager| {
16            let cpu_id = get_cpu().get_cpuid() as u32;
17            match manager.get_timer_frequency_hz(cpu_id) {
18                Ok(freq) => freq,
19                Err(e) => {
20                    panic!("Failed to get timer frequency: {}", e);
21                }
22            }
23        });
24
25        Stimer {
26            next_event: 0,
27            running: false,
28            frequency: freq,
29        }
30    }
31
32    pub fn set_interval_us(&mut self, interval: u64) {
33        let current = self.get_time();
34        self.set_next_event(current + (interval * self.frequency / 1000000));
35    }
36
37    pub fn start(&mut self) {
38        self.running = true;
39        InterruptManager::with_manager(|manager| {
40            let cpu_id = get_cpu().get_cpuid() as u32;
41            if manager.set_timer(cpu_id, self.get_next_event()).is_err() {
42                panic!("Failed to set timer for CPU {}", cpu_id);
43            }
44        });
45
46        let mut sie: usize;
47        unsafe {
48            asm!(
49                "csrr {0}, sie",
50                out(reg) sie,
51            );
52            /* Enable timer interrupt */
53            sie |= 1 << 5;
54            asm!(
55                "csrw sie, {0}",
56                in(reg) sie,
57            );
58        }
59    }
60
61    pub fn stop(&mut self) {
62        self.running = false;
63        InterruptManager::with_manager(|manager| {
64            let cpu_id = get_cpu().get_cpuid() as u32;
65            if manager.set_timer(cpu_id, 0xFFFFFFFFFFFFFFFF).is_err() {
66                panic!("Failed to stop timer for CPU {}", cpu_id);
67            }
68        });
69
70        let mut sie: usize;
71        unsafe {
72            asm!(
73                "csrr {0}, sie",
74                out(reg) sie,
75            );
76            /* Disable timer interrupt */
77            sie &= !(1 << 5);
78            asm!(
79                "csrw sie, {0}",
80                in(reg) sie,
81            );
82        }
83    }
84
85    pub fn is_running(&self) -> bool {
86        self.running
87    }
88
89    fn get_next_event(&self) -> u64 {
90        self.next_event
91    }
92
93    pub fn get_time_us(&self) -> u64 {
94        (self.get_time() * 1_000_000) / self.frequency
95    }
96
97    /// Get the current clock time
98    fn get_time(&self) -> u64 {
99        let time: u64;
100        unsafe {
101            asm!(
102                "rdtime {0}",
103                out(reg) time,
104            );
105        }
106        time
107    }
108
109    fn set_next_event(&mut self, next_event: u64) {
110        self.next_event = next_event;
111    }
112}