@@ -222,7 +222,7 @@ impl CFGR {
222
222
/// wherever it is possible.
223
223
pub fn freeze ( self ) -> Clocks {
224
224
let flash = unsafe { & ( * FLASH :: ptr ( ) ) } ;
225
- let rcc = unsafe { & * RCC :: ptr ( ) } ;
225
+ let rcc = unsafe { & ( * RCC :: ptr ( ) ) } ;
226
226
227
227
// If HSE is provided by the user
228
228
let hse_freq: u32 = self . hse . as_ref ( ) . map_or ( 0 , |c| c. freq ) ;
@@ -233,131 +233,130 @@ impl CFGR {
233
233
_ => hse_freq
234
234
} ;
235
235
236
- if sysclk <= base_clk { // We can use the base clock directly
237
- match & self . hse {
238
- // If HSE clock is provided, we use it
239
- Some ( _) => rcc. cfgr . modify ( |_, w| w. sw ( ) . hse ( ) ) ,
240
- // If HSE is not provided, we use HSI
241
- None => rcc. cfgr . modify ( |_, w| w. sw ( ) . hsi ( ) )
242
- } ;
236
+ // Configure HSE if provided
237
+ if self . hse . is_some ( ) {
238
+ // Configure the HSE mode
239
+ match self . hse . as_ref ( ) . unwrap ( ) . mode {
240
+ HSEClockMode :: Bypass => { rcc. cr . modify (
241
+ |_, w| w. hsebyp ( ) . bypassed ( )
242
+ ) } ,
243
+ HSEClockMode :: Oscillator => { rcc. cr . modify (
244
+ |_, w| w. hsebyp ( ) . not_bypassed ( )
245
+ ) }
246
+ }
247
+ // Start HSE
248
+ rcc. cr . modify ( |_, w| w. hseon ( ) . on ( ) ) ;
249
+ while rcc. cr . read ( ) . hserdy ( ) . is_not_ready ( ) { }
250
+ }
243
251
244
- } else { // A PLL is needed to multiply the frequence
252
+ let mut use_pll = false ;
253
+
254
+ if sysclk != base_clk { // A PLL is needed to multiply / divide the frequence
245
255
// Input divisor from HSI/HSE clock, must result in less than 2MHz, and
246
256
// must be between 2 and 63. In this case, the condition is always
247
257
// respected. We set it at 2MHz as recommanded by the user manual.
248
- let pllm = base_clk / 2_000_000 ;
249
- let pllp_val: u32 ;
250
- let vco_clkin = base_clk / pllm;
251
-
252
- // Sysclk output divisor, must result in >= 24MHz and <= 216MHz
253
- // needs to be the equivalent of 2, 4, 6 or 8
254
- // We can calculate that:
255
- // * PLLP = 2 => SYSCLK \in [25*vco_clkin ; 216*vco_clkin]
256
- // * PLLP = 4 => SYSCLK \in [12,5*vco_clkin ; 108*vco_clkin]
257
- // * PLLP = 6 => SYSCLK \in [8,33*vco_clkin ; 72*vco_clkin ]
258
- // * PLLP = 8 => SYSCLK \in [6,25*vco_clkin ; 54*vco_clkin ]
259
- let pllp = if sysclk >= 25 * vco_clkin {
260
- pllp_val = 2 ;
261
- 0b00
262
- } else if sysclk >= 13 * vco_clkin {
263
- pllp_val = 4 ;
264
- 0b01
265
- } else if sysclk >= 9 * vco_clkin {
266
- pllp_val = 6 ;
267
- 0b10
268
- } else {
269
- pllp_val = 8 ;
270
- 0b11
271
- } ;
258
+ let pllm = ( ( base_clk as f32 ) / ( 2_000_000 as f32 ) ) . ceil ( ) as u8 ;
259
+ let vco_clkin_mhz = ( base_clk as f32 / pllm as f32 ) / 1_000_000.0 ;
260
+ let mut sysclk_mhz: f32 = sysclk as f32 / 1_000_000.0 ;
272
261
273
262
// PLLN, main scaler, must result in >= 192MHz and <= 432MHz, min
274
263
// 50, max 432, this constraint is allways respected when vco_clkin
275
- // = 2 MHz
276
- let plln = ( sysclk / vco_clkin) * pllp_val;
277
- // Check that the desired SYSCLK is physically feasible. /1000 is to
278
- // avoid u32 overflow
279
- assert ! ( ( base_clk / 1_000 ) * plln >= sysclk / 1_000 ) ;
280
- // Update sysclk with the real value
281
- sysclk = ( vco_clkin * plln) / pllp_val;
282
-
283
- match & self . hse {
284
- // If HSE is provided
285
- Some ( hse) => {
286
- // Configure the HSE mode
287
- match hse. mode {
288
- HSEClockMode :: Bypass => { rcc. cr . modify (
289
- |_, w| w. hsebyp ( ) . bypassed ( )
290
- ) } ,
291
- HSEClockMode :: Oscillator => { rcc. cr . modify (
292
- |_, w| w. hsebyp ( ) . not_bypassed ( )
293
- ) }
294
- }
295
-
296
- // Configure PLL from HSI
297
- rcc. pllcfgr . write ( |w| unsafe {
298
- w
299
- . pllsrc ( ) . hse ( )
300
- . pllm ( ) . bits ( pllm as u8 )
301
- . plln ( ) . bits ( plln as u16 )
302
- . pllp ( ) . bits ( pllp)
303
- } ) ;
304
- } ,
305
- // If HSE is not provided
306
- None => {
307
- // configure PLL from HSI
308
- rcc. pllcfgr . write ( |w| unsafe {
309
- w
310
- . pllsrc ( ) . hsi ( )
311
- . pllm ( ) . bits ( pllm as u8 )
312
- . plln ( ) . bits ( plln as u16 )
313
- . pllp ( ) . bits ( pllp)
314
- } ) ;
315
-
316
- } ,
264
+ // <= 2 MHz
265
+ let mut plln: f32 = 100.0 ;
266
+ let allowed_pllp: [ u8 ; 4 ] = [ 2 , 4 , 6 , 8 ] ;
267
+ let pllp_val = * allowed_pllp. iter ( ) . min_by_key ( |& pllp| {
268
+ plln = ( ( sysclk_mhz * ( * pllp as f32 ) ) / vco_clkin_mhz) . floor ( ) ;
269
+ let error = sysclk_mhz - ( ( plln/( * pllp as f32 ) ) * vco_clkin_mhz) ;
270
+
271
+ if error < 0.0
272
+ || plln * vco_clkin_mhz > 432.0
273
+ || plln > 432.0 || plln < 100.0 { core:: u32:: MAX }
274
+ else { ( error* 1_000.0 ) as u32 }
275
+ } ) . unwrap ( ) ;
276
+
277
+ // PLLN coresponding to the best pllp_val
278
+ plln = ( ( sysclk_mhz * ( pllp_val as f32 ) ) / vco_clkin_mhz) . floor ( ) ;
279
+
280
+ // Pllp bits to be written in the register
281
+ let pllp = match pllp_val {
282
+ 2 => 0b00 ,
283
+ 4 => 0b01 ,
284
+ 6 => 0b10 ,
285
+ 8 => 0b11 ,
286
+ _ => unreachable ! ( )
317
287
} ;
318
288
289
+ // Update the real sysclk value
290
+ sysclk_mhz = ( vco_clkin_mhz * plln) / ( pllp_val as f32 ) ;
291
+ sysclk = ( sysclk_mhz * 1_000_000.0 ) as u32 ;
292
+
293
+
294
+ // Turn PLL off
295
+ rcc. cr . modify ( |_, w| w. pllon ( ) . off ( ) ) ;
296
+ // Wait till PLL is disabled
297
+ while ! rcc. cr . read ( ) . pllrdy ( ) . is_not_ready ( ) { }
298
+
299
+ if self . hse . is_some ( ) { // If HSE is provided
300
+ // Configure PLL from HSE
301
+ rcc. pllcfgr . write ( |w| unsafe {
302
+ w
303
+ . pllsrc ( ) . hse ( )
304
+ . pllm ( ) . bits ( pllm as u8 )
305
+ . plln ( ) . bits ( plln as u16 )
306
+ . pllp ( ) . bits ( pllp)
307
+ . pllq ( ) . bits ( 9 )
308
+ } ) ;
309
+ } else { // If HSE is not provided
310
+ // configure PLL from HSI
311
+ rcc. pllcfgr . modify ( |_, w| unsafe {
312
+ w
313
+ . pllsrc ( ) . hsi ( )
314
+ . pllm ( ) . bits ( pllm as u8 )
315
+ . plln ( ) . bits ( plln as u16 )
316
+ . pllp ( ) . bits ( pllp)
317
+ } ) ;
318
+ }
319
+
319
320
// Enable PLL
320
- rcc. cr . modify ( |_, w| w. pllon ( ) . set_bit ( ) ) ;
321
- // Wait for PLL to stabilise
322
- while rcc. cr . read ( ) . pllrdy ( ) . bit_is_set ( ) { }
321
+ rcc. cr . modify ( |_, w| w. pllon ( ) . on ( ) ) ;
322
+ // // Wait for PLL to stabilise
323
+ while rcc. cr . read ( ) . pllrdy ( ) . is_not_ready ( ) { }
323
324
324
- // Use PLL as SYSCLK
325
- // rcc.cfgr.modify(|_, w| unsafe { w.sw().bits(0b10 as u8) });
326
- rcc. cfgr . modify ( |_, w| w. sw ( ) . pll ( ) ) ;
325
+ use_pll = true ;
327
326
}
328
327
329
328
// HCLK. By default, SYSCLK frequence is chosen. Because of the method
330
329
// of clock multiplication and division, even if `sysclk` is set to be
331
330
// the same as `hclk`, it can be slighly inferior to `sysclk` after
332
- // pllm, pllp... calculations
333
- let mut hclk: u32 = min ( sysclk, self . hclk . unwrap_or ( sysclk) ) ;
331
+ // pllm, pllp... calculations
332
+ let mut hclk: u32 = sysclk ; // min(sysclk, self.hclk.unwrap_or(sysclk));
334
333
335
334
// Configure HPRE.
336
- let mut hpre_val: u32 = sysclk / hclk;
335
+ let hpre_val: f32 = ( sysclk as f32 / hclk as f32 ) . ceil ( ) ;
337
336
338
337
// The real value of hpre is computed to be as near as possible to the
339
338
// desired value, this leads to a quantization error
340
- let hpre = match hpre_val {
339
+ let ( hpre_val , hpre) : ( f32 , u8 ) = match hpre_val as u32 {
341
340
0 => unreachable ! ( ) ,
342
- 1 => { hpre_val = 1 ; 0b000 } ,
343
- 2 => { hpre_val = 2 ; 0b1000 } ,
344
- 3 ..=5 => { hpre_val = 4 ; 0b1001 } ,
345
- 6 ..=11 => { hpre_val = 8 ; 0b1010 } ,
346
- 12 ..=39 => { hpre_val = 16 ; 0b1011 } ,
347
- 40 ..=95 => { hpre_val = 64 ; 0b1100 } ,
348
- 96 ..=191 => { hpre_val = 128 ; 0b1101 } ,
349
- 192 ..=383 => { hpre_val = 256 ; 0b1110 } ,
350
- _ => { hpre_val = 256 ; 0b1111 } ,
341
+ 1 => ( 1.0 , 0b000 ) ,
342
+ 2 => ( 2.0 , 0b1000 ) ,
343
+ 3 ..=5 => ( 4.0 , 0b1001 ) ,
344
+ 6 ..=11 => ( 8.0 , 0b1010 ) ,
345
+ 12 ..=39 => ( 16.0 , 0b1011 ) ,
346
+ 40 ..=95 => ( 64.0 , 0b1100 ) ,
347
+ 96 ..=191 => ( 128.0 , 0b1101 ) ,
348
+ 192 ..=383 => ( 256.0 , 0b1110 ) ,
349
+ _ => ( 512.0 , 0b1111 )
351
350
} ;
352
351
// update hclk with the real value
353
- hclk = sysclk / hpre_val;
352
+ hclk = ( sysclk as f32 / hpre_val) . floor ( ) as u32 ;
354
353
355
354
// PCLK1 (APB1). Must be <= 54 Mhz. By default, min(hclk, 54Mhz) is
356
355
// chosen
357
- let mut pclk1: u32 = self . pclk1 . unwrap_or ( min ( 54_000_000 , hclk) ) ;
356
+ let mut pclk1: u32 = min ( 54_000_000 , self . pclk1 . unwrap_or ( hclk) ) ;
358
357
// PCLK2 (APB2). Must be <= 108 Mhz. By default, min(hclk, 108Mhz) is
359
358
// chosen
360
- let mut pclk2: u32 = self . pclk2 . unwrap_or ( min ( 108_000_000 , hclk) ) ;
359
+ let mut pclk2: u32 = min ( 108_000_000 , self . pclk2 . unwrap_or ( hclk) ) ;
361
360
362
361
// Configure PPRE1
363
362
let mut ppre1_val: u32 = ( hclk as f32 / pclk1 as f32 ) . ceil ( ) as u32 ;
@@ -385,14 +384,6 @@ impl CFGR {
385
384
// update pclk2 with the real value
386
385
pclk2 = hclk / ppre2_val;
387
386
388
- // Configure HCLK, PCLK1, PCLK2
389
- rcc. cfgr . modify ( |_, w| unsafe {
390
- w
391
- . ppre1 ( ) . bits ( ppre1 as u8 )
392
- . ppre2 ( ) . bits ( ppre2 as u8 )
393
- . hpre ( ) . bits ( hpre as u8 )
394
- } ) ;
395
-
396
387
// Assumes TIMPRE bit of RCC_DCKCFGR1 is reset (0)
397
388
let timclk1 = if ppre1_val == 1 { pclk1} else { 2 * pclk1} ;
398
389
let timclk2 = if ppre2_val == 1 { pclk2} else { 2 * pclk2} ;
@@ -418,6 +409,32 @@ impl CFGR {
418
409
} )
419
410
} ) ;
420
411
412
+ // Select SYSCLK source
413
+ if use_pll {
414
+ rcc. cfgr . modify ( |_, w| w. sw ( ) . pll ( ) ) ;
415
+ while ! rcc. cfgr . read ( ) . sws ( ) . is_pll ( ) { }
416
+
417
+ } else if self . hse . is_some ( ) {
418
+ rcc. cfgr . modify ( |_, w| w. sw ( ) . hse ( ) ) ;
419
+ while ! rcc. cfgr . read ( ) . sws ( ) . is_hse ( ) { }
420
+
421
+ } else {
422
+ rcc. cfgr . modify ( |_, w| w. sw ( ) . hsi ( ) ) ;
423
+ while ! rcc. cfgr . read ( ) . sws ( ) . is_hsi ( ) { }
424
+ }
425
+
426
+ // Configure HCLK, PCLK1, PCLK2
427
+ rcc. cfgr . modify ( |_, w| unsafe {
428
+ w
429
+ . ppre1 ( ) . bits ( ppre1 as u8 )
430
+ . ppre2 ( ) . bits ( ppre2 as u8 )
431
+ . hpre ( ) . bits ( hpre as u8 )
432
+ } ) ;
433
+
434
+ // As requested by user manual we need to wit 16 ticks before the right
435
+ // predivision is applied
436
+ cortex_m:: asm:: delay ( 16 ) ;
437
+
421
438
Clocks {
422
439
hclk : Hertz ( hclk) ,
423
440
pclk1 : Hertz ( pclk1) ,
0 commit comments