1use core::cell::Cell;
8use kernel::hil::time::{
9 Alarm, AlarmClient, Counter, Frequency, OverflowClient, Ticks, Ticks16, Time,
10};
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
13use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
14use kernel::utilities::StaticRef;
15use kernel::ErrorCode;
16
17pub const TIMER_A0_BASE: StaticRef<TimerRegisters> =
18 unsafe { StaticRef::new(0x4000_0000u32 as *const TimerRegisters) };
19
20pub const TIMER_A1_BASE: StaticRef<TimerRegisters> =
21 unsafe { StaticRef::new(0x4000_0400u32 as *const TimerRegisters) };
22
23pub const TIMER_A2_BASE: StaticRef<TimerRegisters> =
24 unsafe { StaticRef::new(0x4000_0800u32 as *const TimerRegisters) };
25
26pub const TIMER_A3_BASE: StaticRef<TimerRegisters> =
27 unsafe { StaticRef::new(0x4000_0C00u32 as *const TimerRegisters) };
28
29register_structs! {
30 pub TimerRegisters {
32 (0x00 => ctl: ReadWrite<u16, TAxCTL::Register>),
34 (0x02 => cctl0: ReadWrite<u16, TAxCCTLx::Register>),
36 (0x04 => cctl1: ReadWrite<u16, TAxCCTLx::Register>),
38 (0x06 => cctl2: ReadWrite<u16, TAxCCTLx::Register>),
40 (0x08 => cctl3: ReadWrite<u16, TAxCCTLx::Register>),
42 (0x0A => cctl4: ReadWrite<u16, TAxCCTLx::Register>),
44 (0x0C => cctl5: ReadWrite<u16, TAxCCTLx::Register>),
46 (0x0E => cctl6: ReadWrite<u16, TAxCCTLx::Register>),
48 (0x10 => cnt: ReadWrite<u16>),
50 (0x12 => ccr0: ReadWrite<u16>),
52 (0x14 => ccr1: ReadWrite<u16>),
54 (0x16 => ccr2: ReadWrite<u16>),
56 (0x18 => ccr3: ReadWrite<u16>),
58 (0x1A => ccr4: ReadWrite<u16>),
60 (0x1C => ccr5: ReadWrite<u16>),
62 (0x1E => ccr6: ReadWrite<u16>),
64 (0x20 => ex0: ReadWrite<u16, TAxEX0::Register>),
66 (0x22 => _reserved),
67 (0x2E => iv: ReadWrite<u16, TAxIV::Register>),
69 (0x30 => @END),
70 }
71}
72
73register_bitfields! [u16,
74 TAxCTL [
76 TAIFG OFFSET(0) NUMBITS(1) [],
78 TAIE OFFSET(1) NUMBITS(1) [],
80 TACLR OFFSET(2) NUMBITS(1) [],
82 MC OFFSET(4) NUMBITS(2) [
84 StopMode = 0,
86 UpMode = 1,
88 ContinuousMode = 2,
90 UpDownMode = 3
92 ],
93 ID OFFSET(6) NUMBITS(2) [
95 DividedBy1 = 0,
97 DividedBy2 = 1,
99 DividedBy4 = 2,
101 DividedBy8 = 3
103 ],
104 TASSEL OFFSET(8) NUMBITS(2) [
106 TAxCLK = 0,
108 ACLK = 1,
110 SMCLK = 2,
112 INCLK = 3
114 ]
115 ],
116 TAxCCTLx [
118 CCIFG OFFSET(0) NUMBITS(1) [],
120 COV OFFSET(1) NUMBITS(1) [],
122 OUT OFFSET(2) NUMBITS(1) [],
124 CCI OFFSET(3) NUMBITS(1) [],
126 CCIE OFFSET(4) NUMBITS(1) [],
128 OUTMOD OFFSET(5) NUMBITS(3) [
130 OutBit = 0,
132 Set = 1,
134 ToggleReset = 2,
136 SetReset = 3,
138 Toggle = 4,
140 Reset = 5,
142 ToggleSet = 6,
144 ResetSet = 7
146 ],
147 CAP OFFSET(8) NUMBITS(1) [],
149 SCCI OFFSET(10) NUMBITS(1) [],
151 SCS OFFSET(11) NUMBITS(1) [
153 Asynchronous = 0,
155 Synchronous = 1
157 ],
158 CCIS OFFSET(12) NUMBITS(2) [
160 CCIxA = 0,
162 CCIxB = 1,
164 GND = 2,
166 VCC = 3
168 ],
169 CM OFFSET(14) NUMBITS(2) [
171 NoCapture = 0,
173 CaptureRisingEdge = 1,
175 CaptureFallingEdge = 2,
177 CaptureBothEdges = 3
179 ]
180 ],
181 TAxIV [
183 TAIV OFFSET(0) NUMBITS(16) [
184 NoInterrupt = 0x00,
186 InterruptCCR1 = 0x02,
188 InterruptCCR2 = 0x04,
190 InterruptCCR3 = 0x06,
192 InterruptCCR4 = 0x08,
194 InterruptCCR5 = 0x0A,
196 InterruptCCR6 = 0x0C,
198 InterruptTimer = 0x0E
200 ]
201 ],
202 TAxEX0 [
204 TAIDEX OFFSET(0) NUMBITS(3) [
206 DivideBy1 = 0,
208 DivideBy2 = 1,
210 DivideBy3 = 2,
212 DivideBy4 = 3,
214 DivideBy5 = 4,
216 DivideBy6 = 5,
218 DivideBy7 = 6,
220 DivideBy8 = 7
222 ]
223 ]
224];
225
226#[derive(PartialEq, Copy, Clone)]
229enum TimerMode {
230 Disabled,
231 Alarm,
232 InternalTimer,
233}
234
235pub struct TimerAFrequency {}
236
237impl Frequency for TimerAFrequency {
238 fn frequency() -> u32 {
239 crate::cs::ACLK_HZ / 16
240 }
241}
242
243pub enum InternalTrigger {
244 CaptureCompare1,
245 CaptureCompare2,
246 CaptureCompare3,
247 CaptureCompare4,
248 CaptureCompare5,
249 CaptureCompare6,
250}
251
252pub trait InternalTimer {
253 fn start(&self, frequency_hz: u32, int_src: InternalTrigger) -> Result<(), ErrorCode>;
259
260 fn stop(&self);
262}
263
264pub struct TimerA<'a> {
265 registers: StaticRef<TimerRegisters>,
266 mode: Cell<TimerMode>,
267 alarm_client: OptionalCell<&'a dyn AlarmClient>,
268}
269
270impl<'a> TimerA<'a> {
271 pub const fn new(base: StaticRef<TimerRegisters>) -> TimerA<'a> {
272 TimerA {
273 registers: base,
274 mode: Cell::new(TimerMode::Disabled),
275 alarm_client: OptionalCell::empty(),
276 }
277 }
278
279 fn setup_for_alarm(&self) {
281 self.registers.ctl.modify(
291 TAxCTL::TASSEL::ACLK
292 + TAxCTL::ID::DividedBy8
293 + TAxCTL::MC::ContinuousMode
294 + TAxCTL::TAIE::CLEAR
295 + TAxCTL::TAIFG::CLEAR,
296 );
297
298 self.registers.ex0.modify(TAxEX0::TAIDEX::DivideBy2);
300 self.mode.set(TimerMode::Alarm);
301 }
302
303 fn stop_timer(&self) {
305 self.registers
307 .ctl
308 .modify(TAxCTL::MC::StopMode + TAxCTL::TAIE::CLEAR);
309
310 self.registers.cctl0.set(0);
312 self.registers.cctl1.set(0);
313 self.registers.cctl2.set(0);
314 self.registers.cctl3.set(0);
315 self.registers.cctl4.set(0);
316 self.registers.cctl5.set(0);
317 self.registers.cctl6.set(0);
318
319 self.mode.set(TimerMode::Disabled);
320 }
321
322 fn handle_alarm_interrupt(&self) {
323 self.registers.cctl0.modify(TAxCCTLx::CCIE::CLEAR);
325 self.alarm_client.map(|client| client.alarm());
326 }
327
328 pub fn handle_interrupt(&self) {
329 if self.registers.cctl0.is_set(TAxCCTLx::CCIFG) {
330 if self.mode.get() == TimerMode::Alarm {
331 self.handle_alarm_interrupt();
332 }
333 self.registers.cctl0.modify(TAxCCTLx::CCIFG::CLEAR);
334 }
335 }
336}
337
338impl Time for TimerA<'_> {
339 type Frequency = TimerAFrequency;
340 type Ticks = Ticks16;
341
342 fn now(&self) -> Ticks16 {
343 Self::Ticks::from(self.registers.cnt.get())
344 }
345}
346
347impl<'a> Counter<'a> for TimerA<'a> {
348 fn set_overflow_client(&self, _client: &'a dyn OverflowClient) {}
349
350 fn start(&self) -> Result<(), ErrorCode> {
351 self.setup_for_alarm();
352 Ok(())
353 }
354
355 fn stop(&self) -> Result<(), ErrorCode> {
356 self.stop_timer();
357 Ok(())
358 }
359
360 fn reset(&self) -> Result<(), ErrorCode> {
361 self.registers.cnt.set(0);
362 Ok(())
363 }
364
365 fn is_running(&self) -> bool {
366 self.registers.cctl0.is_set(TAxCCTLx::CCIE)
367 }
368}
369
370impl<'a> Alarm<'a> for TimerA<'a> {
371 fn set_alarm_client(&self, client: &'a dyn AlarmClient) {
372 self.alarm_client.set(client);
373 }
374
375 fn set_alarm(&self, reference: Self::Ticks, dt: Self::Ticks) {
376 if self.mode.get() != TimerMode::Alarm {
377 self.setup_for_alarm();
378 }
379 let now = self.now();
380 let mut expire = reference.wrapping_add(dt);
381 if !now.within_range(reference, expire) {
382 expire = now;
383 }
384
385 if expire.wrapping_sub(now) <= self.minimum_dt() {
386 expire = now.wrapping_add(self.minimum_dt());
387 }
388
389 let _ = self.disarm();
390 self.registers.ccr0.set(expire.into_u16());
392 self.registers.cctl0.modify(TAxCCTLx::CCIE::SET);
394 }
395
396 fn get_alarm(&self) -> Self::Ticks {
397 Self::Ticks::from(self.registers.ccr0.get())
398 }
399
400 fn is_armed(&self) -> bool {
401 let int_enabled = self.registers.cctl0.is_set(TAxCCTLx::CCIE);
402 (self.mode.get() == TimerMode::Alarm) && int_enabled
403 }
404
405 fn disarm(&self) -> Result<(), ErrorCode> {
406 self.registers.cctl0.modify(TAxCCTLx::CCIE::CLEAR);
408 Ok(())
411 }
412
413 fn minimum_dt(&self) -> Self::Ticks {
414 Self::Ticks::from(1_u16)
415 }
416}
417
418impl InternalTimer for TimerA<'_> {
419 fn start(&self, frequency_hz: u32, trigger: InternalTrigger) -> Result<(), ErrorCode> {
420 if self.mode.get() != TimerMode::Disabled && self.mode.get() != TimerMode::InternalTimer {
421 return Err(ErrorCode::BUSY);
422 }
423
424 if frequency_hz > crate::cs::SMCLK_HZ {
425 return Err(ErrorCode::INVAL);
426 }
427
428 self.stop_timer();
430
431 let reg_val = if frequency_hz <= 100 {
432 self.registers.ctl.modify(TAxCTL::ID::DividedBy8);
434 self.registers.ex0.modify(TAxEX0::TAIDEX::DivideBy5);
435 (crate::cs::SMCLK_HZ / 40) / frequency_hz
436 } else {
437 self.registers.ctl.modify(TAxCTL::ID::DividedBy1);
438 self.registers.ex0.modify(TAxEX0::TAIDEX::DivideBy1);
439 crate::cs::SMCLK_HZ / frequency_hz
440 };
441
442 self.registers.ctl.modify(
447 TAxCTL::TASSEL::SMCLK + TAxCTL::MC::UpMode + TAxCTL::TAIE::CLEAR + TAxCTL::TAIFG::CLEAR,
448 );
449
450 self.registers.ccr0.set((reg_val - 1) as u16);
452 self.registers.cctl0.modify(TAxCCTLx::CCIE::CLEAR);
453
454 let (ccr_reg, cctl_reg) = match trigger {
456 InternalTrigger::CaptureCompare1 => (&self.registers.ccr1, &self.registers.cctl1),
457 InternalTrigger::CaptureCompare2 => (&self.registers.ccr2, &self.registers.cctl2),
458 InternalTrigger::CaptureCompare3 => (&self.registers.ccr3, &self.registers.cctl3),
459 InternalTrigger::CaptureCompare4 => (&self.registers.ccr4, &self.registers.cctl4),
460 InternalTrigger::CaptureCompare5 => (&self.registers.ccr5, &self.registers.cctl5),
461 InternalTrigger::CaptureCompare6 => (&self.registers.ccr6, &self.registers.cctl6),
462 };
463
464 ccr_reg.set((reg_val - 2) as u16);
466 cctl_reg.modify(TAxCCTLx::OUTMOD::SetReset + TAxCCTLx::OUT::CLEAR + TAxCCTLx::CCIE::CLEAR);
468
469 self.mode.set(TimerMode::InternalTimer);
470 Ok(())
471 }
472
473 fn stop(&self) {
474 self.stop_timer();
475 }
476}