@@ -7,7 +7,6 @@ use crate::pac::rtc::{dr, tr};
7
7
use crate :: pac:: { self , rcc:: RegisterBlock , PWR , RCC , RTC } ;
8
8
use crate :: rcc:: Enable ;
9
9
use core:: fmt;
10
- use core:: marker:: PhantomData ;
11
10
use fugit:: RateExtU32 ;
12
11
use time:: { Date , PrimitiveDateTime , Time , Weekday } ;
13
12
@@ -67,27 +66,33 @@ pub struct Lse;
67
66
/// RTC clock source LSI oscillator clock (type state)
68
67
pub struct Lsi ;
69
68
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 ,
72
74
}
73
75
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 )
77
79
}
78
80
}
79
81
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
+ }
83
88
}
84
89
}
85
90
86
91
/// Real Time Clock peripheral
87
- pub struct Rtc < CS : FrequencySource = Lse > {
92
+ pub struct Rtc {
88
93
/// RTC Peripheral register
89
94
pub regs : RTC ,
90
- _clock_source : PhantomData < CS > ,
95
+ clock_source : ClockSource ,
91
96
}
92
97
93
98
#[ cfg( feature = "defmt" ) ]
@@ -114,31 +119,30 @@ pub enum LSEClockMode {
114
119
Bypass ,
115
120
}
116
121
117
- impl Rtc < Lse > {
122
+ impl Rtc {
118
123
/// Create and enable a new RTC with external crystal or ceramic resonator and default prescalers.
119
124
pub fn new ( regs : RTC , pwr : & mut PWR ) -> Self {
120
125
Self :: with_config ( regs, pwr, LSEClockMode :: Oscillator , 255 , 127 )
121
126
}
122
-
123
127
/// Create and enable a new RTC, and configure its clock source and prescalers.
124
128
///
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.
127
131
pub fn with_config (
128
132
regs : RTC ,
129
133
pwr : & mut PWR ,
130
- mode : LSEClockMode ,
134
+ clock_source : impl Into < ClockSource > ,
131
135
prediv_s : u16 ,
132
136
prediv_a : u8 ,
133
137
) -> Self {
134
138
let mut result = Self {
135
139
regs,
136
- _clock_source : PhantomData ,
140
+ clock_source : clock_source . into ( ) ,
137
141
} ;
138
142
139
143
// Steps:
140
144
// Enable PWR and DBP
141
- // Enable LSE (if needed)
145
+ // Enable LSE/LSI (if needed)
142
146
// Enable RTC Clock
143
147
// Disable Write Protect
144
148
// Enter Init
@@ -151,12 +155,24 @@ impl Rtc<Lse> {
151
155
let rcc = & ( * RCC :: ptr ( ) ) ;
152
156
// As per the sample code, unlock comes first. (Enable PWR and DBP)
153
157
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
+ }
157
175
}
158
- // Set clock source to LSE.
159
- rcc. bdcr ( ) . modify ( |_, w| w. rtcsel ( ) . lse ( ) ) ;
160
176
result. enable ( rcc) ;
161
177
}
162
178
@@ -191,59 +207,18 @@ impl Rtc<Lse> {
191
207
while rcc. bdcr ( ) . read ( ) . lserdy ( ) . bit_is_clear ( ) { }
192
208
}
193
209
}
194
- }
195
210
196
- impl Rtc < Lsi > {
197
211
/// Create and enable a new RTC with internal crystal and default prescalers.
198
212
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 )
200
214
}
201
215
202
216
/// Create and enable a new RTC, and configure its clock source and prescalers.
203
217
///
204
218
/// From AN3371, Table 3, when using the LSI,
205
219
/// set `prediv_s` to 249, and `prediv_a` to 127 to get a calendar clock of 1Hz.
206
220
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)
247
222
}
248
223
249
224
fn enable_lsi ( & mut self , rcc : & RegisterBlock ) {
@@ -253,9 +228,7 @@ impl Rtc<Lsi> {
253
228
rcc. csr ( ) . modify ( |_, w| w. lsion ( ) . on ( ) ) ;
254
229
while rcc. csr ( ) . read ( ) . lsirdy ( ) . is_not_ready ( ) { }
255
230
}
256
- }
257
231
258
- impl < CS : FrequencySource > Rtc < CS > {
259
232
fn unlock ( & mut self , rcc : & RegisterBlock , pwr : & mut PWR ) {
260
233
// Enable the backup interface
261
234
// Set APB1 - Bit 28 (PWREN)
@@ -543,6 +516,7 @@ impl<CS: FrequencySource> Rtc<CS> {
543
516
///
544
517
/// Panics if interval is greater than 2¹⁷-1 seconds.
545
518
pub fn enable_wakeup ( & mut self , interval : fugit:: MicrosDurationU64 ) {
519
+ let clock_source = self . clock_source ;
546
520
self . modify ( false , |regs| {
547
521
regs. cr ( ) . modify ( |_, w| w. wute ( ) . clear_bit ( ) ) ;
548
522
regs. isr ( ) . modify ( |_, w| w. wutf ( ) . clear_bit ( ) ) ;
@@ -551,7 +525,7 @@ impl<CS: FrequencySource> Rtc<CS> {
551
525
use crate :: pac:: rtc:: cr:: WUCKSEL ;
552
526
if interval < fugit:: MicrosDurationU64 :: secs ( 32 ) {
553
527
// 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 ( ) ;
555
529
let freq_duration: fugit:: MicrosDurationU64 = frequency. into_duration ( ) ;
556
530
let ticks_per_interval = interval / freq_duration;
557
531
0 commit comments