rp2040/
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
5use cortexm0p::support::atomic;
6use kernel::hil;
7use kernel::hil::time::{Alarm, Ticks, Ticks32, Time};
8use kernel::utilities::cells::OptionalCell;
9use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
10use kernel::utilities::registers::{
11    register_bitfields, register_structs, ReadOnly, ReadWrite, WriteOnly,
12};
13use kernel::utilities::StaticRef;
14use kernel::ErrorCode;
15
16use crate::interrupts::TIMER_IRQ_0;
17
18register_structs! {
19    /// Controls time and alarms\n
20    /// time is a 64 bit value indicating the time in usec since power-on\n
21    /// timeh is the top 32 bits of time & timel is the bottom 32 bits\n
22    /// to change time write to timelw before timehw\n
23    /// to read time read from timelr before timehr\n
24    /// An alarm is set by setting alarm_enable and writing to the corresponding
25    /// When an alarm is pending, the corresponding alarm_running signal will be
26    /// An alarm can be cancelled before it has finished by clearing the alarm_e
27    /// When an alarm fires, the corresponding alarm_irq is set and alarm_runnin
28    /// To clear the interrupt write a 1 to the corresponding alarm_irq
29    TimerRegisters {
30        /// Write to bits 63:32 of time\n
31        /// always write timelw before timehw
32        (0x000 => timehw: WriteOnly<u32, TIMEHW::Register>),
33        /// Write to bits 31:0 of time\n
34        /// writes do not get copied to time until timehw is written
35        (0x004 => timelw: WriteOnly<u32, TIMELW::Register>),
36        /// Read from bits 63:32 of time\n
37        /// always read timelr before timehr
38        (0x008 => timehr: ReadOnly<u32, TIMEHR::Register>),
39        /// Read from bits 31:0 of time
40        (0x00C => timelr: ReadOnly<u32, TIMELR::Register>),
41        /// Arm alarm 0, and configure the time it will fire.\n
42        /// Once armed, the alarm fires when TIMER_ALARM0 == TIMELR.\n
43        /// The alarm will disarm itself once it fires, and can\n
44        /// be disarmed early using the ARMED status register.
45        (0x010 => alarm0: ReadWrite<u32, ALARM0::Register>),
46        /// Arm alarm 1, and configure the time it will fire.\n
47        /// Once armed, the alarm fires when TIMER_ALARM1 == TIMELR.\n
48        /// The alarm will disarm itself once it fires, and can\n
49        /// be disarmed early using the ARMED status register.
50        (0x014 => alarm1: ReadWrite<u32, ALARM1::Register>),
51        /// Arm alarm 2, and configure the time it will fire.\n
52        /// Once armed, the alarm fires when TIMER_ALARM2 == TIMELR.\n
53        /// The alarm will disarm itself once it fires, and can\n
54        /// be disarmed early using the ARMED status register.
55        (0x018 => alarm2: ReadWrite<u32, ALARM2::Register>),
56        /// Arm alarm 3, and configure the time it will fire.\n
57        /// Once armed, the alarm fires when TIMER_ALARM3 == TIMELR.\n
58        /// The alarm will disarm itself once it fires, and can\n
59        /// be disarmed early using the ARMED status register.
60        (0x01C => alarm3: ReadWrite<u32, ALARM3::Register>),
61        /// Indicates the armed/disarmed status of each alarm.\n
62        /// A write to the corresponding ALARMx register arms the alarm.\n
63        /// Alarms automatically disarm upon firing, but writing ones here\n
64        /// will disarm immediately without waiting to fire.
65        (0x020 => armed: ReadWrite<u32>),
66        /// Raw read from bits 63:32 of time (no side effects)
67        (0x024 => timerawh: ReadOnly<u32, TIMERAWH::Register>),
68        /// Raw read from bits 31:0 of time (no side effects)
69        (0x028 => timerawl: ReadOnly<u32, TIMERAWL::Register>),
70        /// Set bits high to enable pause when the corresponding debug ports are active
71        (0x02C => dbgpause: ReadWrite<u32, DBGPAUSE::Register>),
72        /// Set high to pause the timer
73        (0x030 => pause: ReadWrite<u32>),
74        /// Raw Interrupts
75        (0x034 => intr: ReadWrite<u32, INTR::Register>),
76        /// Interrupt Enable
77        (0x038 => inte: ReadWrite<u32, INTE::Register>),
78        /// Interrupt Force
79        (0x03C => intf: ReadWrite<u32, INTF::Register>),
80        /// Interrupt status after masking & forcing
81        (0x040 => ints: ReadWrite<u32, INTS::Register>),
82        (0x044 => @END),
83    }
84}
85register_bitfields![u32,
86TIMEHW [
87    VALUE OFFSET (0) NUMBITS (32) []
88],
89TIMELW [
90    VALUE OFFSET (0) NUMBITS (32) []
91],
92TIMEHR [
93    VALUE OFFSET (0) NUMBITS (32) []
94],
95TIMELR [
96    VALUE OFFSET (0) NUMBITS (32) []
97],
98ALARM0 [
99    VALUE OFFSET (0) NUMBITS (32) []
100],
101ALARM1 [
102    VALUE OFFSET (0) NUMBITS (32) []
103],
104ALARM2 [
105    VALUE OFFSET (0) NUMBITS (32) []
106],
107ALARM3 [
108    VALUE OFFSET (0) NUMBITS (32) []
109],
110ARMED [
111    ARMED OFFSET(0) NUMBITS(4) []
112],
113TIMERAWH [
114    VALUE OFFSET (0) NUMBITS (32) []
115],
116TIMERAWL [
117    VALUE OFFSET (0) NUMBITS (32) []
118],
119DBGPAUSE [
120    /// Pause when processor 1 is in debug mode
121    DBG1 OFFSET(2) NUMBITS(1) [],
122    /// Pause when processor 0 is in debug mode
123    DBG0 OFFSET(1) NUMBITS(1) []
124],
125PAUSE [
126
127    PAUSE OFFSET(0) NUMBITS(1) []
128],
129INTR [
130
131    ALARM_3 OFFSET(3) NUMBITS(1) [],
132
133    ALARM_2 OFFSET(2) NUMBITS(1) [],
134
135    ALARM_1 OFFSET(1) NUMBITS(1) [],
136
137    ALARM_0 OFFSET(0) NUMBITS(1) []
138],
139INTE [
140
141    ALARM_3 OFFSET(3) NUMBITS(1) [],
142
143    ALARM_2 OFFSET(2) NUMBITS(1) [],
144
145    ALARM_1 OFFSET(1) NUMBITS(1) [],
146
147    ALARM_0 OFFSET(0) NUMBITS(1) []
148],
149INTF [
150
151    ALARM_3 OFFSET(3) NUMBITS(1) [],
152
153    ALARM_2 OFFSET(2) NUMBITS(1) [],
154
155    ALARM_1 OFFSET(1) NUMBITS(1) [],
156
157    ALARM_0 OFFSET(0) NUMBITS(1) []
158],
159INTS [
160
161    ALARM_3 OFFSET(3) NUMBITS(1) [],
162
163    ALARM_2 OFFSET(2) NUMBITS(1) [],
164
165    ALARM_1 OFFSET(1) NUMBITS(1) [],
166
167    ALARM_0 OFFSET(0) NUMBITS(1) []
168]
169];
170const TIMER_BASE: StaticRef<TimerRegisters> =
171    unsafe { StaticRef::new(0x40054000 as *const TimerRegisters) };
172
173pub struct RPTimer<'a> {
174    registers: StaticRef<TimerRegisters>,
175    client: OptionalCell<&'a dyn hil::time::AlarmClient>,
176}
177
178impl<'a> RPTimer<'a> {
179    pub const fn new() -> RPTimer<'a> {
180        RPTimer {
181            registers: TIMER_BASE,
182            client: OptionalCell::empty(),
183        }
184    }
185
186    fn enable_interrupt(&self) {
187        self.registers.inte.modify(INTE::ALARM_0::SET);
188    }
189
190    fn disable_interrupt(&self) {
191        self.registers.inte.modify(INTE::ALARM_0::CLEAR);
192    }
193
194    fn enable_timer_interrupt(&self) {
195        // Even though setting the INTE::ALARM_0 bit should be enough to enable
196        // the interrupt firing, it seems that RP2040 requires manual NVIC
197        // enabling of the interrupt.
198        //
199        // Failing to do so results in the interrupt being set as pending but
200        // not fired. This means that the interrupt will be handled whenever the
201        // next kernel tasks are processed.
202        unsafe {
203            atomic(|| {
204                let n = cortexm0p::nvic::Nvic::new(TIMER_IRQ_0);
205                n.enable();
206            })
207        }
208    }
209
210    fn disable_timer_interrupt(&self) {
211        // Even though clearing the INTE::ALARM_0 bit should be enough to disable
212        // the interrupt firing, it seems that RP2040 requires manual NVIC
213        // disabling of the interrupt.
214        unsafe {
215            cortexm0p::nvic::Nvic::new(TIMER_IRQ_0).disable();
216        }
217    }
218
219    pub fn handle_interrupt(&self) {
220        self.registers.intr.modify(INTR::ALARM_0::SET);
221        self.client.map(|client| client.alarm());
222    }
223}
224
225impl Time for RPTimer<'_> {
226    type Frequency = hil::time::Freq1MHz;
227    type Ticks = Ticks32;
228
229    fn now(&self) -> Self::Ticks {
230        Self::Ticks::from(self.registers.timerawl.get())
231    }
232}
233
234impl<'a> Alarm<'a> for RPTimer<'a> {
235    fn set_alarm_client(&self, client: &'a dyn hil::time::AlarmClient) {
236        self.client.set(client);
237    }
238
239    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
240        let mut expire = reference.wrapping_add(dt);
241        let now = self.now();
242        if !now.within_range(reference, expire) {
243            expire = now;
244        }
245
246        if expire.wrapping_sub(now) < self.minimum_dt() {
247            expire = now.wrapping_add(self.minimum_dt());
248        }
249
250        self.registers.alarm0.set(expire.into_u32());
251        self.enable_timer_interrupt();
252        self.enable_interrupt();
253    }
254
255    fn get_alarm(&self) -> Self::Ticks {
256        Self::Ticks::from(self.registers.alarm0.get())
257    }
258
259    fn disarm(&self) -> Result<(), ErrorCode> {
260        self.registers.armed.set(1);
261        unsafe {
262            atomic(|| {
263                // Clear pending interrupts
264                cortexm0p::nvic::Nvic::new(TIMER_IRQ_0).clear_pending();
265            });
266        }
267        self.disable_interrupt();
268        self.disable_timer_interrupt();
269        Ok(())
270    }
271
272    fn is_armed(&self) -> bool {
273        let armed = self.registers.armed.get() & 0b0001;
274        if armed == 1 {
275            return true;
276        }
277        false
278    }
279
280    fn minimum_dt(&self) -> Self::Ticks {
281        Self::Ticks::from(50)
282    }
283}