driver_interface/timer/
mod.rs

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