litex/timer.rs
1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! LiteX timer core
6//!
7//! Hardware source and documentation available at
8//! [`litex/soc/cores/timer.py`](https://github.com/enjoy-digital/litex/blob/master/litex/soc/cores/timer.py).
9
10use core::cell::Cell;
11use core::marker::PhantomData;
12use kernel::hil::time::{
13 Alarm, AlarmClient, Frequency, Ticks, Ticks32, Ticks64, Time, Timer, TimerClient,
14};
15use kernel::utilities::cells::OptionalCell;
16use kernel::utilities::StaticRef;
17use kernel::ErrorCode;
18
19use crate::event_manager::LiteXEventManager;
20use crate::litex_registers::{
21 register_bitfields, LiteXSoCRegisterConfiguration, Read, ReadRegWrapper, Write, WriteRegWrapper,
22};
23
24const EVENT_MANAGER_INDEX: usize = 0;
25
26type LiteXTimerEV<'a, R> = LiteXEventManager<
27 'a,
28 u8,
29 <R as LiteXSoCRegisterConfiguration>::ReadOnly8,
30 <R as LiteXSoCRegisterConfiguration>::ReadWrite8,
31 <R as LiteXSoCRegisterConfiguration>::ReadWrite8,
32>;
33
34/// [`LiteXTimer`] register layout
35#[repr(C)]
36pub struct LiteXTimerRegisters<R: LiteXSoCRegisterConfiguration> {
37 /// Load value when Timer is (re-)enabled. In One-Shot mode, the
38 /// value written to this register specifies the Timer's duration
39 /// in clock cycles.
40 load: R::ReadWrite32,
41 /// Reload value when Timer reaches `0`. In Periodic mode, the
42 /// value written to this register specify the Timer's period in
43 /// clock cycles.
44 reload: R::ReadWrite32,
45 /// Enable flag of the Timer. Set this flag to `1` to enable/start
46 /// the Timer. Set to `0` to disable the Timer.
47 en: R::ReadWrite8,
48 /// Update trigger for the current countdown value. A write to
49 /// this register latches the current countdown value to `value`
50 /// register.
51 update_value: R::ReadWrite8,
52 /// Latched countdown value. This value is updated by writing to
53 /// `update_value`.
54 value: R::ReadWrite32,
55 /// LiteX EventManager status register
56 ev_status: R::ReadOnly8,
57 /// LiteX EventManager pending register
58 ev_pending: R::ReadWrite8,
59 /// LiteX EventManager pending register
60 ev_enable: R::ReadWrite8,
61 /// Write a `1` to latch current Uptime cycles to `uptime_cycles`
62 /// register.
63 ///
64 /// # Optional register
65 ///
66 /// This register is only present if the SoC was configured with
67 /// `timer_update = True`. Therefore, it's only indirectly
68 /// accessed by the [`LiteXTimerUptime`] struct,
69 /// which a board will need to construct separately.
70 uptime_latch: R::ReadWrite8,
71 /// Latched uptime since power-up (in `sys_clk` cycles)
72 ///
73 /// # Optional register
74 ///
75 /// This register is only present if the SoC was configured with
76 /// `timer_update = True`. Therefore, it's only indirectly
77 /// accessed by the [`LiteXTimerUptime`] struct,
78 /// which a board will need to construct separately.
79 uptime: R::ReadOnly64,
80}
81
82impl<R: LiteXSoCRegisterConfiguration> LiteXTimerRegisters<R> {
83 fn ev(&self) -> LiteXTimerEV<'_, R> {
84 LiteXTimerEV::<R>::new(&self.ev_status, &self.ev_pending, &self.ev_enable)
85 }
86}
87
88register_bitfields![u8,
89 en [
90 enable OFFSET(0) NUMBITS(1) []
91 ],
92 update_value [
93 latch_value OFFSET(0) NUMBITS(1) []
94 ],
95 uptime_latch [
96 latch_value OFFSET(0) NUMBITS(1) []
97 ]
98];
99
100/// LiteX hardware timer core uptime extension
101///
102/// Defined in
103/// [`litex/soc/cores/timer.py`](https://github.com/enjoy-digital/litex/blob/master/litex/soc/cores/timer.py).
104///
105/// This hardware peripheral can optionally feature an uptime
106/// register, which counts the current ticks since power on. This
107/// wrapper can be used to provide users a safe way to access this
108/// register through the [`Time::now`] interface, if it is available
109/// in hardware.
110pub struct LiteXTimerUptime<'t, R: LiteXSoCRegisterConfiguration, F: Frequency> {
111 timer: &'t LiteXTimer<'t, R, F>,
112}
113
114impl<'t, R: LiteXSoCRegisterConfiguration, F: Frequency> LiteXTimerUptime<'t, R, F> {
115 /// Contruct a new [`LiteXTimerUptime`] wrapper
116 ///
117 /// The function is marked `unsafe` as it will provide a safe
118 /// method to access the `uptime`-register on the underlying
119 /// [`LiteXTimer`]. If this register is not present (i.e. the
120 /// uptime feature is disabled), this will result in undefined
121 /// behavior.
122 pub const unsafe fn new(timer: &'t LiteXTimer<'t, R, F>) -> LiteXTimerUptime<'t, R, F> {
123 LiteXTimerUptime { timer }
124 }
125}
126
127impl<R: LiteXSoCRegisterConfiguration, F: Frequency> Time for LiteXTimerUptime<'_, R, F> {
128 type Frequency = F;
129 type Ticks = Ticks64;
130
131 /// Return the current ticks since sytem power on
132 fn now(&self) -> Self::Ticks {
133 unsafe { self.timer.uptime() }
134 }
135}
136
137/// LiteX hardware timer core
138///
139/// Defined in
140/// [`litex/soc/cores/timer.py`](https://github.com/enjoy-digital/litex/blob/master/litex/soc/cores/timer.py).
141///
142/// This peripheral supports counting down a certain interval, either
143/// as a oneshot timer or in a repeated fashion.
144///
145/// # Uptime extension
146///
147/// LiteX timers can _optionally_ be extended to feature an uptime
148/// register integrated into the timer peripheral, monotonically
149/// counting the clock ticks and wrapping at the maximum value.
150///
151/// The uptime register may have a different width as the [`Timer`]
152/// peripheral itself, hence it must be implemented using a separate
153/// type. The type must contain a reference to this [`Timer`]
154/// instance, since the register is located on this register bank.
155///
156/// Since this extension is not always configured, the Timer features
157/// an _unsafe_ function to read the uptime. It must only be called by
158/// [`LiteXTimerUptime`] struct and only if the uptime has been
159/// configured.
160pub struct LiteXTimer<'a, R: LiteXSoCRegisterConfiguration, F: Frequency> {
161 registers: StaticRef<LiteXTimerRegisters<R>>,
162 client: OptionalCell<&'a dyn TimerClient>,
163 /// Variable to store whether an interval has been set at least
164 /// once (e.g. the timer has been started once)
165 interval_set: Cell<bool>,
166 _frequency: PhantomData<F>,
167}
168
169impl<R: LiteXSoCRegisterConfiguration, F: Frequency> LiteXTimer<'_, R, F> {
170 pub fn new(base: StaticRef<LiteXTimerRegisters<R>>) -> Self {
171 LiteXTimer {
172 registers: base,
173 client: OptionalCell::empty(),
174 interval_set: Cell::new(false),
175 _frequency: PhantomData,
176 }
177 }
178
179 /// Get the uptime register value.
180 ///
181 /// This function is marked as unsafe to avoid clients calling it,
182 /// if the underlying LiteX hardware timer does not feature the
183 /// uptime registers.
184 ///
185 /// Clients should use the [`LiteXTimerUptime`] wrapper instead,
186 /// which exposes this value as part of their
187 /// [`Time::now`] implementation.
188 unsafe fn uptime(&self) -> Ticks64 {
189 WriteRegWrapper::wrap(&self.registers.uptime_latch).write(uptime_latch::latch_value::SET);
190 self.registers.uptime.get().into()
191 }
192
193 pub fn service_interrupt(&self) {
194 // Check whether the event is still asserted.
195 //
196 // It could be that an interrupt was fired and the timer was
197 // reset / disabled in the mean time.
198 if self.registers.ev().event_asserted(EVENT_MANAGER_INDEX) {
199 if self.registers.reload.get() == 0 {
200 // Timer is a oneshot
201
202 // If the timer really is a oneshot, the remaining time must be 0
203 WriteRegWrapper::wrap(&self.registers.update_value)
204 .write(update_value::latch_value::SET);
205 assert!(self.registers.value.get() == 0);
206
207 // Completely disable and make sure it doesn't generate
208 // more interrupts until it is started again
209 let _ = self.cancel();
210 } else {
211 // Timer is repeating
212 //
213 // Simply only acknowledge the current interrupt
214 self.registers.ev().clear_event(EVENT_MANAGER_INDEX);
215 }
216
217 // In any case, perform a callback to the client
218 self.client.map(|client| {
219 client.timer();
220 });
221 }
222 }
223
224 fn start_timer(&self, tics: u32, repeat_ticks: Option<u32>) {
225 // If the timer is already enabled, cancel it and disable all
226 // interrupts
227 if self.is_enabled() {
228 let _ = self.cancel();
229 }
230
231 if let Some(reload) = repeat_ticks {
232 // Reload the timer with `reload_ticks` after it has
233 // expired (reloading mode)
234 self.registers.reload.set(reload);
235 } else {
236 // Prevent reloading of the timer (oneshot mode)
237 self.registers.reload.set(0);
238 }
239
240 // Load the countdown in ticks (this register won't get
241 // overwritten, hence it is a safe reference to the original
242 // tics value which we don't need to save locally)
243 self.registers.load.set(tics);
244
245 // Since the timer is disabled, the load register is
246 // immediately mirrored to the internal register, which will
247 // cause the event source to be off.
248 //
249 // It is important for the internal value to be non-zero prior
250 // to enabling the event, as it could otherwise immediately
251 // generate an event again (which might be desired for a timer
252 // with tics == 0).
253 //
254 // Clear any pending event of a previous timer, then enable
255 // the event.
256 self.registers.ev().clear_event(EVENT_MANAGER_INDEX);
257 self.registers.ev().enable_event(EVENT_MANAGER_INDEX);
258
259 // The timer has been started at least once by now
260 self.interval_set.set(true);
261
262 // Start the timer
263 WriteRegWrapper::wrap(&self.registers.en).write(en::enable::SET);
264 }
265}
266
267impl<R: LiteXSoCRegisterConfiguration, F: Frequency> Time for LiteXTimer<'_, R, F> {
268 type Frequency = F;
269 type Ticks = Ticks32;
270
271 fn now(&self) -> Self::Ticks {
272 WriteRegWrapper::wrap(&self.registers.update_value).write(update_value::latch_value::SET);
273 self.registers.value.get().into()
274 }
275}
276
277impl<'a, R: LiteXSoCRegisterConfiguration, F: Frequency> Timer<'a> for LiteXTimer<'a, R, F> {
278 fn set_timer_client(&self, client: &'a dyn TimerClient) {
279 self.client.set(client);
280 }
281
282 fn oneshot(&self, interval: Self::Ticks) -> Self::Ticks {
283 self.start_timer(interval.into_u32(), None);
284 interval
285 }
286
287 fn repeating(&self, interval: Self::Ticks) -> Self::Ticks {
288 self.start_timer(interval.into_u32(), Some(interval.into_u32()));
289 interval
290 }
291
292 fn interval(&self) -> Option<Self::Ticks> {
293 if self.interval_set.get() {
294 // The timer has been started at least once, so we can
295 // trust that the `load` register will have the interval
296 // of the last requested timer.
297 Some(self.registers.load.get().into())
298 } else {
299 // The timer was never started and so does not have an
300 // interval set.
301 None
302 }
303 }
304
305 fn is_repeating(&self) -> bool {
306 // The timer is repeating timer if it has been started at
307 // least once and the reload register is non-zero
308 self.interval_set.get() && self.registers.reload.get() != 0
309 }
310
311 fn is_oneshot(&self) -> bool {
312 // The timer is a oneshot if it has been started at least once
313 // and the reload register is 0
314 self.interval_set.get() && self.registers.reload.get() == 0
315 }
316
317 fn time_remaining(&self) -> Option<Self::Ticks> {
318 if self.is_enabled() {
319 WriteRegWrapper::wrap(&self.registers.update_value)
320 .write(update_value::latch_value::SET);
321 Some(self.registers.value.get().into())
322 } else {
323 None
324 }
325 }
326
327 fn is_enabled(&self) -> bool {
328 ReadRegWrapper::wrap(&self.registers.en).is_set(en::enable)
329 }
330
331 fn cancel(&self) -> Result<(), ErrorCode> {
332 // Prevent the event source from generating new interrupts
333 self.registers.ev().disable_event(EVENT_MANAGER_INDEX);
334
335 // Stop the timer
336 WriteRegWrapper::wrap(&self.registers.en).write(en::enable::CLEAR);
337
338 // Clear any previous event
339 self.registers.ev().clear_event(EVENT_MANAGER_INDEX);
340
341 Ok(())
342 }
343}
344
345/// LiteX alarm implementation, based on [`LiteXTimer`] and
346/// [`LiteXTimerUptime`]
347///
348/// LiteX does not have an [`Alarm`] compatible hardware peripheral,
349/// so an [`Alarm`] is emulated using a repeatedly set [`LiteXTimer`],
350/// comparing the current time against the [`LiteXTimerUptime`] (which
351/// is also exposed as [`Time::now`].
352pub struct LiteXAlarm<'t, 'c, R: LiteXSoCRegisterConfiguration, F: Frequency> {
353 uptime: &'t LiteXTimerUptime<'t, R, F>,
354 timer: &'t LiteXTimer<'t, R, F>,
355 alarm_client: OptionalCell<&'c dyn AlarmClient>,
356 reference_time: Cell<<LiteXTimerUptime<'t, R, F> as Time>::Ticks>,
357 alarm_time: OptionalCell<<LiteXTimerUptime<'t, R, F> as Time>::Ticks>,
358}
359
360impl<'t, 'c, R: LiteXSoCRegisterConfiguration, F: Frequency> LiteXAlarm<'t, 'c, R, F> {
361 pub fn new(
362 uptime: &'t LiteXTimerUptime<'t, R, F>,
363 timer: &'t LiteXTimer<'t, R, F>,
364 ) -> LiteXAlarm<'t, 'c, R, F> {
365 LiteXAlarm {
366 uptime,
367 timer,
368 alarm_client: OptionalCell::empty(),
369 reference_time: Cell::new((0_u32).into()),
370 alarm_time: OptionalCell::empty(),
371 }
372 }
373
374 /// Initialize the [`LiteXAlarm`]
375 ///
376 /// This will register itself as a client for the underlying
377 /// [`LiteXTimer`].
378 pub fn initialize(&'t self) {
379 self.timer.set_timer_client(self);
380 }
381
382 fn timer_tick(&self, is_callback: bool) {
383 // Check whether we've already reached the alarm time,
384 // otherwise set the timer to the difference or the max value
385 // respectively
386
387 // This function gets called when initially setting the alarm
388 // and for every fired LiteXTimer oneshot operation. Since we
389 // can't call a client-callback within the same call stack of
390 // the initial `set_alarm` call, we need to wait on the timer
391 // at least once (even if the alarm time has already passed).
392
393 let reference = self.reference_time.get();
394 let alarm_time = self.alarm_time.unwrap_or_panic(); // Unwrap fail = alarm not set
395
396 if !self.now().within_range(reference, alarm_time) {
397 // It's time, ring the alarm
398
399 // Make sure we're in an callback, otherwise set the timer
400 // to a very small value to trigger a Timer interrupt
401 // immediately
402 if is_callback {
403 // Reset the alarm to 0
404 self.alarm_time.clear();
405
406 // Call the client
407 self.alarm_client.map(|c| c.alarm());
408 } else {
409 // Trigger an interrupt one tick from now, which will
410 // call this function again
411 self.timer.oneshot((1_u32).into());
412 }
413 } else {
414 // It's not yet time to call the client, set the timer
415 // again
416
417 let remaining = alarm_time.wrapping_sub(self.now());
418 if remaining < (u32::MAX as u64).into() {
419 // The remaining time fits into a single timer
420 // invocation
421 self.timer.oneshot(remaining.into_u32().into());
422 } else {
423 // The remaining time is longer than a single timer
424 // invocation can cover, set the timer to the maximum
425 // value
426 self.timer.oneshot(u32::MAX.into());
427 }
428 }
429 }
430}
431
432impl<'t, R: LiteXSoCRegisterConfiguration, F: Frequency> Time for LiteXAlarm<'t, '_, R, F> {
433 type Frequency = F;
434 type Ticks = <LiteXTimerUptime<'t, R, F> as Time>::Ticks;
435
436 fn now(&self) -> Self::Ticks {
437 self.uptime.now()
438 }
439}
440
441impl<'c, R: LiteXSoCRegisterConfiguration, F: Frequency> Alarm<'c> for LiteXAlarm<'_, 'c, R, F> {
442 fn set_alarm_client(&self, client: &'c dyn AlarmClient) {
443 self.alarm_client.set(client);
444 }
445
446 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
447 // Cancel any pending alarm
448 if self.is_armed() {
449 let _ = self.disarm();
450 }
451
452 // Store both the reference and alarm time (required for
453 // reliable comparison with wrapping time)
454 self.reference_time.set(reference);
455 self.alarm_time.set(reference.wrapping_add(dt));
456
457 // Set the underlying timer at least once (`is_callback =
458 // false`) to trigger a callback to the client in a different
459 // call stack
460 self.timer_tick(false);
461 }
462
463 fn get_alarm(&self) -> Self::Ticks {
464 // Undefined at boot, so 0
465 self.alarm_time.unwrap_or((0_u32).into())
466 }
467
468 fn is_armed(&self) -> bool {
469 self.alarm_time.is_some()
470 }
471
472 fn disarm(&self) -> Result<(), ErrorCode> {
473 let _ = self.timer.cancel();
474 self.alarm_time.clear();
475
476 Ok(())
477 }
478
479 fn minimum_dt(&self) -> Self::Ticks {
480 (1_u32).into()
481 }
482}
483
484impl<R: LiteXSoCRegisterConfiguration, F: Frequency> TimerClient for LiteXAlarm<'_, '_, R, F> {
485 fn timer(&self) {
486 self.timer_tick(true);
487 }
488}