1use 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    tasks_start: WriteOnly<u32, Task::Register>,
22    tasks_stop: WriteOnly<u32, Task::Register>,
24    tasks_clear: WriteOnly<u32, Task::Register>,
26    tasks_trigovrflw: WriteOnly<u32, Task::Register>,
28    _reserved0: [u8; 240],
29    events_tick: ReadWrite<u32, Event::Register>,
31    events_ovrflw: ReadWrite<u32, Event::Register>,
33    _reserved1: [u8; 56],
34    events_compare: [ReadWrite<u32, Event::Register>; 4],
36    _reserved2: [u8; 436],
37    intenset: ReadWrite<u32, Inte::Register>,
39    intenclr: ReadWrite<u32, Inte::Register>,
41    _reserved3: [u8; 52],
42    evten: ReadWrite<u32, Inte::Register>,
44    evtenset: ReadWrite<u32, Inte::Register>,
46    evtenclr: ReadWrite<u32, Inte::Register>,
48    _reserved4: [u8; 440],
49    counter: ReadOnly<u32, Counter::Register>,
51    prescaler: ReadWrite<u32, Prescaler::Register>,
54    _reserved5: [u8; 52],
55    cc: [ReadWrite<u32, Counter::Register>; 4],
57    _reserved6: [u8; 2732],
58    power: ReadWrite<u32>,
60}
61
62register_bitfields![u32,
63    Inte [
64        TICK 0,
66        OVRFLW 1,
68        COMPARE0 16,
70        COMPARE1 17,
72        COMPARE2 18,
74        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.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        Self::Ticks::from(10)
204    }
205}