1use crate::pm::{self, PBDClock};
12use kernel::ErrorCode;
13use kernel::hil::Controller;
14use kernel::hil::time::{self, Ticks};
15use kernel::utilities::StaticRef;
16use kernel::utilities::cells::OptionalCell;
17use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
18use kernel::utilities::registers::{
19 ReadOnly, ReadWrite, WriteOnly, register_bitfields, register_structs,
20};
21
22const ALARM0_SYNC_TICS: u32 = 8;
37
38register_structs! {
39 AstRegisters {
40 (0x000 => cr: ReadWrite<u32, Control::Register>),
41 (0x004 => cv: ReadWrite<u32, Value::Register>),
42 (0x008 => sr: ReadOnly<u32, Status::Register>),
43 (0x00C => scr: WriteOnly<u32, Interrupt::Register>),
44 (0x010 => ier: WriteOnly<u32, Interrupt::Register>),
45 (0x014 => idr: WriteOnly<u32, Interrupt::Register>),
46 (0x018 => imr: ReadOnly<u32, Interrupt::Register>),
47 (0x01C => wer: ReadWrite<u32, Event::Register>),
48 (0x020 => ar0: ReadWrite<u32, Value::Register>),
49 (0x024 => ar1: ReadWrite<u32, Value::Register>),
50 (0x028 => _reserved0: [u32; 2]),
51 (0x030 => pir0: ReadWrite<u32, PeriodicInterval::Register>),
52 (0x034 => pir1: ReadWrite<u32, PeriodicInterval::Register>),
53 (0x038 => _reserved1: [u32; 2]),
54 (0x040 => clock: ReadWrite<u32, ClockControl::Register>),
55 (0x044 => dtr: ReadWrite<u32, DigitalTuner::Register>),
56 (0x048 => eve: WriteOnly<u32, Event::Register>),
57 (0x04C => evd: WriteOnly<u32, Event::Register>),
58 (0x050 => evm: ReadOnly<u32, Event::Register>),
59 (0x054 => calv: ReadWrite<u32, Calendar::Register>),
60 (0x058 => @END),
61 }
62}
63
64register_bitfields![u32,
65 Control [
66 PSEL OFFSET(16) NUMBITS(5) [],
68 CA1 OFFSET(9) NUMBITS(1) [
70 NoClearCounter = 0,
71 ClearCounter = 1
72 ],
73 CA0 OFFSET(8) NUMBITS(1) [
75 NoClearCounter = 0,
76 ClearCounter = 1
77 ],
78 CAL OFFSET(2) NUMBITS(1) [
80 CounterMode = 0,
81 CalendarMode = 1
82 ],
83 PCLR OFFSET(1) NUMBITS(1) [],
85 EN OFFSET(0) NUMBITS(1) [
87 Disable = 0,
88 Enable = 1
89 ]
90 ],
91
92 Value [
93 VALUE OFFSET(0) NUMBITS(32) []
94 ],
95
96 Status [
97 CLKRDY 29,
99 CLKBUSY 28,
101 READY 25,
103 BUSY 24,
105 PER0 16,
107 ALARM0 8,
109 OVF 0
111 ],
112
113 Interrupt [
114 CLKRDY 29,
116 READY 25,
118 PER0 16,
120 ALARM0 8,
122 OVF 0
124 ],
125
126 Event [
127 PER0 16,
129 ALARM0 8,
131 OVF 0
133 ],
134
135 PeriodicInterval [
136 INSEL OFFSET(0) NUMBITS(5) []
138 ],
139
140 ClockControl [
141 CSSEL OFFSET(8) NUMBITS(3) [
143 RCSYS = 0,
144 OSC32 = 1,
145 APBClock = 2,
146 GCLK = 3,
147 Clk1k = 4
148 ],
149 CEN OFFSET(0) NUMBITS(1) [
151 Disable = 0,
152 Enable = 1
153 ]
154 ],
155
156 DigitalTuner [
157 VALUE OFFSET(8) NUMBITS(8) [],
158 ADD OFFSET(5) NUMBITS(1) [],
159 EXP OFFSET(0) NUMBITS(5) []
160 ],
161
162 Calendar [
163 YEAR OFFSET(26) NUMBITS(6) [],
164 MONTH OFFSET(22) NUMBITS(4) [],
165 DAY OFFSET(17) NUMBITS(5) [],
166 HOUR OFFSET(12) NUMBITS(5) [],
167 MIN OFFSET( 6) NUMBITS(6) [],
168 SEC OFFSET( 0) NUMBITS(6) []
169 ]
170];
171
172const AST_ADDRESS: StaticRef<AstRegisters> =
173 unsafe { StaticRef::new(0x400F0800 as *const AstRegisters) };
174
175pub struct Ast<'a> {
176 registers: StaticRef<AstRegisters>,
177 callback: OptionalCell<&'a dyn time::AlarmClient>,
178}
179
180impl Ast<'_> {
181 pub const fn new() -> Self {
182 Self {
183 registers: AST_ADDRESS,
184 callback: OptionalCell::empty(),
185 }
186 }
187}
188
189impl Controller for Ast<'_> {
190 type Config = &'static dyn time::AlarmClient;
191
192 fn configure(&self, client: Self::Config) {
193 self.callback.set(client);
194
195 pm::enable_clock(pm::Clock::PBD(PBDClock::AST));
196 self.select_clock(Clock::ClockOsc32);
197 self.disable();
198 self.disable_alarm_irq();
199 self.set_prescalar(0); self.enable_alarm_wake();
201
202 self.clear_alarm();
203 }
204}
205
206#[repr(usize)]
207#[allow(dead_code)]
208enum Clock {
209 ClockRCSys = 0,
210 ClockOsc32 = 1,
211 ClockAPB = 2,
212 ClockGclk2 = 3,
213 Clock1K = 4,
214}
215
216impl Ast<'_> {
217 fn clock_busy(&self) -> bool {
218 self.registers.sr.is_set(Status::CLKBUSY)
219 }
220
221 fn busy(&self) -> bool {
222 self.registers.sr.is_set(Status::BUSY)
223 }
224
225 fn clear_alarm(&self) {
228 while self.busy() {}
229 self.registers.scr.write(Interrupt::ALARM0::SET);
230 while self.busy() {}
231 }
232
233 fn select_clock(&self, clock: Clock) {
235 while self.clock_busy() {}
237 self.registers.clock.modify(ClockControl::CEN::CLEAR);
238 while self.clock_busy() {}
239
240 self.registers
242 .clock
243 .write(ClockControl::CSSEL.val(clock as u32));
244 while self.clock_busy() {}
245
246 self.registers.clock.modify(ClockControl::CEN::SET);
248 while self.clock_busy() {}
249 }
250
251 fn enable(&self) {
253 while self.busy() {}
254 self.registers.cr.modify(Control::EN::SET);
255 while self.busy() {}
256 }
257
258 fn disable(&self) {
260 while self.busy() {}
261 self.registers.cr.modify(Control::EN::CLEAR);
262 while self.busy() {}
263 }
264
265 fn is_enabled(&self) -> bool {
266 let regs: &AstRegisters = &self.registers;
267 while self.busy() {}
268 regs.cr.is_set(Control::EN)
269 }
270
271 fn is_alarm_enabled(&self) -> bool {
273 while self.busy() {}
274 self.registers.sr.is_set(Status::ALARM0)
275 }
276
277 fn set_prescalar(&self, val: u8) {
278 while self.busy() {}
279 self.registers.cr.modify(Control::PSEL.val(val as u32));
280 while self.busy() {}
281 }
282
283 fn enable_alarm_irq(&self) {
284 self.registers.ier.write(Interrupt::ALARM0::SET);
285 }
286
287 fn disable_alarm_irq(&self) {
288 self.registers.idr.write(Interrupt::ALARM0::SET);
289 }
290
291 fn enable_alarm_wake(&self) {
292 while self.busy() {}
293 self.registers.wer.modify(Event::ALARM0::SET);
294 while self.busy() {}
295 }
296
297 fn get_counter(&self) -> u32 {
298 while self.busy() {}
299 self.registers.cv.read(Value::VALUE)
300 }
301
302 fn set_counter(&self, val: u32) {
303 let regs: &AstRegisters = &self.registers;
304 while self.busy() {}
305 regs.cv.set(val);
306 }
307
308 pub fn handle_interrupt(&self) {
309 self.clear_alarm();
310 self.callback.map(|cb| {
311 cb.alarm();
312 });
313 }
314}
315
316impl time::Time for Ast<'_> {
317 type Frequency = time::Freq16KHz;
318 type Ticks = time::Ticks32;
319
320 fn now(&self) -> Self::Ticks {
321 Self::Ticks::from(self.get_counter())
322 }
323}
324
325impl<'a> time::Counter<'a> for Ast<'a> {
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 expire = now;
358 }
359
360 if expire.wrapping_sub(now).into_u32() <= ALARM0_SYNC_TICS {
363 expire = now.wrapping_add(Self::Ticks::from(ALARM0_SYNC_TICS));
364 }
365
366 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 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}