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
83 .set((sysclk.to_raw() / TICK_HZ as u32) as u64)
84 .unwrap();
85 timekeeper_reg_block.write_reset_value(u32::MAX);
86 timekeeper_reg_block.write_count_value(u32::MAX);
88 let irqsel = unsafe { va108xx::Irqsel::steal() };
89 irqsel
91 .tim(TimekeeperTim::ID.value() as usize)
92 .write(|w| unsafe { w.bits(timekeeper_irq as u32) });
93 unsafe {
94 enable_nvic_interrupt(timekeeper_irq);
95 }
96 timekeeper_reg_block.modify_control(|mut value| {
97 value.set_irq_enable(true);
98 value
99 });
100 timekeeper_reg_block.write_enable_control(EnableControl::new_enable());
101
102 enable_tim_clk(AlarmTim::ID);
103 assert_tim_reset_for_cycles(AlarmTim::ID, 2);
104
105 alarm_tim_reg_block.modify_control(|mut value| {
107 value.set_irq_enable(false);
108 value.set_enable(false);
109 value
110 });
111 unsafe {
113 enable_nvic_interrupt(alarm_irq);
114 }
115 irqsel
116 .tim(AlarmTim::ID.value() as usize)
117 .write(|w| unsafe { w.bits(alarm_irq as u32) });
118 }
119
120 #[cfg(feature = "vor4x")]
121 #[doc(hidden)]
122 pub fn __init<TimekeeperTim: TimInstance, AlarmTim: TimInstance>(
123 &self,
124 _timekeeper_tim: TimekeeperTim,
125 _alarm_tim: AlarmTim,
126 clocks: &crate::clock::Clocks,
127 ) {
128 if ALARM_TIM.get().is_some() || TIMEKEEPER_TIM.get().is_some() {
129 return;
130 }
131 ALARM_TIM.set(AlarmTim::ID).ok();
132 TIMEKEEPER_TIM.set(TimekeeperTim::ID).ok();
133 let mut timekeeper_regs = unsafe { TimekeeperTim::ID.steal_regs() };
134 let mut alarm_regs = unsafe { AlarmTim::ID.steal_regs() };
135
136 enable_tim_clk(TimekeeperTim::ID);
137 assert_tim_reset_for_cycles(TimekeeperTim::ID, 2);
138
139 SCALE
142 .set((TimekeeperTim::clock(clocks).to_raw() / TICK_HZ as u32) as u64)
143 .unwrap();
144 timekeeper_regs.write_reset_value(u32::MAX);
145 timekeeper_regs.write_count_value(u32::MAX);
147 unsafe {
149 enable_nvic_interrupt(TimekeeperTim::IRQ);
150 }
151 timekeeper_regs.modify_control(|mut value| {
152 value.set_irq_enable(true);
153 value
154 });
155 timekeeper_regs.write_enable_control(EnableControl::new_enable());
156
157 enable_tim_clk(AlarmTim::ID);
158 assert_tim_reset_for_cycles(AlarmTim::ID, 2);
159 alarm_regs.modify_control(|mut value| {
161 value.set_irq_enable(false);
162 value.set_enable(false);
163 value
164 });
165 unsafe {
167 enable_nvic_interrupt(AlarmTim::IRQ);
168 }
169 }
170
171 fn timekeeper_tim() -> MmioTimer<'static> {
172 TIMEKEEPER_TIM
173 .get()
174 .map(|tim| unsafe { tim.steal_regs() })
175 .unwrap()
176 }
177 fn alarm_tim() -> MmioTimer<'static> {
178 ALARM_TIM
179 .get()
180 .map(|tim| unsafe { tim.steal_regs() })
181 .unwrap()
182 }
183
184 pub unsafe fn on_interrupt_timekeeping(&self) {
190 self.next_period();
191 }
192
193 pub unsafe fn on_interrupt_alarm(&self) {
199 critical_section::with(|cs| {
200 if self.alarms.borrow(cs).timestamp.get() <= self.now() {
201 self.trigger_alarm(cs)
202 }
203 })
204 }
205
206 fn next_period(&self) {
207 let period = self.periods.fetch_add(1, Ordering::AcqRel) + 1;
208 let t = (period as u64) << 32;
209 critical_section::with(|cs| {
210 let alarm = &self.alarms.borrow(cs);
211 let at = alarm.timestamp.get();
212 if at < t {
213 self.trigger_alarm(cs);
214 } else {
215 let mut alarm_tim = Self::alarm_tim();
216
217 let remaining_ticks = (at - t).checked_mul(*SCALE.get().unwrap());
218 if remaining_ticks.is_some_and(|v| v <= u32::MAX as u64) {
219 alarm_tim.write_enable_control(EnableControl::new_disable());
220 alarm_tim.write_count_value(remaining_ticks.unwrap() as u32);
221 alarm_tim.modify_control(|mut value| {
222 value.set_irq_enable(true);
223 value
224 });
225 alarm_tim.write_enable_control(EnableControl::new_enable());
226 }
227 }
228 })
229 }
230
231 fn trigger_alarm(&self, cs: CriticalSection) {
232 Self::alarm_tim().modify_control(|mut value| {
233 value.set_irq_enable(false);
234 value.set_enable(false);
235 value
236 });
237
238 let alarm = &self.alarms.borrow(cs);
239 alarm.timestamp.set(u64::MAX);
241
242 let mut next = self
244 .queue
245 .borrow(cs)
246 .borrow_mut()
247 .next_expiration(self.now());
248 while !self.set_alarm(cs, next) {
249 next = self
250 .queue
251 .borrow(cs)
252 .borrow_mut()
253 .next_expiration(self.now());
254 }
255 }
256
257 fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
258 if SCALE.get().is_none() {
259 return false;
260 }
261 let mut alarm_tim = Self::alarm_tim();
262 alarm_tim.modify_control(|mut value| {
263 value.set_irq_enable(false);
264 value.set_enable(false);
265 value
266 });
267
268 let alarm = self.alarms.borrow(cs);
269 alarm.timestamp.set(timestamp);
270
271 let t = self.now();
272 if timestamp <= t {
273 alarm.timestamp.set(u64::MAX);
274 return false;
275 }
276
277 let safe_timestamp = timestamp.max(t + 3);
288 let timer_ticks = (safe_timestamp - t).checked_mul(*SCALE.get().unwrap());
289 alarm_tim.write_reset_value(u32::MAX);
290 if timer_ticks.is_some_and(|v| v <= u32::MAX as u64) {
291 alarm_tim.write_count_value(timer_ticks.unwrap() as u32);
292 alarm_tim.modify_control(|mut value| {
293 value.set_irq_enable(true);
294 value.set_enable(true);
295 value
296 });
297 }
298 true
302 }
303}
304
305impl Driver for TimerDriver {
306 fn now(&self) -> u64 {
307 if SCALE.get().is_none() {
308 return 0;
309 }
310 let mut period1: u32;
311 let mut period2: u32;
312 let mut counter_val: u32;
313
314 loop {
315 period1 = self.periods.load(Ordering::Acquire);
318
319 counter_val = u32::MAX - Self::timekeeper_tim().read_count_value();
320
321 period2 = self.periods.load(Ordering::Relaxed);
323 if period1 == period2 {
324 let now = (((period1 as u64) << 32) | counter_val as u64) / *SCALE.get().unwrap();
325 return now;
326 }
327 }
328 }
329
330 fn schedule_wake(&self, at: u64, waker: &core::task::Waker) {
331 critical_section::with(|cs| {
332 let mut queue = self.queue.borrow(cs).borrow_mut();
333
334 if queue.schedule_wake(at, waker) {
335 let mut next = queue.next_expiration(self.now());
336 while !self.set_alarm(cs, next) {
337 next = queue.next_expiration(self.now());
338 }
339 }
340 })
341 }
342}