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