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