2
2
3
3
use core:: cmp;
4
4
5
- use crate :: stm32:: { rcc, RCC } ;
6
- use cast:: u32;
5
+ use crate :: stm32:: {
6
+ rcc:: { self , cfgr} ,
7
+ RCC ,
8
+ } ;
7
9
8
10
use crate :: flash:: ACR ;
9
11
use crate :: time:: Hertz ;
@@ -99,8 +101,14 @@ const HSI: u32 = 8_000_000; // Hz
99
101
// some microcontrollers do not have USB
100
102
#[ cfg( any( feature = "stm32f301" , feature = "stm32f334" , ) ) ]
101
103
mod usb_clocking {
102
- pub fn has_usb ( ) -> bool {
103
- false
104
+ use crate :: stm32:: rcc:: cfgr;
105
+
106
+ pub fn is_valid (
107
+ _sysclk : & u32 ,
108
+ _hse : & Option < u32 > ,
109
+ _pll_options : & Option < ( cfgr:: PLLMUL_A , cfgr:: PLLSRC_A ) > ,
110
+ ) -> ( bool , bool ) {
111
+ ( false , false )
104
112
}
105
113
106
114
pub fn set_usbpre < W > ( w : & mut W , _: bool ) -> & mut W {
@@ -119,19 +127,29 @@ mod usb_clocking {
119
127
feature = "stm32f398" ,
120
128
) ) ]
121
129
mod usb_clocking {
122
- use crate :: stm32:: rcc;
130
+ use crate :: stm32:: rcc:: cfgr ;
123
131
124
- pub fn has_usb ( ) -> bool {
125
- true
132
+ pub fn is_valid (
133
+ sysclk : & u32 ,
134
+ hse : & Option < u32 > ,
135
+ pll_options : & Option < ( cfgr:: PLLMUL_A , cfgr:: PLLSRC_A ) > ,
136
+ ) -> ( cfgr:: USBPRE_A , bool ) {
137
+ // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
138
+ // PLL output frequency is a supported one.
139
+ // usbpre == false: divide clock by 1.5, otherwise no division
140
+ let usb_ok = hse. is_some ( ) && pll_options. is_some ( ) ;
141
+ match ( usb_ok, sysclk) {
142
+ ( true , 72_000_000 ) => ( cfgr:: USBPRE_A :: DIV1_5 , true ) ,
143
+ ( true , 48_000_000 ) => ( cfgr:: USBPRE_A :: DIV1 , true ) ,
144
+ _ => ( cfgr:: USBPRE_A :: DIV1 , false ) ,
145
+ }
126
146
}
127
147
128
- pub fn set_usbpre ( w : & mut rcc :: cfgr:: W , bit : bool ) -> & mut rcc :: cfgr:: W {
129
- w. usbpre ( ) . bit ( bit )
148
+ pub fn set_usbpre ( w : & mut cfgr:: W , usb_prescale : cfgr :: USBPRE_A ) -> & mut cfgr:: W {
149
+ w. usbpre ( ) . variant ( usb_prescale )
130
150
}
131
151
}
132
152
133
- use self :: usb_clocking:: { has_usb, set_usbpre} ;
134
-
135
153
/// Clock configuration
136
154
pub struct CFGR {
137
155
hse : Option < u32 > ,
@@ -195,14 +213,14 @@ impl CFGR {
195
213
feature = "stm32f303xe" ,
196
214
feature = "stm32f398"
197
215
) ) ) ]
198
- fn calc_pll ( & self ) -> ( u32 , u32 , rcc :: cfgr:: PLLSRC_A ) {
216
+ fn calc_pll ( & self ) -> ( u32 , u32 , cfgr:: PLLSRC_A ) {
199
217
let pllsrcclk = self . hse . unwrap_or ( HSI / 2 ) ;
200
218
let pllmul = self . sysclk . unwrap_or ( pllsrcclk) / pllsrcclk;
201
219
202
220
let pllsrc = if self . hse . is_some ( ) {
203
- rcc :: cfgr:: PLLSRC_A :: HSE_DIV_PREDIV
221
+ cfgr:: PLLSRC_A :: HSE_DIV_PREDIV
204
222
} else {
205
- rcc :: cfgr:: PLLSRC_A :: HSI_DIV2
223
+ cfgr:: PLLSRC_A :: HSI_DIV2
206
224
} ;
207
225
( pllsrcclk, pllmul, pllsrc)
208
226
}
@@ -214,92 +232,108 @@ impl CFGR {
214
232
feature = "stm32f303xe" ,
215
233
feature = "stm32f398" ,
216
234
) ) ]
217
- fn calc_pll ( & self ) -> ( u32 , u32 , rcc :: cfgr:: PLLSRC_A ) {
235
+ fn calc_pll ( & self ) -> ( u32 , u32 , cfgr:: PLLSRC_A ) {
218
236
let mut pllsrcclk = self . hse . unwrap_or ( HSI / 2 ) ;
219
237
let mut pllmul = self . sysclk . unwrap_or ( pllsrcclk) / pllsrcclk;
220
238
221
239
let pllsrc = if self . hse . is_some ( ) {
222
- rcc :: cfgr:: PLLSRC_A :: HSE_DIV_PREDIV
240
+ cfgr:: PLLSRC_A :: HSE_DIV_PREDIV
223
241
} else if pllmul > 16 {
224
242
pllmul /= 2 ;
225
243
pllsrcclk *= 2 ;
226
- rcc :: cfgr:: PLLSRC_A :: HSI_DIV_PREDIV
244
+ cfgr:: PLLSRC_A :: HSI_DIV_PREDIV
227
245
} else {
228
- rcc :: cfgr:: PLLSRC_A :: HSI_DIV2
246
+ cfgr:: PLLSRC_A :: HSI_DIV2
229
247
} ;
230
248
( pllsrcclk, pllmul, pllsrc)
231
249
}
232
250
233
251
/// Returns a tuple containing the effective sysclk rate and optional pll settings.
234
- fn calc_sysclk ( & self ) -> ( u32 , Option < ( u8 , rcc :: cfgr:: PLLSRC_A ) > ) {
252
+ fn calc_sysclk ( & self ) -> ( u32 , Option < ( cfgr :: PLLMUL_A , cfgr:: PLLSRC_A ) > ) {
235
253
let ( pllsrcclk, pllmul, pllsrc) = self . calc_pll ( ) ;
236
254
if pllmul == 1 {
237
255
return ( pllsrcclk, None ) ;
238
256
}
239
257
240
258
let pllmul = cmp:: min ( cmp:: max ( pllmul, 2 ) , 16 ) ;
241
- let sysclk = pllmul * pllsrcclk ;
259
+ let sysclk = pllsrcclk * pllmul ;
242
260
assert ! ( sysclk <= 72_000_000 ) ;
243
261
244
- let pllmul_bits = pllmul as u8 - 2 ;
245
- ( sysclk, Some ( ( pllmul_bits, pllsrc) ) )
262
+ // NOTE From<u8> for PLLMUL_A is not implemented
263
+ let pllmul_mul = match pllmul as u8 {
264
+ 2 => cfgr:: PLLMUL_A :: MUL2 ,
265
+ 3 => cfgr:: PLLMUL_A :: MUL3 ,
266
+ 4 => cfgr:: PLLMUL_A :: MUL4 ,
267
+ 5 => cfgr:: PLLMUL_A :: MUL5 ,
268
+ 6 => cfgr:: PLLMUL_A :: MUL6 ,
269
+ 7 => cfgr:: PLLMUL_A :: MUL7 ,
270
+ 8 => cfgr:: PLLMUL_A :: MUL8 ,
271
+ 9 => cfgr:: PLLMUL_A :: MUL9 ,
272
+ 10 => cfgr:: PLLMUL_A :: MUL10 ,
273
+ 11 => cfgr:: PLLMUL_A :: MUL11 ,
274
+ 12 => cfgr:: PLLMUL_A :: MUL12 ,
275
+ 13 => cfgr:: PLLMUL_A :: MUL13 ,
276
+ 14 => cfgr:: PLLMUL_A :: MUL14 ,
277
+ 15 => cfgr:: PLLMUL_A :: MUL15 ,
278
+ 16 => cfgr:: PLLMUL_A :: MUL16 ,
279
+ _ => unreachable ! ( ) ,
280
+ } ;
281
+ ( sysclk, Some ( ( pllmul_mul, pllsrc) ) )
246
282
}
247
283
248
284
/// Freezes the clock configuration, making it effective
249
285
pub fn freeze ( self , acr : & mut ACR ) -> Clocks {
250
286
let ( sysclk, pll_options) = self . calc_sysclk ( ) ;
251
287
252
- let hpre_bits = self
288
+ let ( hpre_bits, hpre ) = self
253
289
. hclk
254
290
. map ( |hclk| match sysclk / hclk {
255
291
0 => unreachable ! ( ) ,
256
- 1 => 0b0111 ,
257
- 2 => 0b1000 ,
258
- 3 ..=5 => 0b1001 ,
259
- 6 ..=11 => 0b1010 ,
260
- 12 ..=39 => 0b1011 ,
261
- 40 ..=95 => 0b1100 ,
262
- 96 ..=191 => 0b1101 ,
263
- 192 ..=383 => 0b1110 ,
264
- _ => 0b1111 ,
292
+ 1 => ( cfgr :: HPRE_A :: DIV1 , 1 ) ,
293
+ 2 => ( cfgr :: HPRE_A :: DIV2 , 2 ) ,
294
+ 3 ..=5 => ( cfgr :: HPRE_A :: DIV4 , 4 ) ,
295
+ 6 ..=11 => ( cfgr :: HPRE_A :: DIV8 , 8 ) ,
296
+ 12 ..=39 => ( cfgr :: HPRE_A :: DIV16 , 16 ) ,
297
+ 40 ..=95 => ( cfgr :: HPRE_A :: DIV64 , 64 ) ,
298
+ 96 ..=191 => ( cfgr :: HPRE_A :: DIV128 , 128 ) ,
299
+ 192 ..=383 => ( cfgr :: HPRE_A :: DIV256 , 256 ) ,
300
+ _ => ( cfgr :: HPRE_A :: DIV512 , 512 ) ,
265
301
} )
266
- . unwrap_or ( 0b0111 ) ;
302
+ . unwrap_or ( ( cfgr :: HPRE_A :: DIV1 , 1 ) ) ;
267
303
268
- let hclk = sysclk / ( 1 << ( hpre_bits - 0b0111 ) ) ;
304
+ let hclk: u32 = sysclk / hpre ;
269
305
270
306
assert ! ( hclk <= 72_000_000 ) ;
271
307
272
- let ppre1_bits = self
308
+ let ( ppre1_bits, ppre1 ) = self
273
309
. pclk1
274
310
. map ( |pclk1| match hclk / pclk1 {
275
311
0 => unreachable ! ( ) ,
276
- 1 => 0b011 ,
277
- 2 => 0b100 ,
278
- 3 ..=5 => 0b101 ,
279
- 6 ..=11 => 0b110 ,
280
- _ => 0b111 ,
312
+ 1 => ( cfgr :: PPRE1_A :: DIV1 , 1 ) ,
313
+ 2 => ( cfgr :: PPRE1_A :: DIV2 , 2 ) ,
314
+ 3 ..=5 => ( cfgr :: PPRE1_A :: DIV4 , 4 ) ,
315
+ 6 ..=11 => ( cfgr :: PPRE1_A :: DIV8 , 8 ) ,
316
+ _ => ( cfgr :: PPRE1_A :: DIV16 , 16 ) ,
281
317
} )
282
- . unwrap_or ( 0b011 ) ;
318
+ . unwrap_or ( ( cfgr :: PPRE1_A :: DIV1 , 1 ) ) ;
283
319
284
- let ppre1 = 1 << ( ppre1_bits - 0b011 ) ;
285
- let pclk1 = hclk / u32 ( ppre1) ;
320
+ let pclk1 = hclk / u32:: from ( ppre1) ;
286
321
287
322
assert ! ( pclk1 <= 36_000_000 ) ;
288
323
289
- let ppre2_bits = self
324
+ let ( ppre2_bits, ppre2 ) = self
290
325
. pclk2
291
326
. map ( |pclk2| match hclk / pclk2 {
292
327
0 => unreachable ! ( ) ,
293
- 1 => 0b011 ,
294
- 2 => 0b100 ,
295
- 3 ..=5 => 0b101 ,
296
- 6 ..=11 => 0b110 ,
297
- _ => 0b111 ,
328
+ 1 => ( cfgr :: PPRE2_A :: DIV1 , 1 ) ,
329
+ 2 => ( cfgr :: PPRE2_A :: DIV2 , 2 ) ,
330
+ 3 ..=5 => ( cfgr :: PPRE2_A :: DIV4 , 4 ) ,
331
+ 6 ..=11 => ( cfgr :: PPRE2_A :: DIV8 , 8 ) ,
332
+ _ => ( cfgr :: PPRE2_A :: DIV16 , 16 ) ,
298
333
} )
299
- . unwrap_or ( 0b011 ) ;
334
+ . unwrap_or ( ( cfgr :: PPRE2_A :: DIV1 , 1 ) ) ;
300
335
301
- let ppre2 = 1 << ( ppre2_bits - 0b011 ) ;
302
- let pclk2 = hclk / u32 ( ppre2) ;
336
+ let pclk2 = hclk / u32:: from ( ppre2) ;
303
337
304
338
assert ! ( pclk2 <= 72_000_000 ) ;
305
339
@@ -316,56 +350,45 @@ impl CFGR {
316
350
} )
317
351
}
318
352
319
- // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
320
- // PLL output frequency is a supported one.
321
- // usbpre == false: divide clock by 1.5, otherwise no division
322
- let usb_ok = has_usb ( ) && self . hse . is_some ( ) && pll_options. is_some ( ) ;
323
- let ( usbpre, usbclk_valid) = match ( usb_ok, sysclk) {
324
- ( true , 72_000_000 ) => ( false , true ) ,
325
- ( true , 48_000_000 ) => ( true , true ) ,
326
- _ => ( true , false ) ,
327
- } ;
353
+ let ( usbpre, usbclk_valid) = usb_clocking:: is_valid ( & sysclk, & self . hse , & pll_options) ;
328
354
329
355
let rcc = unsafe { & * RCC :: ptr ( ) } ;
330
356
331
357
if self . hse . is_some ( ) {
332
358
// enable HSE and wait for it to be ready
359
+ rcc. cr . modify ( |_, w| w. hseon ( ) . on ( ) ) ;
333
360
334
- rcc. cr . modify ( |_, w| w. hseon ( ) . set_bit ( ) ) ;
335
-
336
- while rcc. cr . read ( ) . hserdy ( ) . bit_is_clear ( ) { }
361
+ while rcc. cr . read ( ) . hserdy ( ) . is_not_ready ( ) { }
337
362
}
338
363
339
- if let Some ( ( pllmul_bits , pllsrc) ) = pll_options {
364
+ if let Some ( ( pllmul_mul , pllsrc) ) = pll_options {
340
365
// enable PLL and wait for it to be ready
341
366
rcc. cfgr
342
- . modify ( |_, w| w. pllmul ( ) . bits ( pllmul_bits ) . pllsrc ( ) . variant ( pllsrc) ) ;
367
+ . modify ( |_, w| w. pllmul ( ) . variant ( pllmul_mul ) . pllsrc ( ) . variant ( pllsrc) ) ;
343
368
344
- rcc. cr . modify ( |_, w| w. pllon ( ) . set_bit ( ) ) ;
369
+ rcc. cr . modify ( |_, w| w. pllon ( ) . on ( ) ) ;
345
370
346
- while rcc. cr . read ( ) . pllrdy ( ) . bit_is_clear ( ) { }
371
+ while rcc. cr . read ( ) . pllrdy ( ) . is_not_ready ( ) { }
347
372
}
348
373
349
374
// set prescalers and clock source
350
- rcc. cfgr . modify ( |_, w| unsafe {
351
- set_usbpre ( w, usbpre)
352
- . ppre2 ( )
353
- . bits ( ppre2_bits)
375
+ rcc. cfgr . modify ( |_, w| {
376
+ usb_clocking:: set_usbpre ( w, usbpre) ;
377
+
378
+ w. ppre2 ( )
379
+ . variant ( ppre2_bits)
354
380
. ppre1 ( )
355
- . bits ( ppre1_bits)
381
+ . variant ( ppre1_bits)
356
382
. hpre ( )
357
- . bits ( hpre_bits)
358
- . sw ( )
359
- . bits ( if pll_options. is_some ( ) {
360
- // PLL
361
- 0b10
362
- } else if self . hse . is_some ( ) {
363
- // HSE
364
- 0b01
365
- } else {
366
- // HSI
367
- 0b00
368
- } )
383
+ . variant ( hpre_bits) ;
384
+
385
+ if pll_options. is_some ( ) {
386
+ w. sw ( ) . pll ( )
387
+ } else if self . hse . is_some ( ) {
388
+ w. sw ( ) . hse ( )
389
+ } else {
390
+ w. sw ( ) . hsi ( )
391
+ }
369
392
} ) ;
370
393
371
394
Clocks {
0 commit comments