1
1
//! Reset and Clock Control
2
2
3
+ use core:: default;
4
+
3
5
use crate :: pac:: {
4
6
rcc:: { self , cfgr, cfgr2} ,
5
7
RCC ,
6
8
} ;
7
9
8
10
use crate :: flash:: ACR ;
9
11
use crate :: time:: Hertz ;
12
+ use crate :: time:: U32Ext ;
13
+
14
+ #[ derive( Copy , Clone , Debug ) ]
15
+ pub enum RccError {
16
+ PllMaxExceeded ,
17
+ Pclk1MaxExceeded ,
18
+ Pclk2MaxExceeded ,
19
+ SysclkMaxExceeded ,
20
+ HclkMaxExceeded ,
21
+ }
10
22
11
23
/// Extension trait that constrains the `RCC` peripheral
12
24
pub trait RccExt {
@@ -357,7 +369,7 @@ impl CFGR {
357
369
feature = "stm32f303xe" ,
358
370
feature = "stm32f398"
359
371
) ) ) ]
360
- fn calc_pll ( & self , sysclk : u32 ) -> ( u32 , PllConfig ) {
372
+ fn calc_pll ( & self , sysclk : u32 ) -> Result < ( u32 , PllConfig ) , RccError > {
361
373
let pllsrcclk = self . hse . unwrap_or ( HSI / 2 ) ;
362
374
// Get the optimal value for the pll divisor (PLL_DIV) and multiplier (PLL_MUL)
363
375
// Only for HSE PLL_DIV can be changed
@@ -377,22 +389,26 @@ impl CFGR {
377
389
divisor *= 2 ;
378
390
}
379
391
380
- // PLL_MUL maximal value is 16
381
- assert ! ( divisor <= 16 ) ;
382
- // PRE_DIV maximal value is 16
383
- assert ! ( multiplier <= 16 ) ;
392
+ // PLL_MUL and PLLD_DIV maximal values are 16
393
+ if multiplier <= 16 || divisor <= 16 {
394
+ return Err ( RccError :: PllMaxExceeded ) ;
395
+ }
384
396
385
397
( multiplier, Some ( divisor) )
386
398
}
387
399
// HSI division is always divided by 2 and has no adjustable division
388
400
else {
389
401
let pll_mul = sysclk / pllsrcclk;
390
- assert ! ( pll_mul <= 16 ) ;
402
+ if pll_mul <= 16 {
403
+ return Err ( RccError :: PllMaxExceeded ) ;
404
+ }
391
405
( pll_mul, None )
392
406
} ;
393
407
394
408
let sysclk = ( pllsrcclk / pll_div. unwrap_or ( 1 ) ) * pll_mul;
395
- assert ! ( sysclk <= 72_000_000 ) ;
409
+ if sysclk <= 72_000_000 {
410
+ return Err ( RccError :: SysclkMaxExceeded ) ;
411
+ }
396
412
397
413
let pll_src = if self . hse . is_some ( ) {
398
414
cfgr:: PLLSRC_A :: HSE_DIV_PREDIV
@@ -404,14 +420,14 @@ impl CFGR {
404
420
let pll_mul_bits = into_pll_mul ( pll_mul as u8 ) ;
405
421
let pll_div_bits = pll_div. map ( |pll_div| into_pre_div ( pll_div as u8 ) ) ;
406
422
407
- (
423
+ Ok ( (
408
424
sysclk,
409
425
PllConfig {
410
426
src : pll_src,
411
427
mul : pll_mul_bits,
412
428
div : pll_div_bits,
413
429
} ,
414
- )
430
+ ) )
415
431
}
416
432
417
433
/// Calculate the values for the pll multiplier (PLLMUL) and the pll divisor (PLLDIV).
@@ -423,7 +439,7 @@ impl CFGR {
423
439
/// the external oscillator (HSE).
424
440
/// After this the system clock frequency (SYSCLK) can be changed via a division and a
425
441
/// multiplication block.
426
- /// It can be divided from with values 1..16 and multiplied from 2..16.
442
+ /// It can be divided from with values ` 1..16` and multiplied from ` 2..16` .
427
443
///
428
444
/// To determine the optimal values, the greatest common divisor is calculated and the
429
445
/// limitations of the possible values are taken into considiration.
@@ -434,7 +450,7 @@ impl CFGR {
434
450
feature = "stm32f303xe" ,
435
451
feature = "stm32f398" ,
436
452
) ) ]
437
- fn calc_pll ( & self , sysclk : u32 ) -> ( u32 , PllConfig ) {
453
+ fn calc_pll ( & self , sysclk : u32 ) -> Result < ( u32 , PllConfig ) , RccError > {
438
454
let pllsrcclk = self . hse . unwrap_or ( HSI ) ;
439
455
440
456
let ( pll_mul, pll_div) = {
@@ -451,17 +467,18 @@ impl CFGR {
451
467
divisor *= 2 ;
452
468
}
453
469
454
- // PLL_MUL maximal value is 16
455
- assert ! ( multiplier <= 16 ) ;
456
-
457
- // PRE_DIV maximal value is 16
458
- assert ! ( divisor <= 16 ) ;
470
+ // PLL_MUL and PLLD_DIV maximal values are 16
471
+ if multiplier <= 16 || divisor <= 16 {
472
+ return Err ( RccError :: PllMaxExceeded ) ;
473
+ }
459
474
460
475
( multiplier, divisor)
461
476
} ;
462
477
463
478
let sysclk = ( pllsrcclk / pll_div) * pll_mul;
464
- assert ! ( sysclk <= 72_000_000 ) ;
479
+ if sysclk <= 72_000_000 {
480
+ return Err ( RccError :: SysclkMaxExceeded ) ;
481
+ }
465
482
466
483
// Select hardware clock source of the PLL
467
484
// TODO Check whether HSI_DIV2 could be useful
@@ -475,25 +492,25 @@ impl CFGR {
475
492
let pll_mul_bits = into_pll_mul ( pll_mul as u8 ) ;
476
493
let pll_div_bits = into_pre_div ( pll_div as u8 ) ;
477
494
478
- (
495
+ Ok ( (
479
496
sysclk,
480
497
PllConfig {
481
498
src : pll_src,
482
499
mul : pll_mul_bits,
483
500
div : Some ( pll_div_bits) ,
484
501
} ,
485
- )
502
+ ) )
486
503
}
487
504
488
505
/// Get the system clock, the system clock source and the pll_options, if needed.
489
506
///
490
507
/// The system clock source is determined by the chosen system clock and the provided hardware
491
508
/// clock.
492
509
/// This function does only chose the PLL if needed, otherwise it will use the oscillator clock as system clock.
493
- fn get_sysclk ( & self ) -> ( u32 , cfgr:: SW_A , Option < PllConfig > ) {
510
+ fn get_sysclk ( & self ) -> Result < ( u32 , cfgr:: SW_A , Option < PllConfig > ) , RccError > {
494
511
// If a sysclk is given, check if the PLL has to be used,
495
512
// else select the system clock source, which is either HSI or HSE.
496
- match ( self . sysclk , self . hse ) {
513
+ Ok ( match ( self . sysclk , self . hse ) {
497
514
// No need to use the PLL
498
515
// PLL is needed for USB, but we can make this assumption, to not use PLL here,
499
516
// because the two valid USB clocks, 72 Mhz and 48 Mhz, can't be generated
@@ -503,23 +520,22 @@ impl CFGR {
503
520
// No need to use the PLL
504
521
( Some ( sysclk) , None ) if sysclk == HSI => ( HSI , cfgr:: SW_A :: HSI , None ) ,
505
522
( Some ( sysclk) , _) => {
506
- let ( sysclk, pll_config) = self . calc_pll ( sysclk) ;
523
+ let ( sysclk, pll_config) = self . calc_pll ( sysclk) ? ;
507
524
( sysclk, cfgr:: SW_A :: PLL , Some ( pll_config) )
508
525
}
509
526
// Use HSE as system clock
510
527
( None , Some ( hse) ) => ( hse, cfgr:: SW_A :: HSE , None ) ,
511
528
// Use HSI as system clock
512
529
( None , None ) => ( HSI , cfgr:: SW_A :: HSI , None ) ,
513
- }
530
+ } )
514
531
}
515
532
516
533
/// Freezes the clock configuration, making it effective
517
- pub fn freeze ( self , acr : & mut ACR ) -> Clocks {
518
- let ( sysclk, sysclk_source, pll_config) = self . get_sysclk ( ) ;
534
+ pub fn freeze ( self , acr : & mut ACR ) -> Result < Clocks , RccError > {
535
+ let ( sysclk, sysclk_source, pll_config) = self . get_sysclk ( ) ? ;
519
536
520
- let ( hpre_bits, hpre) = self
521
- . hclk
522
- . map ( |hclk| match sysclk / hclk {
537
+ let ( hpre_bits, hpre) = if let Some ( hclk) = self . hclk {
538
+ match sysclk. checked_div ( hclk) . ok_or ( RccError :: HclkMaxExceeded ) ? {
523
539
0 => unreachable ! ( ) ,
524
540
1 => ( cfgr:: HPRE_A :: DIV1 , 1 ) ,
525
541
2 => ( cfgr:: HPRE_A :: DIV2 , 2 ) ,
@@ -529,45 +545,56 @@ impl CFGR {
529
545
40 ..=95 => ( cfgr:: HPRE_A :: DIV64 , 64 ) ,
530
546
96 ..=191 => ( cfgr:: HPRE_A :: DIV128 , 128 ) ,
531
547
192 ..=383 => ( cfgr:: HPRE_A :: DIV256 , 256 ) ,
548
+ // TODO: Add Error case, if result is to high
532
549
_ => ( cfgr:: HPRE_A :: DIV512 , 512 ) ,
533
- } )
534
- . unwrap_or ( ( cfgr:: HPRE_A :: DIV1 , 1 ) ) ;
550
+ }
551
+ } else {
552
+ ( cfgr:: HPRE_A :: DIV1 , 1 )
553
+ } ;
535
554
536
555
let hclk: u32 = sysclk / hpre;
537
556
538
- assert ! ( hclk <= 72_000_000 ) ;
557
+ if hclk <= 72_000_000 {
558
+ return Err ( RccError :: HclkMaxExceeded ) ;
559
+ }
539
560
540
- let ( ppre1_bits, ppre1) = self
541
- . pclk1
542
- . map ( |pclk1| match hclk / pclk1 {
561
+ let ( ppre1_bits, ppre1) = if let Some ( pclk1) = self . pclk1 {
562
+ match hclk. checked_div ( pclk1) . ok_or ( RccError :: Pclk1MaxExceeded ) ? {
543
563
0 => unreachable ! ( ) ,
544
564
1 => ( cfgr:: PPRE1_A :: DIV1 , 1 ) ,
545
565
2 => ( cfgr:: PPRE1_A :: DIV2 , 2 ) ,
546
566
3 ..=5 => ( cfgr:: PPRE1_A :: DIV4 , 4 ) ,
547
567
6 ..=11 => ( cfgr:: PPRE1_A :: DIV8 , 8 ) ,
548
568
_ => ( cfgr:: PPRE1_A :: DIV16 , 16 ) ,
549
- } )
550
- . unwrap_or ( ( cfgr:: PPRE1_A :: DIV1 , 1 ) ) ;
569
+ }
570
+ } else {
571
+ ( cfgr:: PPRE1_A :: DIV1 , 1 )
572
+ } ;
551
573
552
574
let pclk1 = hclk / u32:: from ( ppre1) ;
553
575
554
- assert ! ( pclk1 <= 36_000_000 ) ;
576
+ if pclk1 <= 36_000_000 {
577
+ return Err ( RccError :: Pclk1MaxExceeded ) ;
578
+ }
555
579
556
- let ( ppre2_bits, ppre2) = self
557
- . pclk2
558
- . map ( |pclk2| match hclk / pclk2 {
580
+ let ( ppre2_bits, ppre2) = if let Some ( pclk2) = self . pclk2 {
581
+ match hclk. checked_div ( pclk2) . ok_or ( RccError :: Pclk2MaxExceeded ) ? {
559
582
0 => unreachable ! ( ) ,
560
583
1 => ( cfgr:: PPRE2_A :: DIV1 , 1 ) ,
561
584
2 => ( cfgr:: PPRE2_A :: DIV2 , 2 ) ,
562
585
3 ..=5 => ( cfgr:: PPRE2_A :: DIV4 , 4 ) ,
563
586
6 ..=11 => ( cfgr:: PPRE2_A :: DIV8 , 8 ) ,
564
587
_ => ( cfgr:: PPRE2_A :: DIV16 , 16 ) ,
565
- } )
566
- . unwrap_or ( ( cfgr:: PPRE2_A :: DIV1 , 1 ) ) ;
588
+ }
589
+ } else {
590
+ ( cfgr:: PPRE2_A :: DIV1 , 1 )
591
+ } ;
567
592
568
593
let pclk2 = hclk / u32:: from ( ppre2) ;
569
594
570
- assert ! ( pclk2 <= 72_000_000 ) ;
595
+ if pclk2 <= 72_000_000 {
596
+ return Err ( RccError :: Pclk2MaxExceeded ) ;
597
+ }
571
598
572
599
// Adjust flash wait states according to the
573
600
// HCLK frequency (cpu core clock)
@@ -624,15 +651,15 @@ impl CFGR {
624
651
. variant ( sysclk_source)
625
652
} ) ;
626
653
627
- Clocks {
654
+ Ok ( Clocks {
628
655
hclk : Hertz ( hclk) ,
629
656
pclk1 : Hertz ( pclk1) ,
630
657
pclk2 : Hertz ( pclk2) ,
631
658
ppre1,
632
659
ppre2,
633
660
sysclk : Hertz ( sysclk) ,
634
661
usbclk_valid,
635
- }
662
+ } )
636
663
}
637
664
}
638
665
@@ -686,3 +713,18 @@ impl Clocks {
686
713
self . usbclk_valid
687
714
}
688
715
}
716
+
717
+ // FIXME: Meh this is a public contructor now :(
718
+ impl default:: Default for Clocks {
719
+ fn default ( ) -> Self {
720
+ Self {
721
+ hclk : 8 . mhz ( ) . into ( ) ,
722
+ pclk1 : 8 . mhz ( ) . into ( ) ,
723
+ pclk2 : 8 . mhz ( ) . into ( ) ,
724
+ ppre1 : 1 ,
725
+ ppre2 : 1 ,
726
+ sysclk : 8 . mhz ( ) . into ( ) ,
727
+ usbclk_valid : false ,
728
+ }
729
+ }
730
+ }
0 commit comments