sparreal_kernel/time/
timer.rs

1use core::{
2    sync::atomic::{Ordering, fence},
3    time::Duration,
4};
5
6use super::queue;
7use alloc::boxed::Box;
8use rdrive::timer::*;
9
10const NANO_PER_SEC: u128 = 1_000_000_000;
11
12pub struct Timer {
13    timer: HardwareCPU,
14    q: queue::Queue,
15}
16
17unsafe impl Sync for Timer {}
18unsafe impl Send for Timer {}
19
20impl Timer {
21    pub fn new(timer: HardwareCPU) -> Self {
22        Self {
23            timer,
24            q: queue::Queue::new(),
25        }
26    }
27
28    pub fn enable(&mut self) {
29        let _ = self.timer.open();
30    }
31
32    pub fn since_boot(&self) -> Duration {
33        self.tick_to_duration(self.timer.current_ticks())
34    }
35
36    pub fn after(&mut self, duration: Duration, callback: impl Fn() + 'static) {
37        let ticks = self.duration_to_tick(duration);
38
39        let event = queue::Event {
40            interval: None,
41            at_tick: self.timer.current_ticks() + ticks,
42            callback: Box::new(callback),
43            called: false,
44        };
45
46        self.add_event(event);
47    }
48
49    pub fn every(&mut self, duration: Duration, callback: impl Fn() + 'static) {
50        let ticks = self.duration_to_tick(duration);
51
52        let event = queue::Event {
53            interval: Some(ticks),
54            at_tick: self.timer.current_ticks() + ticks,
55            callback: Box::new(callback),
56            called: false,
57        };
58
59        self.add_event(event);
60    }
61
62    fn add_event(&mut self, event: queue::Event) {
63        self.timer.set_irq_enable(false);
64        fence(Ordering::SeqCst);
65
66        let next_tick = self.q.add_and_next_tick(event);
67        let v = next_tick - self.timer.current_ticks();
68        self.timer.set_timeval(v);
69
70        fence(Ordering::SeqCst);
71        self.timer.set_irq_enable(true);
72    }
73
74    pub fn handle_irq(&mut self) {
75        while let Some(event) = self.q.pop(self.timer.current_ticks()) {
76            (event.callback)();
77        }
78
79        match self.q.next_tick() {
80            Some(next_tick) => {
81                self.timer.set_timeval(next_tick);
82            }
83            None => {
84                self.timer.set_irq_enable(false);
85            }
86        }
87    }
88
89    pub fn set_irq_enable(&mut self, enable: bool) {
90        self.timer.set_irq_enable(enable);
91    }
92
93    fn tick_to_duration(&self, tick: u64) -> Duration {
94        Duration::from_nanos((tick as u128 * NANO_PER_SEC / self.timer.tick_hz() as u128) as _)
95    }
96
97    fn duration_to_tick(&self, duration: Duration) -> u64 {
98        (duration.as_nanos() * self.timer.tick_hz() as u128 / NANO_PER_SEC) as _
99    }
100
101    pub fn irq(&self) -> IrqConfig {
102        self.timer.irq()
103    }
104}