1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use core::sync::atomic::{AtomicUsize, Ordering};
use super::event;
use super::event::{IRQEvent, Waitable};
use super::sync::Once;
use super::utils::div_ceil;
struct KernelTimerInfo {
oscillator_frequency: u64,
pub irq_period_ns: u64,
pub irq_number: u8,
}
static KERNEL_TIMER_INFO: Once<KernelTimerInfo> = Once::new();
pub fn set_kernel_timer_info(irq_number: u8, oscillator_frequency: u64, irq_period_ns: u64) {
assert!(KERNEL_TIMER_INFO.r#try().is_none(), "Kernel Timer Info is already initialized!");
KERNEL_TIMER_INFO.call_once(|| {
KernelTimerInfo {
irq_number,
oscillator_frequency,
irq_period_ns
}
});
}
pub fn wait_ns(ns: usize) -> impl Waitable {
let timer_info = KERNEL_TIMER_INFO.r#try().expect("Kernel Timer Info is not initialized!");
IRQTimer::new(ns, timer_info.irq_number, timer_info.irq_period_ns)
}
#[derive(Debug)]
pub struct IRQTimer {
every_ns: usize,
irq_period_ns: u64,
parent_event: IRQEvent,
reset_value: usize,
countdown_value: AtomicUsize
}
impl IRQTimer {
pub fn new(ns: usize, irq: u8, irq_period_ns: u64) -> Self {
let mut reset_value = div_ceil(ns as u64, irq_period_ns) as usize;
if reset_value == 0 {
reset_value = 1;
}
IRQTimer {
every_ns: ns,
irq_period_ns,
parent_event: event::wait_event(irq),
reset_value,
countdown_value: AtomicUsize::new(0)
}
}
}
impl Waitable for IRQTimer {
fn register(&self) {
self.parent_event.register()
}
fn is_signaled(&self) -> bool {
self.countdown_value.compare_and_swap(0, self.reset_value, Ordering::SeqCst);
self.parent_event.is_signaled()
&& self.countdown_value.fetch_sub(1, Ordering::SeqCst) == 1
}
}