nrf5x/
rtc.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//! RTC driver, nRF5X-family
6
7use core::cell::Cell;
8use kernel::hil::time::{self, Alarm, Ticks, Time};
9use kernel::utilities::cells::OptionalCell;
10use kernel::utilities::registers::interfaces::{Readable, Writeable};
11use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
12use kernel::utilities::StaticRef;
13use kernel::ErrorCode;
14
15const RTC1_BASE: StaticRef<RtcRegisters> =
16    unsafe { StaticRef::new(0x40011000 as *const RtcRegisters) };
17
18#[repr(C)]
19struct RtcRegisters {
20    /// Start RTC Counter.
21    tasks_start: WriteOnly<u32, Task::Register>,
22    /// Stop RTC Counter.
23    tasks_stop: WriteOnly<u32, Task::Register>,
24    /// Clear RTC Counter.
25    tasks_clear: WriteOnly<u32, Task::Register>,
26    /// Set COUNTER to 0xFFFFFFF0.
27    tasks_trigovrflw: WriteOnly<u32, Task::Register>,
28    _reserved0: [u8; 240],
29    /// Event on COUNTER increment.
30    events_tick: ReadWrite<u32, Event::Register>,
31    /// Event on COUNTER overflow.
32    events_ovrflw: ReadWrite<u32, Event::Register>,
33    _reserved1: [u8; 56],
34    /// Compare event on CC\[n\] match.
35    events_compare: [ReadWrite<u32, Event::Register>; 4],
36    _reserved2: [u8; 436],
37    /// Interrupt enable set register.
38    intenset: ReadWrite<u32, Inte::Register>,
39    /// Interrupt enable clear register.
40    intenclr: ReadWrite<u32, Inte::Register>,
41    _reserved3: [u8; 52],
42    /// Configures event enable routing to PPI for each RTC event.
43    evten: ReadWrite<u32, Inte::Register>,
44    /// Enable events routing to PPI.
45    evtenset: ReadWrite<u32, Inte::Register>,
46    /// Disable events routing to PPI.
47    evtenclr: ReadWrite<u32, Inte::Register>,
48    _reserved4: [u8; 440],
49    /// Current COUNTER value.
50    counter: ReadOnly<u32, Counter::Register>,
51    /// 12-bit prescaler for COUNTER frequency (32768/(PRESCALER+1)).
52    /// Must be written when RTC is stopped.
53    prescaler: ReadWrite<u32, Prescaler::Register>,
54    _reserved5: [u8; 52],
55    /// Capture/compare registers.
56    cc: [ReadWrite<u32, Counter::Register>; 4],
57    _reserved6: [u8; 2732],
58    /// Peripheral power control.
59    power: ReadWrite<u32>,
60}
61
62register_bitfields![u32,
63    Inte [
64        /// Enable interrupt on TICK event.
65        TICK 0,
66        /// Enable interrupt on OVRFLW event.
67        OVRFLW 1,
68        /// Enable interrupt on COMPARE\[0\] event.
69        COMPARE0 16,
70        /// Enable interrupt on COMPARE\[1\] event.
71        COMPARE1 17,
72        /// Enable interrupt on COMPARE\[2\] event.
73        COMPARE2 18,
74        /// Enable interrupt on COMPARE\[3\] event.
75        COMPARE3 19
76    ],
77    Prescaler [
78        PRESCALER OFFSET(0) NUMBITS(12)
79    ],
80    Task [
81        ENABLE 0
82    ],
83    Event [
84        READY 0
85    ],
86    Counter [
87        VALUE OFFSET(0) NUMBITS(24)
88    ]
89];
90
91pub struct Rtc<'a> {
92    registers: StaticRef<RtcRegisters>,
93    overflow_client: OptionalCell<&'a dyn time::OverflowClient>,
94    alarm_client: OptionalCell<&'a dyn time::AlarmClient>,
95    enabled: Cell<bool>,
96}
97
98impl Rtc<'_> {
99    pub const fn new() -> Self {
100        Self {
101            registers: RTC1_BASE,
102            overflow_client: OptionalCell::empty(),
103            alarm_client: OptionalCell::empty(),
104            enabled: Cell::new(false),
105        }
106    }
107
108    pub fn handle_interrupt(&self) {
109        if self.registers.events_ovrflw.is_set(Event::READY) {
110            self.registers.events_ovrflw.write(Event::READY::CLEAR);
111            self.overflow_client.map(|client| client.overflow());
112        }
113        if self.registers.events_compare[0].is_set(Event::READY) {
114            self.registers.intenclr.write(Inte::COMPARE0::SET);
115            self.registers.events_compare[0].write(Event::READY::CLEAR);
116            self.alarm_client.map(|client| {
117                client.alarm();
118            });
119        }
120    }
121}
122
123impl Time for Rtc<'_> {
124    type Frequency = time::Freq32KHz;
125    type Ticks = time::Ticks24;
126
127    fn now(&self) -> Self::Ticks {
128        Self::Ticks::from(self.registers.counter.read(Counter::VALUE))
129    }
130}
131
132impl<'a> time::Counter<'a> for Rtc<'a> {
133    fn set_overflow_client(&self, client: &'a dyn time::OverflowClient) {
134        self.overflow_client.set(client);
135        self.registers.intenset.write(Inte::OVRFLW::SET);
136    }
137
138    fn start(&self) -> Result<(), ErrorCode> {
139        self.registers.prescaler.write(Prescaler::PRESCALER.val(0));
140        self.registers.tasks_start.write(Task::ENABLE::SET);
141        self.enabled.set(true);
142        Ok(())
143    }
144
145    fn stop(&self) -> Result<(), ErrorCode> {
146        //self.registers.cc[0].write(Counter::VALUE.val(0));
147        self.registers.tasks_stop.write(Task::ENABLE::SET);
148        self.enabled.set(false);
149        Ok(())
150    }
151
152    fn reset(&self) -> Result<(), ErrorCode> {
153        self.registers.tasks_clear.write(Task::ENABLE::SET);
154        Ok(())
155    }
156
157    fn is_running(&self) -> bool {
158        self.enabled.get()
159    }
160}
161
162impl<'a> Alarm<'a> for Rtc<'a> {
163    fn set_alarm_client(&self, client: &'a dyn time::AlarmClient) {
164        self.alarm_client.set(client);
165    }
166
167    fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
168        const SYNC_TICS: u32 = 2;
169        let regs = &*self.registers;
170
171        let mut expire = reference.wrapping_add(dt);
172
173        let now = self.now();
174        let earliest_possible = now.wrapping_add(Self::Ticks::from(SYNC_TICS));
175
176        if !now.within_range(reference, expire) || expire.wrapping_sub(now).into_u32() <= SYNC_TICS
177        {
178            expire = earliest_possible;
179        }
180
181        regs.cc[0].write(Counter::VALUE.val(expire.into_u32()));
182        regs.events_compare[0].write(Event::READY::CLEAR);
183        regs.intenset.write(Inte::COMPARE0::SET);
184    }
185
186    fn get_alarm(&self) -> Self::Ticks {
187        Self::Ticks::from(self.registers.cc[0].read(Counter::VALUE))
188    }
189
190    fn disarm(&self) -> Result<(), ErrorCode> {
191        let regs = &*self.registers;
192        regs.intenclr.write(Inte::COMPARE0::SET);
193        regs.events_compare[0].write(Event::READY::CLEAR);
194        Ok(())
195    }
196
197    fn is_armed(&self) -> bool {
198        self.registers.evten.is_set(Inte::COMPARE0)
199    }
200
201    fn minimum_dt(&self) -> Self::Ticks {
202        // TODO: not tested, arbitrary value
203        Self::Ticks::from(10)
204    }
205}