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