@@ -8,13 +8,42 @@ use crate::stm32::{rcc, RCC};
88use crate :: flash:: ACR ;
99use crate :: time:: Hertz ;
1010
11+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
12+ pub enum MsiFreq {
13+ #[ doc = "range 0 around 100 kHz" ]
14+ RANGE100K = 0 ,
15+ #[ doc = "range 1 around 200 kHz" ]
16+ RANGE200K = 1 ,
17+ #[ doc = "range 2 around 400 kHz" ]
18+ RANGE400K = 2 ,
19+ #[ doc = "range 3 around 800 kHz" ]
20+ RANGE800K = 3 ,
21+ #[ doc = "range 4 around 1 MHz" ]
22+ RANGE1M = 4 ,
23+ #[ doc = "range 5 around 2 MHz" ]
24+ RANGE2M = 5 ,
25+ #[ doc = "range 6 around 4 MHz" ]
26+ RANGE4M = 6 ,
27+ #[ doc = "range 7 around 8 MHz" ]
28+ RANGE8M = 7 ,
29+ #[ doc = "range 8 around 16 MHz" ]
30+ RANGE16M = 8 ,
31+ #[ doc = "range 9 around 24 MHz" ]
32+ RANGE24M = 9 ,
33+ #[ doc = "range 10 around 32 MHz" ]
34+ RANGE32M = 10 ,
35+ #[ doc = "range 11 around 48 MHz" ]
36+ RANGE48M = 11 ,
37+ }
38+
1139/// Extension trait that constrains the `RCC` peripheral
1240pub trait RccExt {
1341 /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
1442 fn constrain ( self ) -> Rcc ;
1543}
1644
1745impl RccExt for RCC {
46+
1847 fn constrain ( self ) -> Rcc {
1948 Rcc {
2049 ahb1 : AHB1 { _0 : ( ) } ,
@@ -25,10 +54,13 @@ impl RccExt for RCC {
2554 apb2 : APB2 { _0 : ( ) } ,
2655 bdcr : BDCR { _0 : ( ) } ,
2756 csr : CSR { _0 : ( ) } ,
57+ #[ cfg( not( feature = "stm32l47x" ) ) ]
2858 crrcr : CRRCR { _0 : ( ) } ,
2959 cfgr : CFGR {
3060 hclk : None ,
61+ #[ cfg( not( feature = "stm32l47x" ) ) ]
3162 hsi48 : false ,
63+ msi : None ,
3264 lsi : false ,
3365 pclk1 : None ,
3466 pclk2 : None ,
@@ -60,6 +92,7 @@ pub struct Rcc {
6092 /// Control/Status Register
6193 pub csr : CSR ,
6294 /// Clock recovery RC register
95+ #[ cfg( not( feature = "stm32l47x" ) ) ]
6396 pub crrcr : CRRCR ,
6497}
6598
@@ -78,17 +111,20 @@ impl CSR {
78111}
79112
80113/// Clock recovery RC register
114+ #[ cfg( not( feature = "stm32l47x" ) ) ]
81115pub struct CRRCR {
82116 _0 : ( ) ,
83117}
84118
119+ #[ cfg( not( feature = "stm32l47x" ) ) ]
85120impl CRRCR {
86121 // TODO remove `allow`
87122 #[ allow( dead_code) ]
88123 pub ( crate ) fn crrcr ( & mut self ) -> & rcc:: CRRCR {
89124 // NOTE(unsafe) this proxy grants exclusive access to this register
90125 unsafe { & ( * RCC :: ptr ( ) ) . crrcr }
91126 }
127+
92128 pub fn is_hsi48_on ( & mut self ) -> bool {
93129 self . crrcr ( ) . read ( ) . hsi48on ( ) . bit ( )
94130 }
@@ -228,7 +264,9 @@ const HSI: u32 = 16_000_000; // Hz
228264pub struct CFGR {
229265 hclk : Option < u32 > ,
230266 // should we use an option? it can really only be on/off
267+ #[ cfg( not( feature = "stm32l47x" ) ) ]
231268 hsi48 : bool ,
269+ msi : Option < MsiFreq > ,
232270 lsi : bool ,
233271 pclk1 : Option < u32 > ,
234272 pclk2 : Option < u32 > ,
@@ -246,13 +284,20 @@ impl CFGR {
246284 self
247285 }
248286
249- /// Sets HSI48 clock on or off (the default)
287+ /// Enable the 48Mh USB, RNG, SDMMC clock source.
288+ #[ cfg( not( feature = "stm32l47x" ) ) ]
250289 pub fn hsi48 ( mut self , on : bool ) -> Self
251290 {
252291 self . hsi48 = on;
253292 self
254293 }
255294
295+ pub fn msi ( mut self , range : MsiFreq ) -> Self
296+ {
297+ self . msi = Some ( range) ;
298+ self
299+ }
300+
256301 /// Sets LSI clock on (the default) or off
257302 pub fn lsi ( mut self , on : bool ) -> Self
258303 {
@@ -298,7 +343,7 @@ impl CFGR {
298343 }
299344
300345 /// Freezes the clock configuration, making it effective
301- pub fn freeze ( self , acr : & mut ACR ) -> Clocks {
346+ pub fn common_freeze ( & self , acr : & mut ACR ) -> ( Hertz , Hertz , Hertz , u8 , u8 , Hertz ) {
302347
303348 let pllconf = if self . pllcfg . is_none ( ) {
304349 let plln = ( 2 * self . sysclk . unwrap_or ( HSI ) ) / HSI ;
@@ -456,27 +501,73 @@ impl CFGR {
456501 while rcc. csr . read ( ) . lsirdy ( ) . bit_is_clear ( ) { }
457502 }
458503
459- // Turn on HSI48 if required
460- if self . hsi48 {
504+ if let Some ( msi) = self . msi {
505+ unsafe { rcc. cr . modify ( |_, w| w. msirange ( ) . bits ( msi as u8 ) . msirgsel ( ) . set_bit ( ) . msion ( ) . set_bit ( ) ) } ;
506+ // Wait until MSI is running
507+ while rcc. cr . read ( ) . msirdy ( ) . bit_is_clear ( ) { }
508+ }
509+
510+ ( Hertz ( hclk) , Hertz ( pclk1) , Hertz ( pclk2) , ppre1, ppre2, Hertz ( sysclk) )
511+ }
512+
513+
514+ #[ cfg( not( feature = "stm32l47x" ) ) ]
515+ pub fn freeze ( self , acr : & mut ACR ) -> Clocks {
516+
517+ let ( hclk, pclk1, pclk2, ppre1, ppre2, sysclk) = self . common_freeze ( acr) ;
518+ let mut usb_rng = false ;
519+
520+ let rcc = unsafe { & * RCC :: ptr ( ) } ;
521+ // Turn on USB, RNG Clock using the HSI48CLK source (default)
522+ if !cfg ! ( feature = "stm32l47x" ) && self . hsi48 {
461523 // p. 180 in ref-manual
462524 rcc. crrcr . modify ( |_, w| w. hsi48on ( ) . set_bit ( ) ) ;
463525 // Wait until HSI48 is running
464526 while rcc. crrcr . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
527+ usb_rng = true ;
465528 }
466529
530+ Clocks {
531+ hclk,
532+ lsi : self . lsi ,
533+ hsi48 : self . hsi48 ,
534+ usb_rng,
535+ msi : self . msi ,
536+ pclk1,
537+ pclk2,
538+ ppre1,
539+ ppre2,
540+ sysclk,
541+ }
542+ }
543+
544+ #[ cfg( feature = "stm32l47x" ) ]
545+ pub fn freeze ( self , acr : & mut ACR ) -> Clocks {
467546
547+ let ( hclk, pclk1, pclk2, ppre1, ppre2, sysclk) = self . common_freeze ( acr) ;
548+
549+ let mut usb_rng = false ;
550+
551+ let rcc = unsafe { & * RCC :: ptr ( ) } ;
552+ // Select MSI as clock source for usb48, rng ...
553+ if let Some ( MsiFreq :: RANGE48M ) = self . msi {
554+ unsafe { rcc. ccipr . modify ( |_, w| w. clk48sel ( ) . bits ( 0b11 ) ) } ;
555+ usb_rng = true ;
556+ }
468557
469558 Clocks {
470- hclk : Hertz ( hclk) ,
471- hsi48 : self . hsi48 ,
559+ hclk,
472560 lsi : self . lsi ,
473- pclk1 : Hertz ( pclk1) ,
474- pclk2 : Hertz ( pclk2) ,
561+ usb_rng,
562+ msi : self . msi ,
563+ pclk1,
564+ pclk2,
475565 ppre1,
476566 ppre2,
477- sysclk : Hertz ( sysclk ) ,
567+ sysclk,
478568 }
479569 }
570+
480571}
481572
482573#[ derive( Clone , Copy ) ]
@@ -496,7 +587,10 @@ pub struct PllConfig {
496587#[ derive( Clone , Copy , Debug ) ]
497588pub struct Clocks {
498589 hclk : Hertz ,
590+ #[ cfg( not( feature = "stm32l47x" ) ) ]
499591 hsi48 : bool ,
592+ usb_rng : bool ,
593+ msi : Option < MsiFreq > ,
500594 lsi : bool ,
501595 pclk1 : Hertz ,
502596 pclk2 : Hertz ,
@@ -514,10 +608,16 @@ impl Clocks {
514608 }
515609
516610 /// Returns status of HSI48
611+ #[ cfg( not( feature = "stm32l47x" ) ) ]
517612 pub fn hsi48 ( & self ) -> bool {
518613 self . hsi48
519614 }
520615
616+ /// Returns if usb rng clock is available
617+ pub fn usb_rng ( & self ) -> bool {
618+ self . usb_rng
619+ }
620+
521621 /// Returns status of HSI48
522622 pub fn lsi ( & self ) -> bool {
523623 self . lsi
0 commit comments