@@ -7,9 +7,18 @@ use crate::backup_domain::BackupDomain;
7
7
use crate :: time:: Hertz ;
8
8
9
9
use core:: convert:: Infallible ;
10
+ use core:: marker:: PhantomData ;
10
11
11
12
// The LSE runs at at 32 768 hertz unless an external clock is provided
12
13
const LSE_HERTZ : u32 = 32_768 ;
14
+ const LSI_HERTZ : u32 = 40_000 ;
15
+
16
+ /// RTC clock source HSE clock divided by 128 (type state)
17
+ pub struct RtcClkHseDiv128 ;
18
+ /// RTC clock source LSE oscillator clock (type state)
19
+ pub struct RtcClkLse ;
20
+ /// RTC clock source LSI oscillator clock (type state)
21
+ pub struct RtcClkLsi ;
13
22
14
23
/**
15
24
Real time clock
@@ -28,11 +37,12 @@ const LSE_HERTZ: u32 = 32_768;
28
37
[examples/blinky_rtc.rs]: https://github.com/stm32-rs/stm32f1xx-hal/blob/v0.7.0/examples/blinky_rtc.rs
29
38
*/
30
39
31
- pub struct Rtc {
40
+ pub struct Rtc < CS = RtcClkLse > {
32
41
regs : RTC ,
42
+ _clock_source : PhantomData < CS > ,
33
43
}
34
44
35
- impl Rtc {
45
+ impl Rtc < RtcClkLse > {
36
46
/**
37
47
Initialises the RTC. The `BackupDomain` struct is created by
38
48
`Rcc.bkp.constrain()`.
@@ -43,10 +53,13 @@ impl Rtc {
43
53
power cycles where (VBAT) still has power. Use [set_time](#method.set_time) if you want to
44
54
reset the counter.
45
55
*/
46
- pub fn rtc ( regs : RTC , bkp : & mut BackupDomain ) -> Self {
47
- let mut result = Rtc { regs } ;
56
+ pub fn new ( regs : RTC , bkp : & mut BackupDomain ) -> Self {
57
+ let mut result = Rtc {
58
+ regs,
59
+ _clock_source : PhantomData ,
60
+ } ;
48
61
49
- Rtc :: enable_rtc ( bkp) ;
62
+ Self :: enable_rtc ( bkp) ;
50
63
51
64
// Set the prescaler to make it count up once every second.
52
65
let prl = LSE_HERTZ - 1 ;
@@ -77,7 +90,95 @@ impl Rtc {
77
90
. lse ( )
78
91
} )
79
92
}
93
+ }
94
+
95
+ impl Rtc < RtcClkLsi > {
96
+ pub fn rtc ( regs : RTC , bkp : & mut BackupDomain ) -> Self {
97
+ let mut result = Rtc {
98
+ regs,
99
+ _clock_source : PhantomData ,
100
+ } ;
101
+
102
+ Self :: enable_rtc ( bkp) ;
103
+
104
+ // Set the prescaler to make it count up once every second.
105
+ let prl = LSI_HERTZ - 1 ;
106
+ assert ! ( prl < 1 << 20 ) ;
107
+ result. perform_write ( |s| {
108
+ s. regs . prlh . write ( |w| unsafe { w. bits ( prl >> 16 ) } ) ;
109
+ s. regs . prll . write ( |w| unsafe { w. bits ( prl as u16 as u32 ) } ) ;
110
+ } ) ;
111
+
112
+ result
113
+ }
114
+
115
+ /// Enables the RTC device with the lsi as the clock
116
+ fn enable_rtc ( _bkp : & mut BackupDomain ) {
117
+ // NOTE: Safe RCC access because we are only accessing bdcr
118
+ // and we have a &mut on BackupDomain
119
+ let rcc = unsafe { & * RCC :: ptr ( ) } ;
120
+ rcc. csr . modify ( |_, w| {
121
+ w
122
+ // start the LSI oscillator
123
+ . lsion ( )
124
+ . set_bit ( )
125
+ } ) ;
126
+ rcc. bdcr . modify ( |_, w| {
127
+ w
128
+ // Enable the RTC
129
+ . rtcen ( )
130
+ . set_bit ( )
131
+ // Set the source of the RTC to LSI
132
+ . rtcsel ( )
133
+ . lsi ( )
134
+ } )
135
+ }
136
+ }
137
+
138
+ impl Rtc < RtcClkHseDiv128 > {
139
+ pub fn rtc < F > ( regs : RTC , bkp : & mut BackupDomain , hse : F ) -> Self
140
+ where
141
+ F : Into < Hertz > ,
142
+ {
143
+ let mut result = Rtc {
144
+ regs,
145
+ _clock_source : PhantomData ,
146
+ } ;
147
+
148
+ Self :: enable_rtc ( bkp) ;
149
+
150
+ // Set the prescaler to make it count up once every second.
151
+ let prl = hse. into ( ) . 0 / 128 - 1 ;
152
+ assert ! ( prl < 1 << 20 ) ;
153
+ result. perform_write ( |s| {
154
+ s. regs . prlh . write ( |w| unsafe { w. bits ( prl >> 16 ) } ) ;
155
+ s. regs . prll . write ( |w| unsafe { w. bits ( prl as u16 as u32 ) } ) ;
156
+ } ) ;
157
+
158
+ result
159
+ }
160
+
161
+ /// Enables the RTC device with the lsi as the clock
162
+ fn enable_rtc ( _bkp : & mut BackupDomain ) {
163
+ // NOTE: Safe RCC access because we are only accessing bdcr
164
+ // and we have a &mut on BackupDomain
165
+ let rcc = unsafe { & * RCC :: ptr ( ) } ;
166
+ if rcc. cr . read ( ) . hserdy ( ) . bit_is_clear ( ) {
167
+ panic ! ( "HSE oscillator not ready" ) ;
168
+ }
169
+ rcc. bdcr . modify ( |_, w| {
170
+ w
171
+ // Enable the RTC
172
+ . rtcen ( )
173
+ . set_bit ( )
174
+ // Set the source of the RTC to HSE/128
175
+ . rtcsel ( )
176
+ . hse ( )
177
+ } )
178
+ }
179
+ }
80
180
181
+ impl < CS > Rtc < CS > {
81
182
/// Selects the frequency of the RTC Timer
82
183
/// NOTE: Maximum frequency of 16384 Hz using the internal LSE
83
184
pub fn select_frequency ( & mut self , timeout : impl Into < Hertz > ) {
0 commit comments