earlgrey/
timer.rs
1use crate::chip_config::EarlGreyConfig;
8use crate::registers::top_earlgrey::RV_TIMER_BASE_ADDR;
9use core::marker::PhantomData;
10use kernel::hil::time::{self, Ticks64};
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::registers::interfaces::{Readable, Writeable};
13use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite, WriteOnly};
14use kernel::utilities::StaticRef;
15use kernel::ErrorCode;
16use rv32i::machine_timer::MachineTimer;
17
18#[derive(Debug)]
20pub struct Freq10KHz;
21impl time::Frequency for Freq10KHz {
22 fn frequency() -> u32 {
23 10_000
24 }
25}
26
27register_structs! {
28 pub TimerRegisters {
29 (0x000 => alert_test: WriteOnly<u32>),
30 (0x004 => ctrl: ReadWrite<u32, ctrl::Register>),
31 (0x008 => _reserved),
32 (0x100 => intr_enable: ReadWrite<u32, intr::Register>),
33 (0x104 => intr_state: ReadWrite<u32, intr::Register>),
34 (0x108 => intr_test: WriteOnly<u32, intr::Register>),
35 (0x10C => config: ReadWrite<u32, config::Register>),
36 (0x110 => value_low: ReadWrite<u32>),
37 (0x114 => value_high: ReadWrite<u32>),
38 (0x118 => compare_low: ReadWrite<u32>),
39 (0x11C => compare_high: ReadWrite<u32>),
40 (0x120 => @END),
41 }
42}
43
44register_bitfields![u32,
45 ctrl [
46 enable OFFSET(0) NUMBITS(1) []
47 ],
48 intr [
49 timer0 OFFSET(0) NUMBITS(1) []
50 ],
51 config [
52 prescale OFFSET(0) NUMBITS(12) [],
53 step OFFSET(16) NUMBITS(8) []
54 ],
55];
56
57pub struct RvTimer<'a, CFG: EarlGreyConfig> {
58 registers: StaticRef<TimerRegisters>,
59 alarm_client: OptionalCell<&'a dyn time::AlarmClient>,
60 overflow_client: OptionalCell<&'a dyn time::OverflowClient>,
61 mtimer: MachineTimer<'a>,
62 _cfg: PhantomData<CFG>,
63}
64
65impl<CFG: EarlGreyConfig> RvTimer<'_, CFG> {
66 pub fn new() -> Self {
67 Self {
68 registers: TIMER_BASE,
69 alarm_client: OptionalCell::empty(),
70 overflow_client: OptionalCell::empty(),
71 mtimer: MachineTimer::new(
72 &TIMER_BASE.compare_low,
73 &TIMER_BASE.compare_high,
74 &TIMER_BASE.value_low,
75 &TIMER_BASE.value_high,
76 ),
77 _cfg: PhantomData,
78 }
79 }
80
81 pub fn setup(&self) {
82 let prescale: u16 = ((CFG::CPU_FREQ / 10_000) - 1) as u16; let regs = self.registers;
85 regs.config
87 .write(config::prescale.val(prescale as u32) + config::step.val(1u32));
88 regs.compare_high.set(0);
89 regs.value_low.set(0xFFFF_0000);
90 regs.intr_enable.write(intr::timer0::CLEAR);
91 regs.ctrl.write(ctrl::enable::SET);
92 }
93
94 pub fn service_interrupt(&self) {
95 let regs = self.registers;
96 regs.intr_enable.write(intr::timer0::CLEAR);
97 regs.intr_state.write(intr::timer0::SET);
98 self.alarm_client.map(|client| {
99 client.alarm();
100 });
101 }
102}
103
104impl<CFG: EarlGreyConfig> time::Time for RvTimer<'_, CFG> {
105 type Frequency = Freq10KHz;
106 type Ticks = Ticks64;
107
108 fn now(&self) -> Ticks64 {
109 self.mtimer.now()
110 }
111}
112
113impl<'a, CFG: EarlGreyConfig> time::Counter<'a> for RvTimer<'a, CFG> {
114 fn set_overflow_client(&self, client: &'a dyn time::OverflowClient) {
115 self.overflow_client.set(client);
116 }
117
118 fn start(&self) -> Result<(), ErrorCode> {
119 Ok(())
120 }
121
122 fn stop(&self) -> Result<(), ErrorCode> {
123 Err(ErrorCode::BUSY)
125 }
126
127 fn reset(&self) -> Result<(), ErrorCode> {
128 Err(ErrorCode::FAIL)
130 }
131
132 fn is_running(&self) -> bool {
133 true
134 }
135}
136
137impl<'a, CFG: EarlGreyConfig> time::Alarm<'a> for RvTimer<'a, CFG> {
138 fn set_alarm_client(&self, client: &'a dyn time::AlarmClient) {
139 self.alarm_client.set(client);
140 }
141
142 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
143 self.registers.intr_enable.write(intr::timer0::SET);
144
145 self.mtimer.set_alarm(reference, dt)
146 }
147
148 fn get_alarm(&self) -> Self::Ticks {
149 self.mtimer.get_alarm()
150 }
151
152 fn disarm(&self) -> Result<(), ErrorCode> {
153 self.registers.intr_enable.write(intr::timer0::CLEAR);
154
155 self.mtimer.disarm()
156 }
157
158 fn is_armed(&self) -> bool {
159 self.registers.intr_enable.is_set(intr::timer0)
160 }
161
162 fn minimum_dt(&self) -> Self::Ticks {
163 self.mtimer.minimum_dt()
164 }
165}
166
167const TIMER_BASE: StaticRef<TimerRegisters> =
168 unsafe { StaticRef::new(RV_TIMER_BASE_ADDR as *const TimerRegisters) };