1use core::cell::Cell;
19use kernel::deferred_call::{DeferredCall, DeferredCallClient};
20use kernel::hil::date_time;
21use kernel::hil::date_time::{DateTimeClient, DateTimeValues, DayOfWeek, Month};
22use kernel::platform::chip::ClockInterface;
23use kernel::utilities::cells::OptionalCell;
24use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
25use kernel::utilities::registers::{register_bitfields, ReadWrite};
26use kernel::utilities::StaticRef;
27use kernel::ErrorCode;
28use stm32f4xx::clocks::{phclk, Stm32f4Clocks};
29
30#[repr(C)]
32pub struct RtcRegisters {
33 rtc_tr: ReadWrite<u32, RTC_TR::Register>,
35 rtc_dr: ReadWrite<u32, RTC_DR::Register>,
37 rtc_cr: ReadWrite<u32, RTC_CR::Register>,
39 rtc_isr: ReadWrite<u32, RTC_ISR::Register>,
41 rtc_prer: ReadWrite<u32, RTC_PRER::Register>,
43 rtc_wutr: ReadWrite<u32, RTC_WUTR::Register>,
45 rtc_calibr: ReadWrite<u32, RTC_CALIBR::Register>,
47 rtc_alrmar: ReadWrite<u32, RTC_ALRMAR::Register>,
49 rtc_alrmbr: ReadWrite<u32, RTC_ALRMBR::Register>,
51 rtc_wpr: ReadWrite<u32, RTC_WPR::Register>,
53 rtc_ssr: ReadWrite<u32, RTC_SSR::Register>,
55 rtc_shiftr: ReadWrite<u32, RTC_SHIFTR::Register>,
57 rtc_tstr: ReadWrite<u32, RTC_TSTR::Register>,
59 rtc_tsdr: ReadWrite<u32, RTC_TSDR::Register>,
61 rtc_tsssr: ReadWrite<u32, RTC_TSSSR::Register>,
63 rtc_calr: ReadWrite<u32, RTC_CALR::Register>,
65 rtc_tafcr: ReadWrite<u32, RTC_TAFCR::Register>,
67 rtc_alrmassr: ReadWrite<u32, RTC_ALRMASSR::Register>,
69 rtc_alrmbssr: ReadWrite<u32, RTC_ALRMBSSR::Register>,
71
72 rtc_bkpxr: [ReadWrite<u32, RTC_BKPXR::Register>; 19],
74}
75
76register_bitfields![u32,
77RTC_TR[
78 PM OFFSET(22) NUMBITS(1) [],
80 HT OFFSET(20) NUMBITS(2) [],
82 HU OFFSET(16) NUMBITS(4) [],
84 MNT OFFSET(12) NUMBITS(3) [],
86 MNU OFFSET(8) NUMBITS(4) [],
88 ST OFFSET(4) NUMBITS(3) [],
90 SU OFFSET(0) NUMBITS(4) [],
92],
93RTC_DR[
94 YT OFFSET(20) NUMBITS(4) [],
96 YU OFFSET(16) NUMBITS(4) [],
98 WDU OFFSET(13) NUMBITS(3) [],
100 MT OFFSET(12) NUMBITS(1) [],
102 MU OFFSET(8) NUMBITS(4) [],
104 DT OFFSET(4) NUMBITS(2) [],
106 DU OFFSET(0) NUMBITS(4) [],
108],
109RTC_CR[
110 COE OFFSET(23) NUMBITS(1) [],
112 OSEL OFFSET(21) NUMBITS(2) [],
114 POL OFFSET(20) NUMBITS(1) [],
116 COSEL OFFSET(19) NUMBITS(1) [],
118 BKP OFFSET(18) NUMBITS(1) [],
120 SUB1H OFFSET(17) NUMBITS(1) [],
122 ADD1H OFFSET(16) NUMBITS(1) [],
124 TSIE OFFSET(15) NUMBITS(1) [],
126 WUTIE OFFSET(14) NUMBITS(1) [],
128 ALRBIE OFFSET(13) NUMBITS(1) [],
130 ALRAIE OFFSET(12) NUMBITS(1) [],
132 TSE OFFSET(11) NUMBITS(1) [],
134 WUTE OFFSET(10) NUMBITS(1) [],
136 ALRBE OFFSET(9) NUMBITS(1) [],
138 ALRAE OFFSET(8) NUMBITS(1) [],
140 DCE OFFSET(7) NUMBITS(1) [],
142 FMT OFFSET(6) NUMBITS(1) [],
144 BYPSHAD OFFSET(5) NUMBITS(1) [],
146 REFCKON OFFSET(4) NUMBITS(1) [],
148 TSEDGE OFFSET(3) NUMBITS(1) [],
150 WUCKSEL OFFSET(0) NUMBITS(3) [],
152],
153RTC_ISR[
154 RECALPF OFFSET(16) NUMBITS(1) [],
156 TAMP2F OFFSET(14) NUMBITS(1) [],
158 TAMP1F OFFSET(13) NUMBITS(1) [],
160 TSOVF OFFSET(12) NUMBITS(1) [],
162 TSF OFFSET(11) NUMBITS(1) [],
164 WUTF OFFSET(10) NUMBITS(1) [],
166 ALRBF OFFSET(9) NUMBITS(1) [],
168 ALRAF OFFSET(8) NUMBITS(1) [],
170 INIT OFFSET(7) NUMBITS(1) [],
172 INITF OFFSET(6) NUMBITS(1) [],
174 RSF OFFSET(5) NUMBITS(1) [],
176 INITS OFFSET(4) NUMBITS(1) [],
178 SHPF OFFSET(3) NUMBITS(1) [],
180 WUTWF OFFSET(2) NUMBITS(1) [],
182 ALRBWF OFFSET(1) NUMBITS(1) [],
184 ALRAWF OFFSET(0) NUMBITS(1) [],
186],
187RTC_PRER[
188 PREDIV_A OFFSET(16) NUMBITS(7) [],
190 PREDIV_S OFFSET(0) NUMBITS(15) [],
192],
193RTC_WUTR[
194 WUT OFFSET(0) NUMBITS(16) [],
196],
197RTC_CALIBR[
198 DCS OFFSET(7) NUMBITS(1) [],
200 DC OFFSET(0) NUMBITS(5) [],
202],
203RTC_ALRMAR[
204 MSK4 OFFSET(31) NUMBITS(1) [],
206 WDSEL OFFSET(30) NUMBITS(1) [],
208 DT OFFSET(28) NUMBITS(2) [],
210 DU OFFSET(24) NUMBITS(4) [],
212 MSK3 OFFSET(23) NUMBITS(1) [],
214 PM OFFSET(22) NUMBITS(1) [],
216 HT OFFSET(20) NUMBITS(2) [],
218 HU OFFSET(16) NUMBITS(4) [],
220 MSK2 OFFSET(15) NUMBITS(1) [],
222 MNT OFFSET(12) NUMBITS(3) [],
224 MNU OFFSET(8) NUMBITS(4) [],
226 MSK1 OFFSET(7) NUMBITS(1) [],
228 ST OFFSET(4) NUMBITS(3) [],
230 SU OFFSET(0) NUMBITS(4) [],
232],
233RTC_ALRMBR[
234 MSK4 OFFSET(31) NUMBITS(1) [],
236 WDSEL OFFSET(30) NUMBITS(1) [],
238 DT OFFSET(28) NUMBITS(2) [],
240 DU OFFSET(24) NUMBITS(4) [],
242 MSK3 OFFSET(23) NUMBITS(1) [],
244 PM OFFSET(22) NUMBITS(1) [],
246 HT OFFSET(20) NUMBITS(2) [],
248 HU OFFSET(16) NUMBITS(4) [],
250 MSK2 OFFSET(15) NUMBITS(1) [],
252 MNT OFFSET(12) NUMBITS(3) [],
254 MNU OFFSET(8) NUMBITS(4) [],
256 MSK1 OFFSET(7) NUMBITS(1) [],
258 ST OFFSET(4) NUMBITS(3) [],
260 SU OFFSET(0) NUMBITS(4) [],
262],
263RTC_WPR[
264 KEY OFFSET(0) NUMBITS(8) [],
266],
267RTC_SSR[
268 SS OFFSET(0) NUMBITS(16) [],
270],
271RTC_SHIFTR[
272 ADD1S OFFSET(31) NUMBITS(1) [],
274 SUBFS OFFSET(0) NUMBITS(15) [],
276],
277RTC_TSTR[
278 PM OFFSET(22) NUMBITS(1) [],
280 HT OFFSET(20) NUMBITS(2) [],
282 HU OFFSET(16) NUMBITS(4) [],
284 MNT OFFSET(12) NUMBITS(3) [],
286 MNU OFFSET(8) NUMBITS(4) [],
288 ST OFFSET(4) NUMBITS(3) [],
290 STU OFFSET(0) NUMBITS(4) [],
292],
293RTC_TSDR[
294 WDU OFFSET(13) NUMBITS(3) [],
296 MT OFFSET(12) NUMBITS(1) [],
298 MU OFFSET(8) NUMBITS(4) [],
300 DT OFFSET(4) NUMBITS(2) [],
302 DU OFFSET(0) NUMBITS(4) [],
304],
305RTC_TSSSR[
306 SS OFFSET(0) NUMBITS(16) [],
308],
309RTC_CALR[
310 CALP OFFSET(15) NUMBITS(1) [],
312 CALW8 OFFSET(14) NUMBITS(1) [],
314 CALW16 OFFSET(13) NUMBITS(1) [],
316 CALM OFFSET(0) NUMBITS(9) [],
318],
319RTC_TAFCR[
320 ALARMOUTTYPE OFFSET(18) NUMBITS(1) [],
322 TSINSEL OFFSET(17) NUMBITS(1) [],
324 TAMP1INSEL OFFSET(16) NUMBITS(1) [],
326 TAMPPUDIS OFFSET(15) NUMBITS(1) [],
328 TAMPPRCH OFFSET(13) NUMBITS(2) [],
330 TAMPFLT OFFSET(11) NUMBITS(2) [],
332 TAMPFREQ OFFSET(8) NUMBITS(3) [],
334 TAMPTS OFFSET(7) NUMBITS(1) [],
336 TAMP2TRG OFFSET(4) NUMBITS(1) [],
338 TAMP2E OFFSET(3) NUMBITS(1) [],
340 TAMPIE OFFSET(2) NUMBITS(1) [],
342 TAMP1TRG OFFSET(1) NUMBITS(1) [],
344 TAMP1E OFFSET(0) NUMBITS(1) [],
346],
347RTC_ALRMASSR[
348 MASKSS OFFSET(24) NUMBITS(4) [],
350 SS OFFSET(0) NUMBITS(15) [],
352],
353RTC_ALRMBSSR[
354 MASKSS OFFSET(24) NUMBITS(4) [],
356 SS OFFSET(0) NUMBITS(15) [],
358],
359RTC_BKPXR[
360 BKP OFFSET(0) NUMBITS(32) [],
362],
363];
364
365pub struct Rtc<'a> {
366 registers: StaticRef<RtcRegisters>,
367 client: OptionalCell<&'a dyn date_time::DateTimeClient>,
368 pub clock: phclk::PeripheralClock<'a>,
369 pub pwr_clock: phclk::PeripheralClock<'a>,
370 time: Cell<DateTimeValues>,
371
372 deferred_call: DeferredCall,
373 deferred_call_task: OptionalCell<DeferredCallTask>,
374}
375
376#[derive(Clone, Copy)]
377enum DeferredCallTask {
378 Get,
379 Set,
380}
381
382impl DeferredCallClient for Rtc<'_> {
383 fn handle_deferred_call(&self) {
384 self.deferred_call_task.take().map(|value| match value {
385 DeferredCallTask::Get => self
386 .client
387 .map(|client| client.get_date_time_done(Ok(self.time.get()))),
388 DeferredCallTask::Set => self.client.map(|client| client.set_date_time_done(Ok(()))),
389 });
390 }
391 fn register(&'static self) {
392 self.deferred_call.register(self);
393 }
394}
395
396const RTC_BASE: StaticRef<RtcRegisters> =
397 unsafe { StaticRef::new(0x40002800 as *const RtcRegisters) };
398
399impl<'a> Rtc<'a> {
400 pub fn new(clocks: &'a dyn Stm32f4Clocks) -> Rtc<'a> {
401 Rtc {
402 registers: RTC_BASE,
403 client: OptionalCell::empty(),
404 clock: phclk::PeripheralClock::new(phclk::PeripheralClockType::RTC, clocks),
405 pwr_clock: phclk::PeripheralClock::new(phclk::PeripheralClockType::PWR, clocks),
406 time: Cell::new(DateTimeValues {
407 year: 0,
408 month: Month::January,
409 day: 1,
410 day_of_week: DayOfWeek::Sunday,
411 hour: 0,
412 minute: 0,
413 seconds: 0,
414 }),
415 deferred_call: DeferredCall::new(),
416 deferred_call_task: OptionalCell::empty(),
417 }
418 }
419
420 fn dotw_try_from_u32(dotw: u32) -> Result<DayOfWeek, ErrorCode> {
421 match dotw {
422 1 => Ok(DayOfWeek::Monday),
423 2 => Ok(DayOfWeek::Tuesday),
424 3 => Ok(DayOfWeek::Wednesday),
425 4 => Ok(DayOfWeek::Thursday),
426 5 => Ok(DayOfWeek::Friday),
427 6 => Ok(DayOfWeek::Saturday),
428 7 => Ok(DayOfWeek::Sunday),
429 _ => Err(ErrorCode::INVAL),
430 }
431 }
432
433 fn dotw_into_u32(dotw: DayOfWeek) -> u32 {
434 match dotw {
435 DayOfWeek::Monday => 1,
436 DayOfWeek::Tuesday => 2,
437 DayOfWeek::Wednesday => 3,
438 DayOfWeek::Thursday => 4,
439 DayOfWeek::Friday => 5,
440 DayOfWeek::Saturday => 6,
441 DayOfWeek::Sunday => 7,
442 }
443 }
444
445 fn month_try_from_u32(month_num: u32) -> Result<Month, ErrorCode> {
446 match month_num {
447 1 => Ok(Month::January),
448 2 => Ok(Month::February),
449 3 => Ok(Month::March),
450 4 => Ok(Month::April),
451 5 => Ok(Month::May),
452 6 => Ok(Month::June),
453 7 => Ok(Month::July),
454 8 => Ok(Month::August),
455 9 => Ok(Month::September),
456 10 => Ok(Month::October),
457 11 => Ok(Month::November),
458 12 => Ok(Month::December),
459 _ => Err(ErrorCode::INVAL),
460 }
461 }
462
463 fn month_into_u32(month: Month) -> u32 {
464 match month {
465 Month::January => 1,
466 Month::February => 2,
467 Month::March => 3,
468 Month::April => 4,
469 Month::May => 5,
470 Month::June => 6,
471 Month::July => 7,
472 Month::August => 8,
473 Month::September => 9,
474 Month::October => 10,
475 Month::November => 11,
476 Month::December => 12,
477 }
478 }
479
480 #[inline(never)]
481 fn bypass_write_protection(&self) {
485 self.registers.rtc_wpr.modify(RTC_WPR::KEY.val(0xCA)); self.registers.rtc_wpr.modify(RTC_WPR::KEY.val(0x53)); }
488
489 #[inline(never)]
490 fn enable_write_protection(&self) {
494 self.registers.rtc_wpr.modify(RTC_WPR::KEY.val(0x42)); }
496
497 fn date_time_setup(&self, datetime: date_time::DateTimeValues) -> Result<(), ErrorCode> {
498 let month_num = Rtc::month_into_u32(datetime.month);
499 let dotw_num = Rtc::dotw_into_u32(datetime.day_of_week);
500
501 if !(datetime.day >= 1 && datetime.day <= 31) {
502 return Err(ErrorCode::INVAL);
503 }
504 if !(datetime.hour <= 23) {
505 return Err(ErrorCode::INVAL);
506 }
507 if !(datetime.minute <= 59) {
508 return Err(ErrorCode::INVAL);
509 }
510 if !(datetime.seconds <= 59) {
511 return Err(ErrorCode::INVAL);
512 }
513
514 self.registers.rtc_dr.modify(
515 RTC_DR::YT.val((datetime.year % 100) as u32 / 10)
516 + RTC_DR::YU.val((datetime.year % 100) as u32 % 10)
517 + RTC_DR::MT.val(month_num / 10)
518 + RTC_DR::MU.val(month_num % 10)
519 + RTC_DR::DT.val(datetime.day as u32 / 10)
520 + RTC_DR::DU.val(datetime.day as u32 % 10)
521 + RTC_DR::WDU.val(dotw_num),
522 );
523
524 self.registers.rtc_tr.modify(
525 RTC_TR::HT.val(datetime.hour as u32 / 10)
526 + RTC_TR::HU.val(datetime.hour as u32 % 10)
527 + RTC_TR::MNT.val(datetime.minute as u32 / 10)
528 + RTC_TR::MNU.val(datetime.minute as u32 % 10)
529 + RTC_TR::ST.val(datetime.seconds as u32 / 10)
530 + RTC_TR::SU.val(datetime.seconds as u32 % 10),
531 );
532
533 Ok(())
534 }
535
536 pub fn enter_init_mode(&self) -> Result<(), ErrorCode> {
537 self.bypass_write_protection();
538 self.registers.rtc_isr.modify(RTC_ISR::INIT::SET);
539
540 let mut cycle_counter = 100000;
541 while cycle_counter > 0 && !self.registers.rtc_isr.is_set(RTC_ISR::INITF) {
542 cycle_counter -= 1;
543 }
545 if cycle_counter <= 0 {
546 return Err(ErrorCode::FAIL);
547 }
548 Ok(())
549 }
550 pub fn exit_init_mode(&self) -> Result<(), ErrorCode> {
551 self.registers.rtc_isr.modify(RTC_ISR::INIT::CLEAR);
552 let mut cycle_counter = 100000;
553 while cycle_counter > 0 && !self.registers.rtc_isr.is_set(RTC_ISR::RSF) {
554 cycle_counter -= 1;
555 }
556 if cycle_counter <= 0 {
557 return Err(ErrorCode::FAIL);
558 }
559
560 self.enable_write_protection();
561 Ok(())
562 }
563
564 pub fn rtc_init(&self) -> Result<(), ErrorCode> {
565 self.enter_init_mode()?;
566
567 self.registers
568 .rtc_prer
569 .modify(RTC_PRER::PREDIV_A.val(128 - 1));
570 self.registers
571 .rtc_prer
572 .modify(RTC_PRER::PREDIV_S.val(256 - 1));
573
574 self.registers.rtc_cr.modify(RTC_CR::FMT.val(0));
576
577 let datetime = date_time::DateTimeValues {
578 year: 0,
579 month: Month::January,
580 day: 1,
581 day_of_week: DayOfWeek::Monday,
582
583 hour: 0,
584 minute: 0,
585 seconds: 0,
586 };
587 self.date_time_setup(datetime)?;
588
589 self.exit_init_mode()?;
590 Ok(())
591 }
592
593 pub fn enable_clock(&self) {
594 self.pwr_clock.enable();
595
596 match crate::pwr::enable_backup_access() {
598 Err(e) => panic!("{:?}", e),
599 _ => (),
600 }
601
602 self.clock.enable();
603 }
604}
605
606impl<'a> date_time::DateTime<'a> for Rtc<'a> {
607 fn get_date_time(&self) -> Result<(), ErrorCode> {
608 match self.deferred_call_task.take() {
609 Some(DeferredCallTask::Set) => {
610 self.deferred_call_task.insert(Some(DeferredCallTask::Set));
611 return Err(ErrorCode::BUSY);
612 }
613 Some(DeferredCallTask::Get) => {
614 self.deferred_call_task.insert(Some(DeferredCallTask::Get));
615 return Err(ErrorCode::ALREADY);
616 }
617 _ => (),
618 }
619
620 let month_num =
621 self.registers.rtc_dr.read(RTC_DR::MT) * 10 + self.registers.rtc_dr.read(RTC_DR::MU);
622 let month_name = Rtc::month_try_from_u32(month_num)?;
623
624 let dotw_num = self.registers.rtc_dr.read(RTC_DR::WDU);
625 let dotw_name = Rtc::dotw_try_from_u32(dotw_num)?;
626
627 let datetime = date_time::DateTimeValues {
628 hour: (self.registers.rtc_tr.read(RTC_TR::HT) * 10
629 + self.registers.rtc_tr.read(RTC_TR::HU)) as u8,
630 minute: (self.registers.rtc_tr.read(RTC_TR::MNT) * 10
631 + self.registers.rtc_tr.read(RTC_TR::MNU)) as u8,
632 seconds: (self.registers.rtc_tr.read(RTC_TR::ST) * 10
633 + self.registers.rtc_tr.read(RTC_TR::SU)) as u8,
634
635 year: (self.registers.rtc_dr.read(RTC_DR::YT) * 10
636 + self.registers.rtc_dr.read(RTC_DR::YU)) as u16,
637 month: month_name,
638 day: (self.registers.rtc_dr.read(RTC_DR::DT) * 10
639 + self.registers.rtc_dr.read(RTC_DR::DU)) as u8,
640 day_of_week: dotw_name,
641 };
642
643 self.time.replace(datetime);
644
645 self.deferred_call_task.insert(Some(DeferredCallTask::Get));
646 self.deferred_call.set();
647
648 Ok(())
649 }
650
651 fn set_date_time(&self, date_time: date_time::DateTimeValues) -> Result<(), ErrorCode> {
652 match self.deferred_call_task.take() {
653 Some(DeferredCallTask::Set) => {
654 self.deferred_call_task.insert(Some(DeferredCallTask::Set));
655 return Err(ErrorCode::ALREADY);
656 }
657 Some(DeferredCallTask::Get) => {
658 self.deferred_call_task.insert(Some(DeferredCallTask::Get));
659 return Err(ErrorCode::BUSY);
660 }
661 _ => (),
662 }
663
664 self.enter_init_mode()?;
665 self.date_time_setup(date_time)?;
666 self.exit_init_mode()?;
667
668 self.deferred_call_task.insert(Some(DeferredCallTask::Set));
669 self.deferred_call.set();
670 Ok(())
671 }
672
673 fn set_client(&self, client: &'a dyn DateTimeClient) {
674 self.client.set(client);
675 }
676}