vorago_shared_hal/
embassy.rs1use core::cell::{Cell, RefCell};
2
3use crate::{
4 enable_nvic_interrupt,
5 timer::{
6 TimId, TimInstance, assert_tim_reset_for_cycles, enable_tim_clk,
7 regs::{EnableControl, MmioTimer},
8 },
9};
10use critical_section::{CriticalSection, Mutex};
11use embassy_time_driver::TICK_HZ;
12use embassy_time_driver::{Driver, time_driver_impl};
13use embassy_time_queue_utils::Queue;
14use once_cell::sync::OnceCell;
15use portable_atomic::{AtomicU32, Ordering};
16
17#[cfg(feature = "vor1x")]
18use crate::time::Hertz;
19#[cfg(feature = "vor1x")]
20use crate::{PeripheralSelect, enable_peripheral_clock};
21
22time_driver_impl!(
23 static TIME_DRIVER: TimerDriver = TimerDriver {
24 periods: AtomicU32::new(0),
25 alarms: Mutex::new(AlarmState::new()),
26 queue: Mutex::new(RefCell::new(Queue::new())),
27});
28
29pub fn time_driver() -> &'static TimerDriver {
31 &TIME_DRIVER
32}
33
34struct AlarmState {
35 timestamp: Cell<u64>,
36}
37
38impl AlarmState {
39 const fn new() -> Self {
40 Self {
41 timestamp: Cell::new(u64::MAX),
42 }
43 }
44}
45
46unsafe impl Send for AlarmState {}
47
48static SCALE: OnceCell<u64> = OnceCell::new();
49static TIMEKEEPER_TIM: OnceCell<TimId> = OnceCell::new();
50static ALARM_TIM: OnceCell<TimId> = OnceCell::new();
51
52pub struct TimerDriver {
53 periods: AtomicU32,
54 alarms: Mutex<AlarmState>,
56 queue: Mutex<RefCell<Queue>>,
57}
58
59impl TimerDriver {
60 #[cfg(feature = "vor1x")]
61 #[doc(hidden)]
62 pub fn __init<TimekeeperTim: TimInstance, AlarmTim: TimInstance>(
63 &self,
64 sysclk: Hertz,
65 _timekeeper_tim: TimekeeperTim,
66 _alarm_tim: AlarmTim,
67 timekeeper_irq: va108xx::Interrupt,
68 alarm_irq: va108xx::Interrupt,
69 ) {
70 if ALARM_TIM.get().is_some() || TIMEKEEPER_TIM.get().is_some() {
71 return;
72 }
73 ALARM_TIM.set(AlarmTim::ID).ok();
74 TIMEKEEPER_TIM.set(TimekeeperTim::ID).ok();
75 enable_peripheral_clock(PeripheralSelect::Irqsel);
76 enable_tim_clk(TimekeeperTim::ID);
77 assert_tim_reset_for_cycles(TimekeeperTim::ID, 2);
78
79 let mut timekeeper_reg_block = unsafe { TimekeeperTim::ID.steal_regs() };
80 let mut alarm_tim_reg_block = unsafe { AlarmTim::ID.steal_regs() };
81 SCALE.set((sysclk.raw() / TICK_HZ as u32) as u64).unwrap();
83 timekeeper_reg_block.write_reset_value(u32::MAX);
84 timekeeper_reg_block.write_count_value(u32::MAX);
86 let irqsel = unsafe { va108xx::Irqsel::steal() };
87 irqsel
89 .tim(TimekeeperTim::ID.value() as usize)
90 .write(|w| unsafe { w.bits(timekeeper_irq as u32) });
91 unsafe {
92 enable_nvic_interrupt(timekeeper_irq);
93 }
94 timekeeper_reg_block.modify_control(|mut value| {
95 value.set_irq_enable(true);
96 value
97 });
98 timekeeper_reg_block.write_enable_control(EnableControl::new_enable());
99
100 enable_tim_clk(AlarmTim::ID);
101 assert_tim_reset_for_cycles(AlarmTim::ID, 2);
102
103 alarm_tim_reg_block.modify_control(|mut value| {
105 value.set_irq_enable(false);
106 value.set_enable(false);
107 value
108 });
109 unsafe {
111 enable_nvic_interrupt(alarm_irq);
112 }
113 irqsel
114 .tim(AlarmTim::ID.value() as usize)
115 .write(|w| unsafe { w.bits(alarm_irq as u32) });
116 }
117
118 #[cfg(feature = "vor4x")]
119 #[doc(hidden)]
120 pub fn __init<TimekeeperTim: TimInstance, AlarmTim: TimInstance>(
121 &self,
122 _timekeeper_tim: TimekeeperTim,
123 _alarm_tim: AlarmTim,
124 clocks: &crate::clock::Clocks,
125 ) {
126 if ALARM_TIM.get().is_some() || TIMEKEEPER_TIM.get().is_some() {
127 return;
128 }
129 ALARM_TIM.set(AlarmTim::ID).ok();
130 TIMEKEEPER_TIM.set(TimekeeperTim::ID).ok();
131 let mut timekeeper_regs = unsafe { TimekeeperTim::ID.steal_regs() };
132 let mut alarm_regs = unsafe { AlarmTim::ID.steal_regs() };
133
134 enable_tim_clk(TimekeeperTim::ID);
135 assert_tim_reset_for_cycles(TimekeeperTim::ID, 2);
136
137 SCALE
140 .set((TimekeeperTim::clock(clocks).raw() / TICK_HZ as u32) as u64)
141 .unwrap();
142 timekeeper_regs.write_reset_value(u32::MAX);
143 timekeeper_regs.write_count_value(u32::MAX);
145 unsafe {
147 enable_nvic_interrupt(TimekeeperTim::IRQ);
148 }
149 timekeeper_regs.modify_control(|mut value| {
150 value.set_irq_enable(true);
151 value
152 });
153 timekeeper_regs.write_enable_control(EnableControl::new_enable());
154
155 enable_tim_clk(AlarmTim::ID);
156 assert_tim_reset_for_cycles(AlarmTim::ID, 2);
157 alarm_regs.modify_control(|mut value| {
159 value.set_irq_enable(false);
160 value.set_enable(false);
161 value
162 });
163 unsafe {
165 enable_nvic_interrupt(AlarmTim::IRQ);
166 }
167 }
168
169 fn timekeeper_tim() -> MmioTimer<'static> {
170 TIMEKEEPER_TIM
171 .get()
172 .map(|tim| unsafe { tim.steal_regs() })
173 .unwrap()
174 }
175 fn alarm_tim() -> MmioTimer<'static> {
176 ALARM_TIM
177 .get()
178 .map(|tim| unsafe { tim.steal_regs() })
179 .unwrap()
180 }
181
182 pub unsafe fn on_interrupt_timekeeping(&self) {
188 self.next_period();
189 }
190
191 pub unsafe fn on_interrupt_alarm(&self) {
197 critical_section::with(|cs| {
198 if self.alarms.borrow(cs).timestamp.get() <= self.now() {
199 self.trigger_alarm(cs)
200 }
201 })
202 }
203
204 fn next_period(&self) {
205 let period = self.periods.fetch_add(1, Ordering::AcqRel) + 1;
206 let t = (period as u64) << 32;
207 critical_section::with(|cs| {
208 let alarm = &self.alarms.borrow(cs);
209 let at = alarm.timestamp.get();
210 if at < t {
211 self.trigger_alarm(cs);
212 } else {
213 let mut alarm_tim = Self::alarm_tim();
214
215 let remaining_ticks = (at - t).checked_mul(*SCALE.get().unwrap());
216 if remaining_ticks.is_some_and(|v| v <= u32::MAX as u64) {
217 alarm_tim.write_enable_control(EnableControl::new_disable());
218 alarm_tim.write_count_value(remaining_ticks.unwrap() as u32);
219 alarm_tim.modify_control(|mut value| {
220 value.set_irq_enable(true);
221 value
222 });
223 alarm_tim.write_enable_control(EnableControl::new_enable());
224 }
225 }
226 })
227 }
228
229 fn trigger_alarm(&self, cs: CriticalSection) {
230 Self::alarm_tim().modify_control(|mut value| {
231 value.set_irq_enable(false);
232 value.set_enable(false);
233 value
234 });
235
236 let alarm = &self.alarms.borrow(cs);
237 alarm.timestamp.set(u64::MAX);
239
240 let mut next = self
242 .queue
243 .borrow(cs)
244 .borrow_mut()
245 .next_expiration(self.now());
246 while !self.set_alarm(cs, next) {
247 next = self
248 .queue
249 .borrow(cs)
250 .borrow_mut()
251 .next_expiration(self.now());
252 }
253 }
254
255 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
256 if SCALE.get().is_none() {
257 return false;
258 }
259 let mut alarm_tim = Self::alarm_tim();
260 alarm_tim.modify_control(|mut value| {
261 value.set_irq_enable(false);
262 value.set_enable(false);
263 value
264 });
265
266 let alarm = self.alarms.borrow(cs);
267 alarm.timestamp.set(timestamp);
268
269 let t = self.now();
270 if timestamp <= t {
271 alarm.timestamp.set(u64::MAX);
272 return false;
273 }
274
275 let safe_timestamp = timestamp.max(t + 3);
286 let timer_ticks = (safe_timestamp - t).checked_mul(*SCALE.get().unwrap());
287 alarm_tim.write_reset_value(u32::MAX);
288 if timer_ticks.is_some_and(|v| v <= u32::MAX as u64) {
289 alarm_tim.write_count_value(timer_ticks.unwrap() as u32);
290 alarm_tim.modify_control(|mut value| {
291 value.set_irq_enable(true);
292 value.set_enable(true);
293 value
294 });
295 }
296 true
300 }
301}
302
303impl Driver for TimerDriver {
304 fn now(&self) -> u64 {
305 if SCALE.get().is_none() {
306 return 0;
307 }
308 let mut period1: u32;
309 let mut period2: u32;
310 let mut counter_val: u32;
311
312 loop {
313 period1 = self.periods.load(Ordering::Acquire);
316
317 counter_val = u32::MAX - Self::timekeeper_tim().read_count_value();
318
319 period2 = self.periods.load(Ordering::Relaxed);
321 if period1 == period2 {
322 let now = (((period1 as u64) << 32) | counter_val as u64) / *SCALE.get().unwrap();
323 return now;
324 }
325 }
326 }
327
328 fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
329 critical_section::with(|cs| {
330 let mut queue = self.queue.borrow(cs).borrow_mut();
331
332 if queue.schedule_wake(at, waker) {
333 let mut next = queue.next_expiration(self.now());
334 while !self.set_alarm(cs, next) {
335 next = queue.next_expiration(self.now());
336 }
337 }
338 })
339 }
340}