axplat_arm_peripherals/
generic_timer.rs1use axcpu::generic_timer::{GenericTimer, PhysicalTimer as Timer};
4use int_ratio::Ratio;
5
6static mut CNTPCT_TO_NANOS_RATIO: Ratio = Ratio::zero();
7static mut NANOS_TO_CNTPCT_RATIO: Ratio = Ratio::zero();
8
9#[inline]
11pub fn current_ticks() -> u64 {
12 Timer::counter()
13}
14
15#[inline]
17pub fn ticks_to_nanos(ticks: u64) -> u64 {
18 unsafe { CNTPCT_TO_NANOS_RATIO.mul_trunc(ticks) }
19}
20
21#[inline]
23pub fn nanos_to_ticks(nanos: u64) -> u64 {
24 unsafe { NANOS_TO_CNTPCT_RATIO.mul_trunc(nanos) }
25}
26
27pub fn set_oneshot_timer(deadline_ns: u64) {
31 let cur_ticks = current_ticks();
32 let deadline_ticks = nanos_to_ticks(deadline_ns);
33 if cur_ticks < deadline_ticks {
34 let interval = deadline_ticks - cur_ticks;
35 debug_assert!(interval <= u32::MAX as u64);
36 Timer::set_countdown(interval as u32);
37 } else {
38 Timer::set_countdown(0);
39 }
40}
41
42pub fn init_early() {
44 let freq = Timer::frequency();
45 unsafe {
46 CNTPCT_TO_NANOS_RATIO = Ratio::new(axplat::time::NANOS_PER_SEC as u32, freq);
47 NANOS_TO_CNTPCT_RATIO = CNTPCT_TO_NANOS_RATIO.inverse();
48 }
49}
50
51#[cfg(feature = "irq")]
56pub fn enable_irqs(timer_irq_num: usize) {
57 Timer::set_enable(true);
58 Timer::set_countdown(0);
59 axplat::irq::set_enable(timer_irq_num, true);
60}
61
62#[macro_export]
65macro_rules! time_if_impl {
66 ($name:ident) => {
67 struct $name;
68
69 #[impl_interface]
70 impl axplat::time::TimeIf for $name {
71 fn current_ticks() -> u64 {
73 $crate::generic_timer::current_ticks()
74 }
75
76 fn ticks_to_nanos(ticks: u64) -> u64 {
78 $crate::generic_timer::ticks_to_nanos(ticks)
79 }
80
81 fn nanos_to_ticks(nanos: u64) -> u64 {
83 $crate::generic_timer::nanos_to_ticks(nanos)
84 }
85
86 fn epochoffset_nanos() -> u64 {
89 $crate::pl031::epochoffset_nanos()
90 }
91
92 #[cfg(feature = "irq")]
97 fn set_oneshot_timer(deadline_ns: u64) {
98 $crate::generic_timer::set_oneshot_timer(deadline_ns)
99 }
100 }
101 };
102}