11//! Reset and Clock Control
22
3+ use core:: default;
4+
35use crate :: pac:: {
46 rcc:: { self , cfgr, cfgr2} ,
57 RCC ,
68} ;
79
810use crate :: flash:: ACR ;
911use 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+ }
1022
1123/// Extension trait that constrains the `RCC` peripheral
1224pub trait RccExt {
@@ -357,7 +369,7 @@ impl CFGR {
357369 feature = "stm32f303xe" ,
358370 feature = "stm32f398"
359371 ) ) ) ]
360- fn calc_pll ( & self , sysclk : u32 ) -> ( u32 , PllConfig ) {
372+ fn calc_pll ( & self , sysclk : u32 ) -> Result < ( u32 , PllConfig ) , RccError > {
361373 let pllsrcclk = self . hse . unwrap_or ( HSI / 2 ) ;
362374 // Get the optimal value for the pll divisor (PLL_DIV) and multiplier (PLL_MUL)
363375 // Only for HSE PLL_DIV can be changed
@@ -377,22 +389,26 @@ impl CFGR {
377389 divisor *= 2 ;
378390 }
379391
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+ }
384396
385397 ( multiplier, Some ( divisor) )
386398 }
387399 // HSI division is always divided by 2 and has no adjustable division
388400 else {
389401 let pll_mul = sysclk / pllsrcclk;
390- assert ! ( pll_mul <= 16 ) ;
402+ if pll_mul <= 16 {
403+ return Err ( RccError :: PllMaxExceeded ) ;
404+ }
391405 ( pll_mul, None )
392406 } ;
393407
394408 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+ }
396412
397413 let pll_src = if self . hse . is_some ( ) {
398414 cfgr:: PLLSRC_A :: HSE_DIV_PREDIV
@@ -404,14 +420,14 @@ impl CFGR {
404420 let pll_mul_bits = into_pll_mul ( pll_mul as u8 ) ;
405421 let pll_div_bits = pll_div. map ( |pll_div| into_pre_div ( pll_div as u8 ) ) ;
406422
407- (
423+ Ok ( (
408424 sysclk,
409425 PllConfig {
410426 src : pll_src,
411427 mul : pll_mul_bits,
412428 div : pll_div_bits,
413429 } ,
414- )
430+ ) )
415431 }
416432
417433 /// Calculate the values for the pll multiplier (PLLMUL) and the pll divisor (PLLDIV).
@@ -423,7 +439,7 @@ impl CFGR {
423439 /// the external oscillator (HSE).
424440 /// After this the system clock frequency (SYSCLK) can be changed via a division and a
425441 /// 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` .
427443 ///
428444 /// To determine the optimal values, the greatest common divisor is calculated and the
429445 /// limitations of the possible values are taken into considiration.
@@ -434,7 +450,7 @@ impl CFGR {
434450 feature = "stm32f303xe" ,
435451 feature = "stm32f398" ,
436452 ) ) ]
437- fn calc_pll ( & self , sysclk : u32 ) -> ( u32 , PllConfig ) {
453+ fn calc_pll ( & self , sysclk : u32 ) -> Result < ( u32 , PllConfig ) , RccError > {
438454 let pllsrcclk = self . hse . unwrap_or ( HSI ) ;
439455
440456 let ( pll_mul, pll_div) = {
@@ -451,17 +467,18 @@ impl CFGR {
451467 divisor *= 2 ;
452468 }
453469
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+ }
459474
460475 ( multiplier, divisor)
461476 } ;
462477
463478 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+ }
465482
466483 // Select hardware clock source of the PLL
467484 // TODO Check whether HSI_DIV2 could be useful
@@ -475,25 +492,25 @@ impl CFGR {
475492 let pll_mul_bits = into_pll_mul ( pll_mul as u8 ) ;
476493 let pll_div_bits = into_pre_div ( pll_div as u8 ) ;
477494
478- (
495+ Ok ( (
479496 sysclk,
480497 PllConfig {
481498 src : pll_src,
482499 mul : pll_mul_bits,
483500 div : Some ( pll_div_bits) ,
484501 } ,
485- )
502+ ) )
486503 }
487504
488505 /// Get the system clock, the system clock source and the pll_options, if needed.
489506 ///
490507 /// The system clock source is determined by the chosen system clock and the provided hardware
491508 /// clock.
492509 /// 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 > {
494511 // If a sysclk is given, check if the PLL has to be used,
495512 // 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 ) {
497514 // No need to use the PLL
498515 // PLL is needed for USB, but we can make this assumption, to not use PLL here,
499516 // because the two valid USB clocks, 72 Mhz and 48 Mhz, can't be generated
@@ -503,23 +520,22 @@ impl CFGR {
503520 // No need to use the PLL
504521 ( Some ( sysclk) , None ) if sysclk == HSI => ( HSI , cfgr:: SW_A :: HSI , None ) ,
505522 ( Some ( sysclk) , _) => {
506- let ( sysclk, pll_config) = self . calc_pll ( sysclk) ;
523+ let ( sysclk, pll_config) = self . calc_pll ( sysclk) ? ;
507524 ( sysclk, cfgr:: SW_A :: PLL , Some ( pll_config) )
508525 }
509526 // Use HSE as system clock
510527 ( None , Some ( hse) ) => ( hse, cfgr:: SW_A :: HSE , None ) ,
511528 // Use HSI as system clock
512529 ( None , None ) => ( HSI , cfgr:: SW_A :: HSI , None ) ,
513- }
530+ } )
514531 }
515532
516533 /// 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 ( ) ? ;
519536
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 ) ? {
523539 0 => unreachable ! ( ) ,
524540 1 => ( cfgr:: HPRE_A :: DIV1 , 1 ) ,
525541 2 => ( cfgr:: HPRE_A :: DIV2 , 2 ) ,
@@ -529,45 +545,56 @@ impl CFGR {
529545 40 ..=95 => ( cfgr:: HPRE_A :: DIV64 , 64 ) ,
530546 96 ..=191 => ( cfgr:: HPRE_A :: DIV128 , 128 ) ,
531547 192 ..=383 => ( cfgr:: HPRE_A :: DIV256 , 256 ) ,
548+ // TODO: Add Error case, if result is to high
532549 _ => ( cfgr:: HPRE_A :: DIV512 , 512 ) ,
533- } )
534- . unwrap_or ( ( cfgr:: HPRE_A :: DIV1 , 1 ) ) ;
550+ }
551+ } else {
552+ ( cfgr:: HPRE_A :: DIV1 , 1 )
553+ } ;
535554
536555 let hclk: u32 = sysclk / hpre;
537556
538- assert ! ( hclk <= 72_000_000 ) ;
557+ if hclk <= 72_000_000 {
558+ return Err ( RccError :: HclkMaxExceeded ) ;
559+ }
539560
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 ) ? {
543563 0 => unreachable ! ( ) ,
544564 1 => ( cfgr:: PPRE1_A :: DIV1 , 1 ) ,
545565 2 => ( cfgr:: PPRE1_A :: DIV2 , 2 ) ,
546566 3 ..=5 => ( cfgr:: PPRE1_A :: DIV4 , 4 ) ,
547567 6 ..=11 => ( cfgr:: PPRE1_A :: DIV8 , 8 ) ,
548568 _ => ( cfgr:: PPRE1_A :: DIV16 , 16 ) ,
549- } )
550- . unwrap_or ( ( cfgr:: PPRE1_A :: DIV1 , 1 ) ) ;
569+ }
570+ } else {
571+ ( cfgr:: PPRE1_A :: DIV1 , 1 )
572+ } ;
551573
552574 let pclk1 = hclk / u32:: from ( ppre1) ;
553575
554- assert ! ( pclk1 <= 36_000_000 ) ;
576+ if pclk1 <= 36_000_000 {
577+ return Err ( RccError :: Pclk1MaxExceeded ) ;
578+ }
555579
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 ) ? {
559582 0 => unreachable ! ( ) ,
560583 1 => ( cfgr:: PPRE2_A :: DIV1 , 1 ) ,
561584 2 => ( cfgr:: PPRE2_A :: DIV2 , 2 ) ,
562585 3 ..=5 => ( cfgr:: PPRE2_A :: DIV4 , 4 ) ,
563586 6 ..=11 => ( cfgr:: PPRE2_A :: DIV8 , 8 ) ,
564587 _ => ( cfgr:: PPRE2_A :: DIV16 , 16 ) ,
565- } )
566- . unwrap_or ( ( cfgr:: PPRE2_A :: DIV1 , 1 ) ) ;
588+ }
589+ } else {
590+ ( cfgr:: PPRE2_A :: DIV1 , 1 )
591+ } ;
567592
568593 let pclk2 = hclk / u32:: from ( ppre2) ;
569594
570- assert ! ( pclk2 <= 72_000_000 ) ;
595+ if pclk2 <= 72_000_000 {
596+ return Err ( RccError :: Pclk2MaxExceeded ) ;
597+ }
571598
572599 // Adjust flash wait states according to the
573600 // HCLK frequency (cpu core clock)
@@ -624,15 +651,15 @@ impl CFGR {
624651 . variant ( sysclk_source)
625652 } ) ;
626653
627- Clocks {
654+ Ok ( Clocks {
628655 hclk : Hertz ( hclk) ,
629656 pclk1 : Hertz ( pclk1) ,
630657 pclk2 : Hertz ( pclk2) ,
631658 ppre1,
632659 ppre2,
633660 sysclk : Hertz ( sysclk) ,
634661 usbclk_valid,
635- }
662+ } )
636663 }
637664}
638665
@@ -686,3 +713,18 @@ impl Clocks {
686713 self . usbclk_valid
687714 }
688715}
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