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}