stm32f429zi/
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//! Real Time Clock (RTC) driver for STM32f429zi.
6//!
7//! Author: Remus Rughinis <remus.rughinis.007@gmail.com>
8//!
9//! # Hardware Interface Layer (HIL)
10//!
11//! The driver implements Date_Time HIL. The following features are available when using
12//! the driver through HIL:
13//!
14//! + Set time from which real time clock should start counting
15//! + Read current time from the RTC registers
16//!
17
18use 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/// Register block to control RTC
31#[repr(C)]
32pub struct RtcRegisters {
33    /// The RTC_TR is the calendar time shadow register. This register must be written in initialization mode only.
34    rtc_tr: ReadWrite<u32, RTC_TR::Register>,
35    /// The RTC_DR is the calendar date shadow register. This register must be written in initialization mode only.
36    rtc_dr: ReadWrite<u32, RTC_DR::Register>,
37    /// RTC control register
38    rtc_cr: ReadWrite<u32, RTC_CR::Register>,
39    /// RTC initialization and status register
40    rtc_isr: ReadWrite<u32, RTC_ISR::Register>,
41    /// RTC prescaler register
42    rtc_prer: ReadWrite<u32, RTC_PRER::Register>,
43    /// RTC wakeup timer register
44    rtc_wutr: ReadWrite<u32, RTC_WUTR::Register>,
45    /// RTC calibration register
46    rtc_calibr: ReadWrite<u32, RTC_CALIBR::Register>,
47    /// RTC alarm A register
48    rtc_alrmar: ReadWrite<u32, RTC_ALRMAR::Register>,
49    /// RTC alarm B register
50    rtc_alrmbr: ReadWrite<u32, RTC_ALRMBR::Register>,
51    /// RTC write protection register
52    rtc_wpr: ReadWrite<u32, RTC_WPR::Register>,
53    /// RTC sub second register
54    rtc_ssr: ReadWrite<u32, RTC_SSR::Register>,
55    /// RTC shift control register
56    rtc_shiftr: ReadWrite<u32, RTC_SHIFTR::Register>,
57    /// RTC time stamp time register
58    rtc_tstr: ReadWrite<u32, RTC_TSTR::Register>,
59    /// RTC time stamp date register
60    rtc_tsdr: ReadWrite<u32, RTC_TSDR::Register>,
61    /// RTC time stamp sub second register
62    rtc_tsssr: ReadWrite<u32, RTC_TSSSR::Register>,
63    /// RTC calibration register
64    rtc_calr: ReadWrite<u32, RTC_CALR::Register>,
65    /// RTC tamper and alternate function configuration register
66    rtc_tafcr: ReadWrite<u32, RTC_TAFCR::Register>,
67    /// RTC alarm A sub second register
68    rtc_alrmassr: ReadWrite<u32, RTC_ALRMASSR::Register>,
69    /// RTC alarm B sub second register
70    rtc_alrmbssr: ReadWrite<u32, RTC_ALRMBSSR::Register>,
71
72    /// The application can write or read data to and from these registers
73    rtc_bkpxr: [ReadWrite<u32, RTC_BKPXR::Register>; 19],
74}
75
76register_bitfields![u32,
77RTC_TR[
78    /// AM/PM notation. 0: AM or 24-hour format, 1: PM
79    PM OFFSET(22) NUMBITS(1) [],
80    /// Hour tens in BCD format
81    HT OFFSET(20) NUMBITS(2) [],
82    /// Hour units in BCD format
83    HU OFFSET(16) NUMBITS(4) [],
84    /// Minute tens in BCD format
85    MNT OFFSET(12) NUMBITS(3) [],
86    /// Minute units in BCD format
87    MNU OFFSET(8) NUMBITS(4) [],
88    /// Second tens in BCD format
89    ST OFFSET(4) NUMBITS(3) [],
90    /// Second units in BCD format
91    SU OFFSET(0) NUMBITS(4) [],
92],
93RTC_DR[
94    /// Year tens in BCD format
95    YT OFFSET(20) NUMBITS(4) [],
96    /// Year units in BCD format
97    YU OFFSET(16) NUMBITS(4) [],
98    /// Week day units. 000: forbidden, 001: Monday ... 111: Sunday
99    WDU OFFSET(13) NUMBITS(3) [],
100    ///Month tens in BCD format
101    MT OFFSET(12) NUMBITS(1) [],
102    /// Month units in BCD format
103    MU OFFSET(8) NUMBITS(4) [],
104    /// Date tens in BCD format
105    DT OFFSET(4) NUMBITS(2) [],
106    /// Date units in BCD format
107    DU OFFSET(0) NUMBITS(4) [],
108],
109RTC_CR[
110    /// Calibration output enable, enables the RTC_CALIB output
111    COE OFFSET(23) NUMBITS(1) [],
112    /// Output selection, used to select the flag to be routed to RTC_ALARM output
113    OSEL OFFSET(21) NUMBITS(2) [],
114    /// Output polarity, used to configure the polarity of RTC_ALARM output
115    POL OFFSET(20) NUMBITS(1) [],
116    /// Calibration output selection
117    COSEL OFFSET(19) NUMBITS(1) [],
118    /// Backup, memorizes whether daylight saving time change has been performed or not
119    BKP OFFSET(18) NUMBITS(1) [],
120    /// Subtract 1 hour (winter time change)
121    SUB1H OFFSET(17) NUMBITS(1) [],
122    /// Add 1 hour (summer time change)
123    ADD1H OFFSET(16) NUMBITS(1) [],
124    /// Timestamp interrupt enable
125    TSIE OFFSET(15) NUMBITS(1) [],
126    /// Wakeup timer interrupt enable
127    WUTIE OFFSET(14) NUMBITS(1) [],
128    /// Alarm B interrupt enable
129    ALRBIE OFFSET(13) NUMBITS(1) [],
130    /// Alarm A interrupt enable
131    ALRAIE OFFSET(12) NUMBITS(1) [],
132    /// Time stamp enable
133    TSE OFFSET(11) NUMBITS(1) [],
134    /// Wakeup timer enable
135    WUTE OFFSET(10) NUMBITS(1) [],
136    /// Alarm B enable
137    ALRBE OFFSET(9) NUMBITS(1) [],
138    /// Alarm A enable
139    ALRAE OFFSET(8) NUMBITS(1) [],
140    /// Coarse digital calibration enable
141    DCE OFFSET(7) NUMBITS(1) [],
142    /// Hour format
143    FMT OFFSET(6) NUMBITS(1) [],
144    /// Bypass the shadow registers
145    BYPSHAD OFFSET(5) NUMBITS(1) [],
146    /// Reference clock detection enable (50 or 60 Hz)
147    REFCKON OFFSET(4) NUMBITS(1) [],
148    /// Timestamp event active edge
149    TSEDGE OFFSET(3) NUMBITS(1) [],
150    /// Wakeup clock selection
151    WUCKSEL OFFSET(0) NUMBITS(3) [],
152],
153RTC_ISR[
154    /// Recalibration Pending Flag
155    RECALPF OFFSET(16) NUMBITS(1) [],
156    /// TAMPER2 detection flag
157    TAMP2F OFFSET(14) NUMBITS(1) [],
158    /// TAMPER detection flag
159    TAMP1F OFFSET(13) NUMBITS(1) [],
160    /// Timestamp overflow flag
161    TSOVF OFFSET(12) NUMBITS(1) [],
162    /// Timestamp flag
163    TSF OFFSET(11) NUMBITS(1) [],
164    /// Wakeup timer flag
165    WUTF OFFSET(10) NUMBITS(1) [],
166    /// Alarm B flag
167    ALRBF OFFSET(9) NUMBITS(1) [],
168    /// Alarm A flag
169    ALRAF OFFSET(8) NUMBITS(1) [],
170    /// Initialization mode
171    INIT OFFSET(7) NUMBITS(1) [],
172    /// Initialization flag
173    INITF OFFSET(6) NUMBITS(1) [],
174    /// Registers synchronization flag
175    RSF OFFSET(5) NUMBITS(1) [],
176    /// Initialization status flag
177    INITS OFFSET(4) NUMBITS(1) [],
178    /// Shift operation pending
179    SHPF OFFSET(3) NUMBITS(1) [],
180    /// Wakeup timer write flag
181    WUTWF OFFSET(2) NUMBITS(1) [],
182    /// Alarm B write flag
183    ALRBWF OFFSET(1) NUMBITS(1) [],
184    /// Alarm A write flag
185    ALRAWF OFFSET(0) NUMBITS(1) [],
186],
187RTC_PRER[
188    /// Asynchronous precaler factor
189    PREDIV_A OFFSET(16) NUMBITS(7) [],
190    /// Synchronous prescaler factor
191    PREDIV_S OFFSET(0) NUMBITS(15) [],
192],
193RTC_WUTR[
194    /// Wakeup auto-reload value bits
195    WUT OFFSET(0) NUMBITS(16) [],
196],
197RTC_CALIBR[
198    /// Digital calibration sign
199    DCS OFFSET(7) NUMBITS(1) [],
200    /// Digital calibration
201    DC OFFSET(0) NUMBITS(5) [],
202],
203RTC_ALRMAR[
204    /// Alarm A date mask
205    MSK4 OFFSET(31) NUMBITS(1) [],
206    /// Week day selection
207    WDSEL OFFSET(30) NUMBITS(1) [],
208    /// Date tens in BCD format
209    DT OFFSET(28) NUMBITS(2) [],
210    /// Date units in BCD format
211    DU OFFSET(24) NUMBITS(4) [],
212    /// Alarm A hours mask
213    MSK3 OFFSET(23) NUMBITS(1) [],
214    /// AM/PM notation
215    PM OFFSET(22) NUMBITS(1) [],
216    /// Hour tens in BCD format
217    HT OFFSET(20) NUMBITS(2) [],
218    /// Hour units in BCD format
219    HU OFFSET(16) NUMBITS(4) [],
220    /// Alarm A minutes mask
221    MSK2 OFFSET(15) NUMBITS(1) [],
222    /// Minute tens in BCD format
223    MNT OFFSET(12) NUMBITS(3) [],
224    /// Minute units in BCD format
225    MNU OFFSET(8) NUMBITS(4) [],
226    /// Alarm A seconds mask
227    MSK1 OFFSET(7) NUMBITS(1) [],
228    /// Second tens in BCD format
229    ST OFFSET(4) NUMBITS(3) [],
230    /// Second units in BCD format
231    SU OFFSET(0) NUMBITS(4) [],
232],
233RTC_ALRMBR[
234    /// Alarm B date mask
235    MSK4 OFFSET(31) NUMBITS(1) [],
236    /// Week day selection
237    WDSEL OFFSET(30) NUMBITS(1) [],
238    /// Date tens in BCD format
239    DT OFFSET(28) NUMBITS(2) [],
240    /// Date units in BCD format
241    DU OFFSET(24) NUMBITS(4) [],
242    /// Alarm B hours mask
243    MSK3 OFFSET(23) NUMBITS(1) [],
244    /// AM/PM notation
245    PM OFFSET(22) NUMBITS(1) [],
246    /// Hour tens in BCD format
247    HT OFFSET(20) NUMBITS(2) [],
248    /// Hour units in BCD format
249    HU OFFSET(16) NUMBITS(4) [],
250    /// Alarm B minutes mask
251    MSK2 OFFSET(15) NUMBITS(1) [],
252    /// Minute tens in BCD format
253    MNT OFFSET(12) NUMBITS(3) [],
254    /// Minute units in BCD format
255    MNU OFFSET(8) NUMBITS(4) [],
256    /// Alarm B seconds mask
257    MSK1 OFFSET(7) NUMBITS(1) [],
258    /// Second tens in BCD format
259    ST OFFSET(4) NUMBITS(3) [],
260    /// Second units in BCD format
261    SU OFFSET(0) NUMBITS(4) [],
262],
263RTC_WPR[
264    /// Write protection key
265    KEY OFFSET(0) NUMBITS(8) [],
266],
267RTC_SSR[
268    /// Sub second value
269    SS OFFSET(0) NUMBITS(16) [],
270],
271RTC_SHIFTR[
272    /// Add one second
273    ADD1S OFFSET(31) NUMBITS(1) [],
274    /// Subtract a fraction of a second
275    SUBFS OFFSET(0) NUMBITS(15) [],
276],
277RTC_TSTR[
278    /// AM/PM notation
279    PM OFFSET(22) NUMBITS(1) [],
280    /// Hour tens in BCD format
281    HT OFFSET(20) NUMBITS(2) [],
282    /// Hour units in BCD format
283    HU OFFSET(16) NUMBITS(4) [],
284    /// Minute tens in BCD format
285    MNT OFFSET(12) NUMBITS(3) [],
286    /// Minute units in BCD format
287    MNU OFFSET(8) NUMBITS(4) [],
288    /// Second tens in BCD format
289    ST OFFSET(4) NUMBITS(3) [],
290    /// Second units in BCD format
291    STU OFFSET(0) NUMBITS(4) [],
292],
293RTC_TSDR[
294    /// Week day units. 000: forbidden, 001: Monday ... 111: Sunday
295    WDU OFFSET(13) NUMBITS(3) [],
296    ///Month tens in BCD format
297    MT OFFSET(12) NUMBITS(1) [],
298    /// Month units in BCD format
299    MU OFFSET(8) NUMBITS(4) [],
300    /// Date tens in BCD format
301    DT OFFSET(4) NUMBITS(2) [],
302    /// Date units in BCD format
303    DU OFFSET(0) NUMBITS(4) [],
304],
305RTC_TSSSR[
306    /// Sub second value
307    SS OFFSET(0) NUMBITS(16) [],
308],
309RTC_CALR[
310    /// Increase frequency of RTC by 488.0 ppm
311    CALP OFFSET(15) NUMBITS(1) [],
312    /// Use an 8-second calibration cycle period
313    CALW8 OFFSET(14) NUMBITS(1) [],
314    /// Use a 16-second calibration cycle period
315    CALW16 OFFSET(13) NUMBITS(1) [],
316    /// Calibration minus
317    CALM OFFSET(0) NUMBITS(9) [],
318],
319RTC_TAFCR[
320    /// RTC_ALARM output type
321    ALARMOUTTYPE OFFSET(18) NUMBITS(1) [],
322    /// TIMESTAMP mapping
323    TSINSEL OFFSET(17) NUMBITS(1) [],
324    /// TAMPER1 mapping
325    TAMP1INSEL OFFSET(16) NUMBITS(1) [],
326    /// TAMPER pull-up disable
327    TAMPPUDIS OFFSET(15) NUMBITS(1) [],
328    /// Tamper prechange duration
329    TAMPPRCH OFFSET(13) NUMBITS(2) [],
330    /// Tamper filter count
331    TAMPFLT OFFSET(11) NUMBITS(2) [],
332    /// Tamper sampling frequency
333    TAMPFREQ OFFSET(8) NUMBITS(3) [],
334    /// Activate timestamp on tamper detection event
335    TAMPTS OFFSET(7) NUMBITS(1) [],
336    /// Active level for tamper 2
337    TAMP2TRG OFFSET(4) NUMBITS(1) [],
338    /// Tamper 2 detection enable
339    TAMP2E OFFSET(3) NUMBITS(1) [],
340    /// Tamper interrupt enable
341    TAMPIE OFFSET(2) NUMBITS(1) [],
342    /// Active level for tamper 1
343    TAMP1TRG OFFSET(1) NUMBITS(1) [],
344    /// Tamper 1 detection enable
345    TAMP1E OFFSET(0) NUMBITS(1) [],
346],
347RTC_ALRMASSR[
348    /// Mask the most-significant bits starting at this bit
349    MASKSS OFFSET(24) NUMBITS(4) [],
350    /// Sub seconds value
351    SS OFFSET(0) NUMBITS(15) [],
352],
353RTC_ALRMBSSR[
354    /// Mask the most-significant bits starting at this bit
355    MASKSS OFFSET(24) NUMBITS(4) [],
356    /// Sub seconds value
357    SS OFFSET(0) NUMBITS(15) [],
358],
359RTC_BKPXR[
360    /// The application can write or read data to and from these registers
361    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    // This function is marked as #[inline(never)] in order to aid with the debugging process when
482    // disabling board memory protection
483    /// Bypass write protection
484    fn bypass_write_protection(&self) {
485        self.registers.rtc_wpr.modify(RTC_WPR::KEY.val(0xCA)); // Equivalent to 0xCA
486        self.registers.rtc_wpr.modify(RTC_WPR::KEY.val(0x53)); // Equivalent to 0x53
487    }
488
489    #[inline(never)]
490    // This function is marked as #[inline(never)] in order to aid with the debugging process when
491    // enabling board memory protection
492    /// Reactivate write protection
493    fn enable_write_protection(&self) {
494        self.registers.rtc_wpr.modify(RTC_WPR::KEY.val(0x42)); // Equivalent to 0x42
495    }
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            // wait until initialization phase mode is entered
544        }
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        // 0: 24-hour format, 1: AM/PM format
575        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        // Enable access to the backup domain
597        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}