@@ -81,7 +81,7 @@ impl RccExt for RCC {
81
81
hse : None ,
82
82
lse : None ,
83
83
msi : None ,
84
- hsi48 : false ,
84
+ clk48_source : None ,
85
85
lsi : false ,
86
86
hclk : None ,
87
87
pclk1 : None ,
@@ -148,11 +148,13 @@ impl CRRCR {
148
148
}
149
149
150
150
/// Checks if the 48 MHz HSI is enabled
151
+ #[ inline]
151
152
pub fn is_hsi48_on ( & mut self ) -> bool {
152
153
self . crrcr ( ) . read ( ) . hsi48on ( ) . bit ( )
153
154
}
154
155
155
156
/// Checks if the 48 MHz HSI is ready
157
+ #[ inline]
156
158
pub fn is_hsi48_ready ( & mut self ) -> bool {
157
159
self . crrcr ( ) . read ( ) . hsi48rdy ( ) . bit ( )
158
160
}
@@ -347,14 +349,14 @@ pub struct CFGR {
347
349
hse : Option < HseConfig > ,
348
350
lse : Option < LseConfig > ,
349
351
msi : Option < MsiFreq > ,
350
- hsi48 : bool ,
351
352
lsi : bool ,
352
353
hclk : Option < u32 > ,
353
354
pclk1 : Option < u32 > ,
354
355
pclk2 : Option < u32 > ,
355
356
sysclk : Option < u32 > ,
356
357
pll_source : Option < PllSource > ,
357
358
pll_config : Option < PllConfig > ,
359
+ clk48_source : Option < Clk48Source > ,
358
360
}
359
361
360
362
impl CFGR {
@@ -382,12 +384,6 @@ impl CFGR {
382
384
self
383
385
}
384
386
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
-
391
387
/// Enables the MSI with the specified speed
392
388
pub fn msi ( mut self , range : MsiFreq ) -> Self {
393
389
self . msi = Some ( range) ;
@@ -431,6 +427,11 @@ impl CFGR {
431
427
self
432
428
}
433
429
430
+ pub fn clk48_source ( mut self , source : Clk48Source ) -> Self {
431
+ self . clk48_source = Some ( source) ;
432
+ self
433
+ }
434
+
434
435
/// Freezes the clock configuration, making it effective
435
436
pub fn freeze ( & self , acr : & mut ACR , pwr : & mut Pwr ) -> Clocks {
436
437
let rcc = unsafe { & * RCC :: ptr ( ) } ;
@@ -553,18 +554,40 @@ impl CFGR {
553
554
while rcc. cr . read ( ) . msirdy ( ) . bit_is_clear ( ) { }
554
555
}
555
556
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 ) ) } ;
564
581
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
+ }
568
591
}
569
592
570
593
//
@@ -716,14 +739,23 @@ impl CFGR {
716
739
} )
717
740
}
718
741
742
+ let mut pll48m1clk = None ;
743
+
719
744
let sysclk_src_bits;
720
745
let mut msi = self . msi ;
721
746
if let Some ( pllconf) = pllconf {
722
747
// Sanity-checks per RM0394, 6.4.4 PLL configuration register (RCC_PLLCFGR)
723
748
let r = pllconf. r . to_division_factor ( ) ;
724
749
let clock_speed = clock_speed / ( pllconf. m as u32 + 1 ) ;
725
750
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
+ }
727
759
728
760
assert ! ( r <= 8 ) ; // Allowed max output divider
729
761
assert ! ( pllconf. n >= 8 ) ; // Allowed min multiplier
@@ -732,7 +764,7 @@ impl CFGR {
732
764
assert ! ( clock_speed <= 16_000_000 ) ; // VCO input clock max
733
765
assert ! ( vco >= 64_000_000 ) ; // VCO output min
734
766
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
736
768
737
769
// use PLL as source
738
770
sysclk_src_bits = 0b11 ;
@@ -750,6 +782,8 @@ impl CFGR {
750
782
. bits ( pllconf. r . to_bits ( ) )
751
783
. plln ( )
752
784
. bits ( pllconf. n )
785
+ . pllq ( )
786
+ . bits ( q as u8 )
753
787
} ) ;
754
788
755
789
rcc. cr . modify ( |_, w| w. pllon ( ) . set_bit ( ) ) ;
@@ -810,15 +844,16 @@ impl CFGR {
810
844
lsi : lsi_used,
811
845
lse : self . lse . is_some ( ) ,
812
846
msi,
813
- hsi48 : self . hsi48 ,
814
847
pclk1 : pclk1. Hz ( ) ,
815
848
pclk2 : pclk2. Hz ( ) ,
816
849
ppre1,
817
850
ppre2,
851
+ pll48m1clk,
818
852
sysclk : sysclk. Hz ( ) ,
819
853
timclk1 : timclk1. Hz ( ) ,
820
854
timclk2 : timclk2. Hz ( ) ,
821
855
pll_source : pllconf. map ( |_| pll_source) ,
856
+ clk48_source : self . clk48_source ,
822
857
}
823
858
}
824
859
}
@@ -900,24 +935,44 @@ impl PllSource {
900
935
}
901
936
}
902
937
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
+
903
957
/// Frozen clock frequencies
904
958
///
905
959
/// The existence of this value indicates that the clock configuration can no longer be changed
906
960
#[ derive( Clone , Copy , Debug ) ]
907
961
pub struct Clocks {
908
962
hclk : Hertz ,
909
- hsi48 : bool ,
910
963
msi : Option < MsiFreq > ,
911
964
lsi : bool ,
912
965
lse : bool ,
913
966
pclk1 : Hertz ,
914
967
pclk2 : Hertz ,
915
968
ppre1 : u8 ,
916
969
ppre2 : u8 ,
970
+ pll48m1clk : Option < Hertz > ,
917
971
sysclk : Hertz ,
918
972
timclk1 : Hertz ,
919
973
timclk2 : Hertz ,
920
974
pll_source : Option < PllSource > ,
975
+ clk48_source : Option < Clk48Source > ,
921
976
}
922
977
923
978
impl Clocks {
@@ -928,7 +983,25 @@ impl Clocks {
928
983
929
984
/// Returns status of HSI48
930
985
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
+ }
932
1005
}
933
1006
934
1007
// Returns the status of the MSI
0 commit comments