sam4l/
ast.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//! Implementation of a single hardware timer.
6//!
7//! - Author: Amit Levy <levya@cs.stanford.edu>
8//! - Author: Philip Levis <pal@cs.stanford.edu>
9//! - Date: September 17, 2020
10
11use crate::pm::{self, PBDClock};
12use kernel::hil::time::{self, Ticks};
13use kernel::hil::Controller;
14use kernel::utilities::cells::OptionalCell;
15use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
16use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
17use kernel::utilities::StaticRef;
18use kernel::ErrorCode;
19
20/// Minimum number of clock tics to make sure ALARM0 register is synchronized
21///
22/// The datasheet has the following ominous language (Section 19.5.3.2):
23///
24/// > Because of synchronization, the transfer of the alarm value will not
25/// > happen immediately. When changing/setting the alarm value, the user must
26/// > make sure that the counter will not count the selected alarm value before
27/// > the value is transferred to the register. In that case, the first alarm
28/// > interrupt after the change will not be triggered.
29///
30/// In practice, we've observed that when the alarm is set for a counter value
31/// less than or equal to four tics ahead of the current counter value, the
32/// alarm interrupt doesn't fire. Thus, we simply round up to at least eight
33/// tics. Seems safe enough and in practice has seemed to work.
34const ALARM0_SYNC_TICS: u32 = 8;
35
36#[repr(C)]
37struct AstRegisters {
38    cr: ReadWrite<u32, Control::Register>,
39    cv: ReadWrite<u32, Value::Register>,
40    sr: ReadOnly<u32, Status::Register>,
41    scr: WriteOnly<u32, Interrupt::Register>,
42    ier: WriteOnly<u32, Interrupt::Register>,
43    idr: WriteOnly<u32, Interrupt::Register>,
44    imr: ReadOnly<u32, Interrupt::Register>,
45    wer: ReadWrite<u32, Event::Register>,
46    // 0x20
47    ar0: ReadWrite<u32, Value::Register>,
48    ar1: ReadWrite<u32, Value::Register>,
49    _reserved0: [u32; 2],
50    pir0: ReadWrite<u32, PeriodicInterval::Register>,
51    pir1: ReadWrite<u32, PeriodicInterval::Register>,
52    _reserved1: [u32; 2],
53    // 0x40
54    clock: ReadWrite<u32, ClockControl::Register>,
55    dtr: ReadWrite<u32, DigitalTuner::Register>,
56    eve: WriteOnly<u32, Event::Register>,
57    evd: WriteOnly<u32, Event::Register>,
58    evm: ReadOnly<u32, Event::Register>,
59    calv: ReadWrite<u32, Calendar::Register>, // we leave out parameter and version
60}
61
62register_bitfields![u32,
63    Control [
64        /// Prescalar Select
65        PSEL OFFSET(16) NUMBITS(5) [],
66        /// Clear on Alarm 1
67        CA1  OFFSET(9) NUMBITS(1) [
68            NoClearCounter = 0,
69            ClearCounter = 1
70        ],
71        /// Clear on Alarm 0
72        CA0  OFFSET(8) NUMBITS(1) [
73            NoClearCounter = 0,
74            ClearCounter = 1
75        ],
76        /// Calendar Mode
77        CAL  OFFSET(2) NUMBITS(1) [
78            CounterMode = 0,
79            CalendarMode = 1
80        ],
81        /// Prescalar Clear
82        PCLR OFFSET(1) NUMBITS(1) [],
83        /// Enable
84        EN   OFFSET(0) NUMBITS(1) [
85            Disable = 0,
86            Enable = 1
87        ]
88    ],
89
90    Value [
91        VALUE OFFSET(0) NUMBITS(32) []
92    ],
93
94    Status [
95        /// Clock Ready
96        CLKRDY 29,
97        /// Clock Busy
98        CLKBUSY 28,
99        /// AST Ready
100        READY 25,
101        /// AST Busy
102        BUSY 24,
103        /// Periodic 0
104        PER0 16,
105        /// Alarm 0
106        ALARM0 8,
107        /// Overflow
108        OVF 0
109    ],
110
111    Interrupt [
112        /// Clock Ready
113        CLKRDY 29,
114        /// AST Ready
115        READY 25,
116        /// Periodic 0
117        PER0 16,
118        /// Alarm 0
119        ALARM0 8,
120        /// Overflow
121        OVF 0
122    ],
123
124    Event [
125        /// Periodic 0
126        PER0 16,
127        /// Alarm 0
128        ALARM0 8,
129        /// Overflow
130        OVF 0
131    ],
132
133    PeriodicInterval [
134        /// Interval Select
135        INSEL OFFSET(0) NUMBITS(5) []
136    ],
137
138    ClockControl [
139        /// Clock Source Selection
140        CSSEL OFFSET(8) NUMBITS(3) [
141            RCSYS = 0,
142            OSC32 = 1,
143            APBClock = 2,
144            GCLK = 3,
145            Clk1k = 4
146        ],
147        /// Clock Enable
148        CEN   OFFSET(0) NUMBITS(1) [
149            Disable = 0,
150            Enable = 1
151        ]
152    ],
153
154    DigitalTuner [
155        VALUE OFFSET(8) NUMBITS(8) [],
156        ADD   OFFSET(5) NUMBITS(1) [],
157        EXP   OFFSET(0) NUMBITS(5) []
158    ],
159
160    Calendar [
161        YEAR  OFFSET(26) NUMBITS(6) [],
162        MONTH OFFSET(22) NUMBITS(4) [],
163        DAY   OFFSET(17) NUMBITS(5) [],
164        HOUR  OFFSET(12) NUMBITS(5) [],
165        MIN   OFFSET( 6) NUMBITS(6) [],
166        SEC   OFFSET( 0) NUMBITS(6) []
167    ]
168];
169
170const AST_ADDRESS: StaticRef<AstRegisters> =
171    unsafe { StaticRef::new(0x400F0800 as *const AstRegisters) };
172
173pub struct Ast<'a> {
174    registers: StaticRef<AstRegisters>,
175    callback: OptionalCell<&'a dyn time::AlarmClient>,
176}
177
178impl Ast<'_> {
179    pub const fn new() -> Self {
180        Self {
181            registers: AST_ADDRESS,
182            callback: OptionalCell::empty(),
183        }
184    }
185}
186
187impl Controller for Ast<'_> {
188    type Config = &'static dyn time::AlarmClient;
189
190    fn configure(&self, client: Self::Config) {
191        self.callback.set(client);
192
193        pm::enable_clock(pm::Clock::PBD(PBDClock::AST));
194        self.select_clock(Clock::ClockOsc32);
195        self.disable();
196        self.disable_alarm_irq();
197        self.set_prescalar(0); // 32KHz / (2^(0 + 1)) = 16KHz
198        self.enable_alarm_wake();
199
200        self.clear_alarm();
201    }
202}
203
204#[repr(usize)]
205#[allow(dead_code)]
206enum Clock {
207    ClockRCSys = 0,
208    ClockOsc32 = 1,
209    ClockAPB = 2,
210    ClockGclk2 = 3,
211    Clock1K = 4,
212}
213
214impl Ast<'_> {
215    fn clock_busy(&self) -> bool {
216        self.registers.sr.is_set(Status::CLKBUSY)
217    }
218
219    fn busy(&self) -> bool {
220        self.registers.sr.is_set(Status::BUSY)
221    }
222
223    /// Clears the alarm bit in the status register (indicating the alarm value
224    /// has been reached).
225    fn clear_alarm(&self) {
226        while self.busy() {}
227        self.registers.scr.write(Interrupt::ALARM0::SET);
228        while self.busy() {}
229    }
230
231    // Configure the clock to use to drive the AST
232    fn select_clock(&self, clock: Clock) {
233        // Disable clock by setting first bit to zero
234        while self.clock_busy() {}
235        self.registers.clock.modify(ClockControl::CEN::CLEAR);
236        while self.clock_busy() {}
237
238        // Select clock
239        self.registers
240            .clock
241            .write(ClockControl::CSSEL.val(clock as u32));
242        while self.clock_busy() {}
243
244        // Re-enable clock
245        self.registers.clock.modify(ClockControl::CEN::SET);
246        while self.clock_busy() {}
247    }
248
249    /// Enables the AST registers
250    fn enable(&self) {
251        while self.busy() {}
252        self.registers.cr.modify(Control::EN::SET);
253        while self.busy() {}
254    }
255
256    /// Disable the AST registers
257    fn disable(&self) {
258        while self.busy() {}
259        self.registers.cr.modify(Control::EN::CLEAR);
260        while self.busy() {}
261    }
262
263    fn is_enabled(&self) -> bool {
264        let regs: &AstRegisters = &self.registers;
265        while self.busy() {}
266        regs.cr.is_set(Control::EN)
267    }
268
269    /// Returns if an alarm is currently set
270    fn is_alarm_enabled(&self) -> bool {
271        while self.busy() {}
272        self.registers.sr.is_set(Status::ALARM0)
273    }
274
275    fn set_prescalar(&self, val: u8) {
276        while self.busy() {}
277        self.registers.cr.modify(Control::PSEL.val(val as u32));
278        while self.busy() {}
279    }
280
281    fn enable_alarm_irq(&self) {
282        self.registers.ier.write(Interrupt::ALARM0::SET);
283    }
284
285    fn disable_alarm_irq(&self) {
286        self.registers.idr.write(Interrupt::ALARM0::SET);
287    }
288
289    fn enable_alarm_wake(&self) {
290        while self.busy() {}
291        self.registers.wer.modify(Event::ALARM0::SET);
292        while self.busy() {}
293    }
294
295    fn get_counter(&self) -> u32 {
296        while self.busy() {}
297        self.registers.cv.read(Value::VALUE)
298    }
299
300    fn set_counter(&self, val: u32) {
301        let regs: &AstRegisters = &self.registers;
302        while self.busy() {}
303        regs.cv.set(val);
304    }
305
306    pub fn handle_interrupt(&self) {
307        self.clear_alarm();
308        self.callback.map(|cb| {
309            cb.alarm();
310        });
311    }
312}
313
314impl time::Time for Ast<'_> {
315    type Frequency = time::Freq16KHz;
316    type Ticks = time::Ticks32;
317
318    fn now(&self) -> Self::Ticks {
319        Self::Ticks::from(self.get_counter())
320    }
321}
322
323impl<'a> time::Counter<'a> for Ast<'a> {
324    fn set_overflow_client(&self, _client: &'a dyn time::OverflowClient) {}
325
326    fn start(&self) -> Result<(), ErrorCode> {
327        self.enable();
328        Ok(())
329    }
330
331    fn stop(&self) -> Result<(), ErrorCode> {
332        self.disable();
333        Ok(())
334    }
335
336    fn reset(&self) -> Result<(), ErrorCode> {
337        self.set_counter(0);
338        Ok(())
339    }
340
341    fn is_running(&self) -> bool {
342        self.is_enabled()
343    }
344}
345
346impl<'a> time::Alarm<'a> for Ast<'a> {
347    fn set_alarm_client(&self, client: &'a dyn time::AlarmClient) {
348        self.callback.set(client);
349    }
350
351    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
352        let now = Self::Ticks::from(self.get_counter());
353        let mut expire = reference.wrapping_add(dt);
354        if !now.within_range(reference, expire) {
355            // We have already passed when: just fire ASAP
356            // Note this will also trigger the increment below
357            expire = now;
358        }
359
360        // Firing is too close in the future, delay it a bit
361        // to make sure we don't miss the tick
362        if expire.wrapping_sub(now).into_u32() <= ALARM0_SYNC_TICS {
363            expire = now.wrapping_add(Self::Ticks::from(ALARM0_SYNC_TICS));
364        }
365
366        // Clear any alarm event that may be pending before setting new alarm.
367        self.clear_alarm();
368
369        while self.busy() {}
370        self.registers
371            .ar0
372            .write(Value::VALUE.val(expire.into_u32()));
373
374        while self.busy() {}
375        self.enable_alarm_irq();
376        self.enable();
377    }
378
379    fn get_alarm(&self) -> Self::Ticks {
380        while self.busy() {}
381        Self::Ticks::from(self.registers.ar0.read(Value::VALUE))
382    }
383
384    fn disarm(&self) -> Result<(), ErrorCode> {
385        // After disabling the IRQ and clearing the alarm bit in the
386        // status register, the NVIC bit is also guaranteed to be clear.
387        self.disable_alarm_irq();
388        self.clear_alarm();
389        Ok(())
390    }
391
392    fn is_armed(&self) -> bool {
393        self.is_alarm_enabled()
394    }
395
396    fn minimum_dt(&self) -> Self::Ticks {
397        Self::Ticks::from(ALARM0_SYNC_TICS)
398    }
399}