@@ -6,9 +6,9 @@ use crate::bb;
6
6
use crate :: pac:: rtc:: { dr, tr, DR , TR } ;
7
7
use crate :: pac:: { self , rcc:: RegisterBlock , PWR , RCC , RTC } ;
8
8
use crate :: rcc:: Enable ;
9
- use core:: convert:: { TryFrom , TryInto } ;
10
9
use core:: fmt;
11
10
use core:: marker:: PhantomData ;
11
+ use fugit:: { Duration , ExtU32 , Rate , RateExtU32 } ;
12
12
use time:: { Date , PrimitiveDateTime , Time , Weekday } ;
13
13
14
14
/// Invalid input error
@@ -67,8 +67,24 @@ pub struct Lse;
67
67
/// RTC clock source LSI oscillator clock (type state)
68
68
pub struct Lsi ;
69
69
70
+ pub trait FrequencySource {
71
+ fn frequency ( ) -> fugit:: Hertz < u32 > ;
72
+ }
73
+
74
+ impl FrequencySource for Lse {
75
+ fn frequency ( ) -> fugit:: Hertz < u32 > {
76
+ 32_768u32 . Hz ( )
77
+ }
78
+ }
79
+
80
+ impl FrequencySource for Lsi {
81
+ fn frequency ( ) -> fugit:: Hertz < u32 > {
82
+ 32_000u32 . Hz ( )
83
+ }
84
+ }
85
+
70
86
/// Real Time Clock peripheral
71
- pub struct Rtc < CS = Lse > {
87
+ pub struct Rtc < CS : FrequencySource = Lse > {
72
88
/// RTC Peripheral register
73
89
pub regs : RTC ,
74
90
_clock_source : PhantomData < CS > ,
@@ -239,7 +255,7 @@ impl Rtc<Lsi> {
239
255
}
240
256
}
241
257
242
- impl < CS > Rtc < CS > {
258
+ impl < CS : FrequencySource > Rtc < CS > {
243
259
fn unlock ( & mut self , rcc : & RegisterBlock , pwr : & mut PWR ) {
244
260
// Enable the backup interface
245
261
// Set APB1 - Bit 28 (PWREN)
@@ -530,23 +546,50 @@ impl<CS> Rtc<CS> {
530
546
/// # Panics
531
547
///
532
548
/// Panics if interval is greater than 2¹⁷-1.
533
- pub fn enable_wakeup ( & mut self , interval : fugit:: SecsDurationU32 ) {
534
- let interval = interval. ticks ( ) ;
549
+ pub fn enable_wakeup ( & mut self , interval : fugit:: MicrosDurationU64 ) {
535
550
self . modify ( false , |regs| {
536
551
regs. cr . modify ( |_, w| w. wute ( ) . clear_bit ( ) ) ;
537
552
regs. isr . modify ( |_, w| w. wutf ( ) . clear_bit ( ) ) ;
538
553
while regs. isr . read ( ) . wutwf ( ) . bit_is_clear ( ) { }
539
554
540
- if interval > 1 << 16 {
541
- regs. cr . modify ( |_, w| unsafe { w. wucksel ( ) . bits ( 0b110 ) } ) ;
542
- let interval = u16:: try_from ( interval - ( 1 << 16 ) - 1 )
543
- . expect ( "Interval was too large for wakeup timer" ) ;
555
+ if interval < 32u32 . secs :: < 1 , 1_000_000 > ( ) {
556
+ // Use RTCCLK as the wakeup timer clock source
557
+ let frequency: Rate < u64 , 1 , 1 > = ( CS :: frequency ( ) / 2 ) . into ( ) ;
558
+ let freq_duration: Duration < u64 , 1 , 1000000 > = frequency. into_duration ( ) ;
559
+ let ticks_per_interval = interval / freq_duration;
560
+
561
+ let mut prescaler = 0 ;
562
+ while ticks_per_interval >> prescaler > 1 << 16 {
563
+ prescaler += 1 ;
564
+ }
565
+
566
+ let prescaler_bits = match prescaler {
567
+ 0 => 0b11 , // RTCCLK/2
568
+ 1 => 0b10 , // RTCCLK/4
569
+ 2 => 0b01 , // RTCCLK/8
570
+ 3 => 0b00 , // RTCCLK/16
571
+ _ => unreachable ! ( "Longer durations should use ck_spre" ) ,
572
+ } ;
573
+
574
+ let interval = u16:: try_from ( ( ticks_per_interval >> prescaler) - 1 ) . unwrap ( ) ;
575
+
576
+ regs. cr
577
+ . modify ( |_, w| unsafe { w. wucksel ( ) . bits ( prescaler_bits) } ) ;
544
578
regs. wutr . write ( |w| w. wut ( ) . bits ( interval) ) ;
545
579
} else {
546
- regs. cr . modify ( |_, w| unsafe { w. wucksel ( ) . bits ( 0b100 ) } ) ;
547
- let interval =
548
- u16:: try_from ( interval - 1 ) . expect ( "Interval was too large for wakeup timer" ) ;
549
- regs. wutr . write ( |w| w. wut ( ) . bits ( interval) ) ;
580
+ // Use ck_spre (1Hz) as the wakeup timer clock source
581
+ let interval = interval. to_secs ( ) ;
582
+ if interval > 1 << 16 {
583
+ regs. cr . modify ( |_, w| unsafe { w. wucksel ( ) . bits ( 0b110 ) } ) ;
584
+ let interval = u16:: try_from ( interval - ( 1 << 16 ) - 1 )
585
+ . expect ( "Interval was too large for wakeup timer" ) ;
586
+ regs. wutr . write ( |w| w. wut ( ) . bits ( interval) ) ;
587
+ } else {
588
+ regs. cr . modify ( |_, w| unsafe { w. wucksel ( ) . bits ( 0b100 ) } ) ;
589
+ let interval = u16:: try_from ( interval - 1 )
590
+ . expect ( "Interval was too large for wakeup timer" ) ;
591
+ regs. wutr . write ( |w| w. wut ( ) . bits ( interval) ) ;
592
+ }
550
593
}
551
594
552
595
regs. cr . modify ( |_, w| w. wute ( ) . set_bit ( ) ) ;
0 commit comments