@@ -7,7 +7,6 @@ use crate::pac::rtc::{dr, tr};
77use crate :: pac:: { self , rcc:: RegisterBlock , PWR , RCC , RTC } ;
88use crate :: rcc:: Enable ;
99use core:: fmt;
10- use core:: marker:: PhantomData ;
1110use fugit:: RateExtU32 ;
1211use time:: { Date , PrimitiveDateTime , Time , Weekday } ;
1312
@@ -67,27 +66,33 @@ pub struct Lse;
6766/// RTC clock source LSI oscillator clock (type state)
6867pub struct Lsi ;
6968
70- pub trait FrequencySource {
71- fn frequency ( ) -> fugit:: Hertz < u32 > ;
69+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
70+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
71+ pub enum ClockSource {
72+ Lse ( LSEClockMode ) ,
73+ Lsi ,
7274}
7375
74- impl FrequencySource for Lse {
75- fn frequency ( ) -> fugit :: Hertz < u32 > {
76- 32_768u32 . Hz ( )
76+ impl From < LSEClockMode > for ClockSource {
77+ fn from ( value : LSEClockMode ) -> Self {
78+ Self :: Lse ( value )
7779 }
7880}
7981
80- impl FrequencySource for Lsi {
81- fn frequency ( ) -> fugit:: Hertz < u32 > {
82- 32_000u32 . Hz ( )
82+ impl ClockSource {
83+ pub fn frequency ( self ) -> fugit:: Hertz < u32 > {
84+ match self {
85+ Self :: Lse ( _) => 32_768_u32 . Hz ( ) ,
86+ Self :: Lsi => 32 . kHz ( ) ,
87+ }
8388 }
8489}
8590
8691/// Real Time Clock peripheral
87- pub struct Rtc < CS : FrequencySource = Lse > {
92+ pub struct Rtc {
8893 /// RTC Peripheral register
8994 pub regs : RTC ,
90- _clock_source : PhantomData < CS > ,
95+ clock_source : ClockSource ,
9196}
9297
9398#[ cfg( feature = "defmt" ) ]
@@ -114,31 +119,30 @@ pub enum LSEClockMode {
114119 Bypass ,
115120}
116121
117- impl Rtc < Lse > {
122+ impl Rtc {
118123 /// Create and enable a new RTC with external crystal or ceramic resonator and default prescalers.
119124 pub fn new ( regs : RTC , pwr : & mut PWR ) -> Self {
120125 Self :: with_config ( regs, pwr, LSEClockMode :: Oscillator , 255 , 127 )
121126 }
122-
123127 /// Create and enable a new RTC, and configure its clock source and prescalers.
124128 ///
125- /// From AN3371, Table 3, when using the LSE,
126- /// set `prediv_s` to 255, and `prediv_a` to 127 to get a calendar clock of 1Hz.
129+ /// From AN3371, Table 3,
130+ /// set `prediv_s` to 255 (249 for LSI) , and `prediv_a` to 127 to get a calendar clock of 1Hz.
127131 pub fn with_config (
128132 regs : RTC ,
129133 pwr : & mut PWR ,
130- mode : LSEClockMode ,
134+ clock_source : impl Into < ClockSource > ,
131135 prediv_s : u16 ,
132136 prediv_a : u8 ,
133137 ) -> Self {
134138 let mut result = Self {
135139 regs,
136- _clock_source : PhantomData ,
140+ clock_source : clock_source . into ( ) ,
137141 } ;
138142
139143 // Steps:
140144 // Enable PWR and DBP
141- // Enable LSE (if needed)
145+ // Enable LSE/LSI (if needed)
142146 // Enable RTC Clock
143147 // Disable Write Protect
144148 // Enter Init
@@ -151,12 +155,24 @@ impl Rtc<Lse> {
151155 let rcc = & ( * RCC :: ptr ( ) ) ;
152156 // As per the sample code, unlock comes first. (Enable PWR and DBP)
153157 result. unlock ( rcc, pwr) ;
154- // If necessary, enable the LSE.
155- if rcc. bdcr ( ) . read ( ) . lserdy ( ) . bit_is_clear ( ) {
156- result. enable_lse ( rcc, mode) ;
158+ match result. clock_source {
159+ ClockSource :: Lse ( mode) => {
160+ // If necessary, enable the LSE.
161+ if rcc. bdcr ( ) . read ( ) . lserdy ( ) . bit_is_clear ( ) {
162+ result. enable_lse ( rcc, mode) ;
163+ }
164+ // Set clock source to LSE.
165+ rcc. bdcr ( ) . modify ( |_, w| w. rtcsel ( ) . lse ( ) ) ;
166+ }
167+ ClockSource :: Lsi => {
168+ // If necessary, enable the LSE.
169+ if rcc. csr ( ) . read ( ) . lsirdy ( ) . bit_is_clear ( ) {
170+ result. enable_lsi ( rcc) ;
171+ }
172+ // Set clock source to LSI.
173+ rcc. bdcr ( ) . modify ( |_, w| w. rtcsel ( ) . lsi ( ) ) ;
174+ }
157175 }
158- // Set clock source to LSE.
159- rcc. bdcr ( ) . modify ( |_, w| w. rtcsel ( ) . lse ( ) ) ;
160176 result. enable ( rcc) ;
161177 }
162178
@@ -191,59 +207,18 @@ impl Rtc<Lse> {
191207 while rcc. bdcr ( ) . read ( ) . lserdy ( ) . bit_is_clear ( ) { }
192208 }
193209 }
194- }
195210
196- impl Rtc < Lsi > {
197211 /// Create and enable a new RTC with internal crystal and default prescalers.
198212 pub fn new_lsi ( regs : RTC , pwr : & mut PWR ) -> Self {
199- Self :: lsi_with_config ( regs, pwr, 249 , 127 )
213+ Self :: with_config ( regs, pwr, ClockSource :: Lsi , 249 , 127 )
200214 }
201215
202216 /// Create and enable a new RTC, and configure its clock source and prescalers.
203217 ///
204218 /// From AN3371, Table 3, when using the LSI,
205219 /// set `prediv_s` to 249, and `prediv_a` to 127 to get a calendar clock of 1Hz.
206220 pub fn lsi_with_config ( regs : RTC , pwr : & mut PWR , prediv_s : u16 , prediv_a : u8 ) -> Self {
207- let mut result = Self {
208- regs,
209- _clock_source : PhantomData ,
210- } ;
211-
212- // Steps:
213- // Enable PWR and DBP
214- // Enable LSI (if needed)
215- // Enable RTC Clock
216- // Disable Write Protect
217- // Enter Init
218- // Configure 24 hour format
219- // Set prescalers
220- // Exit Init
221- // Enable write protect
222-
223- unsafe {
224- let rcc = & ( * RCC :: ptr ( ) ) ;
225- // As per the sample code, unlock comes first. (Enable PWR and DBP)
226- result. unlock ( rcc, pwr) ;
227- // If necessary, enable the LSE.
228- if rcc. csr ( ) . read ( ) . lsirdy ( ) . bit_is_clear ( ) {
229- result. enable_lsi ( rcc) ;
230- }
231- // Set clock source to LSI.
232- rcc. bdcr ( ) . modify ( |_, w| w. rtcsel ( ) . lsi ( ) ) ;
233- result. enable ( rcc) ;
234- }
235-
236- result. modify ( true , |regs| {
237- // Set 24 Hour
238- regs. cr ( ) . modify ( |_, w| w. fmt ( ) . clear_bit ( ) ) ;
239- // Set prescalers
240- regs. prer ( ) . modify ( |_, w| {
241- w. prediv_s ( ) . set ( prediv_s) ;
242- w. prediv_a ( ) . set ( prediv_a)
243- } )
244- } ) ;
245-
246- result
221+ Self :: with_config ( regs, pwr, ClockSource :: Lsi , prediv_s, prediv_a)
247222 }
248223
249224 fn enable_lsi ( & mut self , rcc : & RegisterBlock ) {
@@ -253,9 +228,7 @@ impl Rtc<Lsi> {
253228 rcc. csr ( ) . modify ( |_, w| w. lsion ( ) . on ( ) ) ;
254229 while rcc. csr ( ) . read ( ) . lsirdy ( ) . is_not_ready ( ) { }
255230 }
256- }
257231
258- impl < CS : FrequencySource > Rtc < CS > {
259232 fn unlock ( & mut self , rcc : & RegisterBlock , pwr : & mut PWR ) {
260233 // Enable the backup interface
261234 // Set APB1 - Bit 28 (PWREN)
@@ -543,6 +516,7 @@ impl<CS: FrequencySource> Rtc<CS> {
543516 ///
544517 /// Panics if interval is greater than 2¹⁷-1 seconds.
545518 pub fn enable_wakeup ( & mut self , interval : fugit:: MicrosDurationU64 ) {
519+ let clock_source = self . clock_source ;
546520 self . modify ( false , |regs| {
547521 regs. cr ( ) . modify ( |_, w| w. wute ( ) . clear_bit ( ) ) ;
548522 regs. isr ( ) . modify ( |_, w| w. wutf ( ) . clear_bit ( ) ) ;
@@ -551,7 +525,7 @@ impl<CS: FrequencySource> Rtc<CS> {
551525 use crate :: pac:: rtc:: cr:: WUCKSEL ;
552526 if interval < fugit:: MicrosDurationU64 :: secs ( 32 ) {
553527 // Use RTCCLK as the wakeup timer clock source
554- let frequency: fugit:: Hertz < u64 > = ( CS :: frequency ( ) / 2 ) . into ( ) ;
528+ let frequency: fugit:: Hertz < u64 > = ( clock_source . frequency ( ) / 2 ) . into ( ) ;
555529 let freq_duration: fugit:: MicrosDurationU64 = frequency. into_duration ( ) ;
556530 let ticks_per_interval = interval / freq_duration;
557531
0 commit comments