kernel/arch/riscv64/
timer.rs1use 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 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 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 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}