@@ -81,7 +81,7 @@ impl RccExt for RCC {
8181 hse : None ,
8282 lse : None ,
8383 msi : None ,
84- hsi48 : false ,
84+ clk48_source : None ,
8585 lsi : false ,
8686 hclk : None ,
8787 pclk1 : None ,
@@ -148,11 +148,13 @@ impl CRRCR {
148148 }
149149
150150 /// Checks if the 48 MHz HSI is enabled
151+ #[ inline]
151152 pub fn is_hsi48_on ( & mut self ) -> bool {
152153 self . crrcr ( ) . read ( ) . hsi48on ( ) . bit ( )
153154 }
154155
155156 /// Checks if the 48 MHz HSI is ready
157+ #[ inline]
156158 pub fn is_hsi48_ready ( & mut self ) -> bool {
157159 self . crrcr ( ) . read ( ) . hsi48rdy ( ) . bit ( )
158160 }
@@ -347,14 +349,14 @@ pub struct CFGR {
347349 hse : Option < HseConfig > ,
348350 lse : Option < LseConfig > ,
349351 msi : Option < MsiFreq > ,
350- hsi48 : bool ,
351352 lsi : bool ,
352353 hclk : Option < u32 > ,
353354 pclk1 : Option < u32 > ,
354355 pclk2 : Option < u32 > ,
355356 sysclk : Option < u32 > ,
356357 pll_source : Option < PllSource > ,
357358 pll_config : Option < PllConfig > ,
359+ clk48_source : Option < Clk48Source > ,
358360}
359361
360362impl CFGR {
@@ -382,12 +384,6 @@ impl CFGR {
382384 self
383385 }
384386
385- /// Enable the 48 MHz USB, RNG, SDMMC HSI clock source. Not available on all stm32l4x6 series
386- pub fn hsi48 ( mut self , on : bool ) -> Self {
387- self . hsi48 = on;
388- self
389- }
390-
391387 /// Enables the MSI with the specified speed
392388 pub fn msi ( mut self , range : MsiFreq ) -> Self {
393389 self . msi = Some ( range) ;
@@ -431,6 +427,11 @@ impl CFGR {
431427 self
432428 }
433429
430+ pub fn clk48_source ( mut self , source : Clk48Source ) -> Self {
431+ self . clk48_source = Some ( source) ;
432+ self
433+ }
434+
434435 /// Freezes the clock configuration, making it effective
435436 pub fn freeze ( & self , acr : & mut ACR , pwr : & mut Pwr ) -> Clocks {
436437 let rcc = unsafe { & * RCC :: ptr ( ) } ;
@@ -553,18 +554,35 @@ impl CFGR {
553554 while rcc. cr . read ( ) . msirdy ( ) . bit_is_clear ( ) { }
554555 }
555556
556- // Turn on USB, RNG Clock using the HSI48 CLK source
557- if self . hsi48 {
558- // p. 180 in ref-manual
559- rcc. crrcr . modify ( |_, w| w. hsi48on ( ) . set_bit ( ) ) ;
557+ // Select 48 MHz clock source for SDMMC, USB, RNG, etc.
558+ match self . clk48_source {
559+ None => {
560+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b00 ) ) } ;
561+ }
562+ #[ cfg( any( feature = "stm32l496" , feature = "stm32l4a6" ) ) ]
563+ Some ( Clk48Source :: Hsi48 ) => {
564+ // Turn on USB, RNG Clock using the HSI48 CLK source.
560565
561- // Wait until HSI48 is running
562- while rcc. crrcr . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
563- }
566+ // p. 180 in ref-manual
567+ rcc. crrcr . modify ( |_, w| w. hsi48on ( ) . set_bit ( ) ) ;
568+
569+ // Wait until HSI48 is running.
570+ while rcc. crrcr . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
564571
565- // Select MSI as clock source for usb48, rng ...
566- if let Some ( MsiFreq :: RANGE48M ) = self . msi {
567- unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b11 ) ) } ;
572+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b00 ) ) } ;
573+ }
574+ Some ( Clk48Source :: PllSai1 ) => {
575+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b01 ) ) } ;
576+
577+ unimplemented ! ( )
578+ }
579+ Some ( Clk48Source :: Pll ) => {
580+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b10 ) ) } ;
581+ }
582+ Some ( Clk48Source :: Msi ) => {
583+ assert_eq ! ( Some ( MsiFreq :: RANGE48M ) , self . msi) ;
584+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b11 ) ) } ;
585+ }
568586 }
569587
570588 //
@@ -716,14 +734,23 @@ impl CFGR {
716734 } )
717735 }
718736
737+ let mut pll48m1clk = None ;
738+
719739 let sysclk_src_bits;
720740 let mut msi = self . msi ;
721741 if let Some ( pllconf) = pllconf {
722742 // Sanity-checks per RM0394, 6.4.4 PLL configuration register (RCC_PLLCFGR)
723743 let r = pllconf. r . to_division_factor ( ) ;
724744 let clock_speed = clock_speed / ( pllconf. m as u32 + 1 ) ;
725745 let vco = clock_speed * pllconf. n as u32 ;
726- let output_clock = vco / r;
746+ let pllclk = vco / r;
747+
748+ let q = ( vco + 48_000_000 - 1 ) / 48_000_000 ;
749+ pll48m1clk = Some ( ( vco / q) . Hz ( ) ) ;
750+
751+ if self . clk48_source == Some ( Clk48Source :: Pll ) {
752+ assert_eq ! ( q, 48_000_000 ) ;
753+ }
727754
728755 assert ! ( r <= 8 ) ; // Allowed max output divider
729756 assert ! ( pllconf. n >= 8 ) ; // Allowed min multiplier
@@ -732,7 +759,7 @@ impl CFGR {
732759 assert ! ( clock_speed <= 16_000_000 ) ; // VCO input clock max
733760 assert ! ( vco >= 64_000_000 ) ; // VCO output min
734761 assert ! ( vco <= 334_000_000 ) ; // VCO output max
735- assert ! ( output_clock <= 80_000_000 ) ; // Max output clock
762+ assert ! ( pllclk <= 80_000_000 ) ; // Max output clock
736763
737764 // use PLL as source
738765 sysclk_src_bits = 0b11 ;
@@ -750,6 +777,8 @@ impl CFGR {
750777 . bits ( pllconf. r . to_bits ( ) )
751778 . plln ( )
752779 . bits ( pllconf. n )
780+ . pllq ( )
781+ . bits ( q as u8 )
753782 } ) ;
754783
755784 rcc. cr . modify ( |_, w| w. pllon ( ) . set_bit ( ) ) ;
@@ -810,15 +839,16 @@ impl CFGR {
810839 lsi : lsi_used,
811840 lse : self . lse . is_some ( ) ,
812841 msi,
813- hsi48 : self . hsi48 ,
814842 pclk1 : pclk1. Hz ( ) ,
815843 pclk2 : pclk2. Hz ( ) ,
816844 ppre1,
817845 ppre2,
846+ pll48m1clk,
818847 sysclk : sysclk. Hz ( ) ,
819848 timclk1 : timclk1. Hz ( ) ,
820849 timclk2 : timclk2. Hz ( ) ,
821850 pll_source : pllconf. map ( |_| pll_source) ,
851+ clk48_source : self . clk48_source ,
822852 }
823853 }
824854}
@@ -900,24 +930,39 @@ impl PllSource {
900930 }
901931}
902932
933+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
934+ /// 48 MHz clock source used by USB OTG FS, RNG and SDMMC.
935+ pub enum Clk48Source {
936+ /// HSI48 clock
937+ #[ cfg( any( feature = "stm32l496" , feature = "stm32l4a6" ) ) ]
938+ Hsi48 ,
939+ /// PLLSAI1 “Q” clock (PLL48M2CLK)
940+ PllSai1 ,
941+ /// PLL “Q” clock (PLL48M1CLK)
942+ Pll ,
943+ /// MSI clock
944+ Msi ,
945+ }
946+
903947/// Frozen clock frequencies
904948///
905949/// The existence of this value indicates that the clock configuration can no longer be changed
906950#[ derive( Clone , Copy , Debug ) ]
907951pub struct Clocks {
908952 hclk : Hertz ,
909- hsi48 : bool ,
910953 msi : Option < MsiFreq > ,
911954 lsi : bool ,
912955 lse : bool ,
913956 pclk1 : Hertz ,
914957 pclk2 : Hertz ,
915958 ppre1 : u8 ,
916959 ppre2 : u8 ,
960+ pll48m1clk : Option < Hertz > ,
917961 sysclk : Hertz ,
918962 timclk1 : Hertz ,
919963 timclk2 : Hertz ,
920964 pll_source : Option < PllSource > ,
965+ clk48_source : Option < Clk48Source > ,
921966}
922967
923968impl Clocks {
@@ -928,7 +973,15 @@ impl Clocks {
928973
929974 /// Returns status of HSI48
930975 pub fn hsi48 ( & self ) -> bool {
931- self . hsi48
976+ #[ cfg( any( feature = "stm32l496" , feature = "stm32l4a6" ) ) ]
977+ {
978+ self . clk48_source == Some ( Clk48Source :: Hsi48 )
979+ }
980+
981+ #[ cfg( not( any( feature = "stm32l496" , feature = "stm32l4a6" ) ) ) ]
982+ {
983+ false
984+ }
932985 }
933986
934987 // Returns the status of the MSI
0 commit comments