@@ -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,40 @@ 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 ( ) ) ;
560-
561- // Wait until HSI48 is running
562- while rcc. crrcr . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
563- }
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(
563+ feature = "stm32l476" ,
564+ feature = "stm32l486" ,
565+ feature = "stm32l496" ,
566+ feature = "stm32l4a6"
567+ ) ) ]
568+ Some ( Clk48Source :: Hsi48 ) => {
569+ // Turn on USB, RNG Clock using the HSI48 CLK source.
570+
571+ // p. 180 in ref-manual
572+ rcc. crrcr . modify ( |_, w| w. hsi48on ( ) . set_bit ( ) ) ;
573+
574+ // Wait until HSI48 is running.
575+ while rcc. crrcr . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
576+
577+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b00 ) ) } ;
578+ }
579+ Some ( Clk48Source :: PllSai1 ) => {
580+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b01 ) ) } ;
564581
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 ) ) } ;
582+ unimplemented ! ( )
583+ }
584+ Some ( Clk48Source :: Pll ) => {
585+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b10 ) ) } ;
586+ }
587+ Some ( Clk48Source :: Msi ) => {
588+ assert_eq ! ( Some ( MsiFreq :: RANGE48M ) , self . msi) ;
589+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b11 ) ) } ;
590+ }
568591 }
569592
570593 //
@@ -716,14 +739,23 @@ impl CFGR {
716739 } )
717740 }
718741
742+ let mut pll48m1clk = None ;
743+
719744 let sysclk_src_bits;
720745 let mut msi = self . msi ;
721746 if let Some ( pllconf) = pllconf {
722747 // Sanity-checks per RM0394, 6.4.4 PLL configuration register (RCC_PLLCFGR)
723748 let r = pllconf. r . to_division_factor ( ) ;
724749 let clock_speed = clock_speed / ( pllconf. m as u32 + 1 ) ;
725750 let vco = clock_speed * pllconf. n as u32 ;
726- let output_clock = vco / r;
751+ let pllclk = vco / r;
752+
753+ let q = ( vco + 48_000_000 - 1 ) / 48_000_000 ;
754+ pll48m1clk = Some ( ( vco / q) . Hz ( ) ) ;
755+
756+ if self . clk48_source == Some ( Clk48Source :: Pll ) {
757+ assert_eq ! ( q, 48_000_000 ) ;
758+ }
727759
728760 assert ! ( r <= 8 ) ; // Allowed max output divider
729761 assert ! ( pllconf. n >= 8 ) ; // Allowed min multiplier
@@ -732,7 +764,7 @@ impl CFGR {
732764 assert ! ( clock_speed <= 16_000_000 ) ; // VCO input clock max
733765 assert ! ( vco >= 64_000_000 ) ; // VCO output min
734766 assert ! ( vco <= 334_000_000 ) ; // VCO output max
735- assert ! ( output_clock <= 80_000_000 ) ; // Max output clock
767+ assert ! ( pllclk <= 80_000_000 ) ; // Max output clock
736768
737769 // use PLL as source
738770 sysclk_src_bits = 0b11 ;
@@ -750,6 +782,8 @@ impl CFGR {
750782 . bits ( pllconf. r . to_bits ( ) )
751783 . plln ( )
752784 . bits ( pllconf. n )
785+ . pllq ( )
786+ . bits ( q as u8 )
753787 } ) ;
754788
755789 rcc. cr . modify ( |_, w| w. pllon ( ) . set_bit ( ) ) ;
@@ -810,15 +844,16 @@ impl CFGR {
810844 lsi : lsi_used,
811845 lse : self . lse . is_some ( ) ,
812846 msi,
813- hsi48 : self . hsi48 ,
814847 pclk1 : pclk1. Hz ( ) ,
815848 pclk2 : pclk2. Hz ( ) ,
816849 ppre1,
817850 ppre2,
851+ pll48m1clk,
818852 sysclk : sysclk. Hz ( ) ,
819853 timclk1 : timclk1. Hz ( ) ,
820854 timclk2 : timclk2. Hz ( ) ,
821855 pll_source : pllconf. map ( |_| pll_source) ,
856+ clk48_source : self . clk48_source ,
822857 }
823858 }
824859}
@@ -900,24 +935,44 @@ impl PllSource {
900935 }
901936}
902937
938+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
939+ /// 48 MHz clock source used by USB OTG FS, RNG and SDMMC.
940+ pub enum Clk48Source {
941+ /// HSI48 clock
942+ #[ cfg( any(
943+ feature = "stm32l476" ,
944+ feature = "stm32l486" ,
945+ feature = "stm32l496" ,
946+ feature = "stm32l4a6"
947+ ) ) ]
948+ Hsi48 ,
949+ /// PLLSAI1 “Q” clock (PLL48M2CLK)
950+ PllSai1 ,
951+ /// PLL “Q” clock (PLL48M1CLK)
952+ Pll ,
953+ /// MSI clock
954+ Msi ,
955+ }
956+
903957/// Frozen clock frequencies
904958///
905959/// The existence of this value indicates that the clock configuration can no longer be changed
906960#[ derive( Clone , Copy , Debug ) ]
907961pub struct Clocks {
908962 hclk : Hertz ,
909- hsi48 : bool ,
910963 msi : Option < MsiFreq > ,
911964 lsi : bool ,
912965 lse : bool ,
913966 pclk1 : Hertz ,
914967 pclk2 : Hertz ,
915968 ppre1 : u8 ,
916969 ppre2 : u8 ,
970+ pll48m1clk : Option < Hertz > ,
917971 sysclk : Hertz ,
918972 timclk1 : Hertz ,
919973 timclk2 : Hertz ,
920974 pll_source : Option < PllSource > ,
975+ clk48_source : Option < Clk48Source > ,
921976}
922977
923978impl Clocks {
@@ -928,7 +983,25 @@ impl Clocks {
928983
929984 /// Returns status of HSI48
930985 pub fn hsi48 ( & self ) -> bool {
931- self . hsi48
986+ #[ cfg( any(
987+ feature = "stm32l476" ,
988+ feature = "stm32l486" ,
989+ feature = "stm32l496" ,
990+ feature = "stm32l4a6"
991+ ) ) ]
992+ {
993+ self . clk48_source == Some ( Clk48Source :: Hsi48 )
994+ }
995+
996+ #[ cfg( not( any(
997+ feature = "stm32l476" ,
998+ feature = "stm32l486" ,
999+ feature = "stm32l496" ,
1000+ feature = "stm32l4a6"
1001+ ) ) ) ]
1002+ {
1003+ false
1004+ }
9321005 }
9331006
9341007 // Returns the status of the MSI
0 commit comments