@@ -8,6 +8,7 @@ use crate::pac::{rcc::RegisterBlock, PWR, RCC, RTC};
8
8
use crate :: rcc:: Enable ;
9
9
use core:: convert:: TryInto ;
10
10
use core:: fmt;
11
+ use core:: marker:: PhantomData ;
11
12
use time:: { Date , PrimitiveDateTime , Time } ;
12
13
13
14
/// Invalid input error
@@ -17,12 +18,16 @@ pub enum Error {
17
18
InvalidInputData ,
18
19
}
19
20
20
- pub const LSE_BITS : u8 = 0b01 ;
21
+ /// RTC clock source LSE oscillator clock (type state)
22
+ pub struct Lse ;
23
+ /// RTC clock source LSI oscillator clock (type state)
24
+ pub struct Lsi ;
21
25
22
26
/// Real Time Clock peripheral
23
- pub struct Rtc {
27
+ pub struct Rtc < CS = Lse > {
24
28
/// RTC Peripheral register
25
29
pub regs : RTC ,
30
+ _clock_source : PhantomData < CS > ,
26
31
}
27
32
28
33
#[ cfg( feature = "defmt" ) ]
@@ -49,27 +54,27 @@ pub enum LSEClockMode {
49
54
Bypass ,
50
55
}
51
56
52
- impl Rtc {
57
+ impl Rtc < Lse > {
53
58
/// Create and enable a new RTC with external crystal or ceramic resonator and default prescalers.
54
59
pub fn new ( regs : RTC , pwr : & mut PWR ) -> Self {
55
- Self :: with_source ( regs, pwr, LSEClockMode :: Oscillator , 255 , 127 )
60
+ Self :: with_config ( regs, pwr, LSEClockMode :: Oscillator , 255 , 127 )
56
61
}
57
62
58
63
/// Create and enable a new RTC, and configure its clock source and prescalers.
59
64
///
60
- /// From AN4759, Table 7, when using the LSE (The only clock source this module
61
- /// supports currently), set `prediv_s` to 255, and `prediv_a` to 127 to get a
62
- /// calendar clock of 1Hz.
63
- /// The `bypass` argument is `true` if you're using an external oscillator that
64
- /// doesn't connect to `OSC32_IN`, such as a MEMS resonator.
65
- pub fn with_source (
65
+ /// From AN3371, Table 3, when using the LSE,
66
+ /// set `prediv_s` to 255, and `prediv_a` to 127 to get a calendar clock of 1Hz.
67
+ pub fn with_config (
66
68
regs : RTC ,
67
69
pwr : & mut PWR ,
68
70
mode : LSEClockMode ,
69
71
prediv_s : u16 ,
70
72
prediv_a : u8 ,
71
73
) -> Self {
72
- let mut result = Self { regs } ;
74
+ let mut result = Self {
75
+ regs,
76
+ _clock_source : PhantomData ,
77
+ } ;
73
78
74
79
// Steps:
75
80
// Enable PWR and DBP
@@ -90,6 +95,8 @@ impl Rtc {
90
95
if rcc. bdcr . read ( ) . lserdy ( ) . bit_is_clear ( ) {
91
96
result. enable_lse ( rcc, mode) ;
92
97
}
98
+ // Set clock source to LSE.
99
+ rcc. bdcr . modify ( |_, w| w. rtcsel ( ) . lse ( ) ) ;
93
100
result. enable ( rcc) ;
94
101
}
95
102
@@ -122,12 +129,75 @@ impl Rtc {
122
129
LSEClockMode :: Oscillator => bb:: clear ( & rcc. bdcr , 2 ) ,
123
130
}
124
131
while rcc. bdcr . read ( ) . lserdy ( ) . bit_is_clear ( ) { }
125
- // Set clock source to LSE.
126
- // Set BDCR - Bit 8 (RTCSEL to value for LSE)
127
- bb:: set ( & rcc. bdcr , 8 ) ;
128
132
}
129
133
}
134
+ }
135
+
136
+ impl Rtc < Lsi > {
137
+ /// Create and enable a new RTC with internal crystal and default prescalers.
138
+ pub fn new_lsi ( regs : RTC , pwr : & mut PWR ) -> Self {
139
+ Self :: lsi_with_config ( regs, pwr, 249 , 127 )
140
+ }
141
+
142
+ /// Create and enable a new RTC, and configure its clock source and prescalers.
143
+ ///
144
+ /// From AN3371, Table 3, when using the LSI,
145
+ /// set `prediv_s` to 249, and `prediv_a` to 127 to get a calendar clock of 1Hz.
146
+ pub fn lsi_with_config ( regs : RTC , pwr : & mut PWR , prediv_s : u16 , prediv_a : u8 ) -> Self {
147
+ let mut result = Self {
148
+ regs,
149
+ _clock_source : PhantomData ,
150
+ } ;
151
+
152
+ // Steps:
153
+ // Enable PWR and DBP
154
+ // Enable LSI (if needed)
155
+ // Enable RTC Clock
156
+ // Disable Write Protect
157
+ // Enter Init
158
+ // Configure 24 hour format
159
+ // Set prescalers
160
+ // Exit Init
161
+ // Enable write protect
162
+
163
+ unsafe {
164
+ let rcc = & ( * RCC :: ptr ( ) ) ;
165
+ // As per the sample code, unlock comes first. (Enable PWR and DBP)
166
+ result. unlock ( rcc, pwr) ;
167
+ // If necessary, enable the LSE.
168
+ if rcc. csr . read ( ) . lsirdy ( ) . bit_is_clear ( ) {
169
+ result. enable_lsi ( rcc) ;
170
+ }
171
+ // Set clock source to LSI.
172
+ rcc. bdcr . modify ( |_, w| w. rtcsel ( ) . lsi ( ) ) ;
173
+ result. enable ( rcc) ;
174
+ }
175
+
176
+ result. modify ( |regs| {
177
+ // Set 24 Hour
178
+ regs. cr . modify ( |_, w| w. fmt ( ) . clear_bit ( ) ) ;
179
+ // Set prescalers
180
+ regs. prer . modify ( |_, w| {
181
+ w. prediv_s ( ) . bits ( prediv_s) ;
182
+ w. prediv_a ( ) . bits ( prediv_a)
183
+ } )
184
+ } ) ;
185
+
186
+ result
187
+ }
188
+
189
+ fn enable_lsi ( & mut self , rcc : & RegisterBlock ) {
190
+ unsafe {
191
+ // Force a reset of the backup domain.
192
+ self . backup_reset ( rcc) ;
193
+ // Enable the LSI.
194
+ rcc. csr . modify ( |_, w| w. lsion ( ) . on ( ) ) ;
195
+ while rcc. csr . read ( ) . lsirdy ( ) . is_not_ready ( ) { }
196
+ }
197
+ }
198
+ }
130
199
200
+ impl < CS > Rtc < CS > {
131
201
fn unlock ( & mut self , rcc : & RegisterBlock , pwr : & mut PWR ) {
132
202
// Enable the backup interface
133
203
// Set APB1 - Bit 28 (PWREN)
0 commit comments