1+ use crate :: stm32:: rcc:: cfgr:: SWW ;
12use crate :: time:: Hertz ;
23
34/// Extension trait that constrains the `RCC` peripheral
@@ -14,8 +15,7 @@ impl RccExt for crate::stm32::RCC {
1415 hclk : None ,
1516 pclk : None ,
1617 sysclk : None ,
17- enable_hsi : true ,
18- enable_hsi48 : false ,
18+ clock_src : SysClkSource :: HSI ,
1919 } ,
2020 }
2121 }
@@ -26,38 +26,34 @@ pub struct Rcc {
2626 pub cfgr : CFGR ,
2727}
2828
29- #[ allow( unused) ]
3029const HSI : u32 = 8_000_000 ; // Hz
31- #[ allow( unused) ]
3230const HSI48 : u32 = 48_000_000 ; // Hz - (available on STM32F04x, STM32F07x and STM32F09x devices only)
3331
3432#[ allow( unused) ]
3533enum SysClkSource {
36- HSI = 0b00 ,
37- HSE = 0b01 ,
38- PLL = 0b10 ,
39- HSI48 = 0b11 ,
40- }
41-
42- #[ allow( unused) ]
43- enum PllSource {
44- HSI_DIV2 = 0b00 ,
45- HSI = 0b01 ,
46- HSE = 0b10 ,
47- HSI48 = 0b11 ,
34+ HSI ,
35+ HSE ( u32 ) ,
36+ HSI48 ,
4837}
4938
5039#[ allow( unused) ]
5140pub struct CFGR {
5241 hclk : Option < u32 > ,
5342 pclk : Option < u32 > ,
5443 sysclk : Option < u32 > ,
55- enable_hsi : bool ,
56- enable_hsi48 : bool ,
44+ clock_src : SysClkSource ,
5745}
5846
5947#[ cfg( feature = "device-selected" ) ]
6048impl CFGR {
49+ pub fn hse < F > ( mut self , freq : F ) -> Self
50+ where
51+ F : Into < Hertz > ,
52+ {
53+ self . clock_src = SysClkSource :: HSE ( freq. into ( ) . 0 ) ;
54+ self
55+ }
56+
6157 pub fn hclk < F > ( mut self , freq : F ) -> Self
6258 where
6359 F : Into < Hertz > ,
@@ -82,35 +78,21 @@ impl CFGR {
8278 self
8379 }
8480
85- pub fn enable_hsi ( mut self , is_enabled : bool ) -> Self {
86- self . enable_hsi = is_enabled;
87- self
88- }
89-
90- #[ cfg( any( feature = "stm32f042" , feature = "stm32f091" ) ) ]
91- pub fn enable_hsi48 ( mut self , is_enabled : bool ) -> Self {
92- self . enable_hsi48 = is_enabled;
93- self
94- }
95-
9681 pub fn freeze ( self ) -> Clocks {
9782 // Default to lowest frequency clock on all systems.
9883 let sysclk = self . sysclk . unwrap_or ( HSI ) ;
9984
10085 let r_sysclk; // The "real" sysclock value, calculated below
101- let src_clk_freq; // Frequency of source clock for PLL and etc, HSI, or HSI48 on supported systems.
10286 let pllmul_bits;
10387
10488 // Select clock source based on user input and capability
10589 // Highest selected frequency source available takes precedent.
10690 // For F04x, F07x, F09x parts, use HSI48 if requested.
107- if self . enable_hsi48 {
108- src_clk_freq = HSI48 ; // Use HSI48 if requested and available.
109- } else if self . enable_hsi {
110- src_clk_freq = HSI ; // HSI if requested
111- } else {
112- src_clk_freq = HSI ; // If no clock source is selected use HSI.
113- }
91+ let src_clk_freq = match self . clock_src {
92+ SysClkSource :: HSE ( freq) => freq,
93+ SysClkSource :: HSI48 => HSI48 ,
94+ _ => HSI ,
95+ } ;
11496
11597 // Pll check
11698 if sysclk == src_clk_freq {
@@ -165,6 +147,8 @@ impl CFGR {
165147 let ppre: u8 = 1 << ( ppre_bits - 0b011 ) ;
166148 let pclk = hclk / cast:: u32 ( ppre) ;
167149
150+ let rcc = unsafe { & * crate :: stm32:: RCC :: ptr ( ) } ;
151+
168152 // adjust flash wait states
169153 unsafe {
170154 let flash = & * crate :: stm32:: FLASH :: ptr ( ) ;
@@ -179,81 +163,62 @@ impl CFGR {
179163 } )
180164 }
181165
166+ // Enable the requested clock
167+ match self . clock_src {
168+ SysClkSource :: HSE ( _) => {
169+ rcc. cr
170+ . modify ( |_, w| w. csson ( ) . on ( ) . hseon ( ) . on ( ) . hsebyp ( ) . not_bypassed ( ) ) ;
171+
172+ while !rcc. cr . read ( ) . hserdy ( ) . bit_is_set ( ) { }
173+ }
174+ SysClkSource :: HSI48 => {
175+ rcc. cr2 . modify ( |_, w| w. hsi48on ( ) . set_bit ( ) ) ;
176+ while rcc. cr2 . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
177+ }
178+ SysClkSource :: HSI => {
179+ rcc. cr . write ( |w| w. hsion ( ) . set_bit ( ) ) ;
180+ while rcc. cr . read ( ) . hsirdy ( ) . bit_is_clear ( ) { }
181+ }
182+ } ;
183+
182184 let rcc = unsafe { & * crate :: stm32:: RCC :: ptr ( ) } ;
183185
184186 // Set up rcc based on above calculated configuration.
185187
186- // Enable requested clock sources
187- // HSI
188- if self . enable_hsi {
189- rcc. cr . write ( |w| w. hsion ( ) . set_bit ( ) ) ;
190- while rcc. cr . read ( ) . hsirdy ( ) . bit_is_clear ( ) { }
191- }
192- // HSI48
193- if self . enable_hsi48 {
194- rcc. cr2 . modify ( |_, w| w. hsi48on ( ) . set_bit ( ) ) ;
195- while rcc. cr2 . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
196- }
197-
198188 // Enable PLL
199189 if let Some ( pllmul_bits) = pllmul_bits {
200- rcc. cfgr . write ( |w| unsafe { w. pllmul ( ) . bits ( pllmul_bits) } ) ;
201-
202- // Set PLL source based on configuration.
203- if self . enable_hsi48 {
204- rcc. cfgr
205- . modify ( |_, w| w. pllsrc ( ) . bits ( PllSource :: HSI48 as u8 ) ) ;
206- } else if self . enable_hsi {
207- rcc. cfgr
208- . modify ( |_, w| w. pllsrc ( ) . bits ( PllSource :: HSI_DIV2 as u8 ) ) ;
209- } else {
210- rcc. cfgr
211- . modify ( |_, w| w. pllsrc ( ) . bits ( PllSource :: HSI_DIV2 as u8 ) ) ;
212- }
190+ let pllsrc_bit: u8 = match self . clock_src {
191+ SysClkSource :: HSI => 0b00 ,
192+ SysClkSource :: HSI48 => 0b11 ,
193+ SysClkSource :: HSE ( _) => 0b01 ,
194+ } ;
195+
196+ // Set PLL source and multiplier
197+ rcc. cfgr
198+ . write ( |w| unsafe { w. pllsrc ( ) . bits ( pllsrc_bit) . pllmul ( ) . bits ( pllmul_bits) } ) ;
213199
214200 rcc. cr . write ( |w| w. pllon ( ) . set_bit ( ) ) ;
215201 while rcc. cr . read ( ) . pllrdy ( ) . bit_is_clear ( ) { }
216202
217203 rcc. cfgr . modify ( |_, w| unsafe {
204+ w. ppre ( ) . bits ( ppre_bits) . hpre ( ) . bits ( hpre_bits) . sw ( ) . pll ( )
205+ } ) ;
206+ } else {
207+ let sw_var = match self . clock_src {
208+ SysClkSource :: HSI => SWW :: HSI ,
209+ SysClkSource :: HSI48 => SWW :: HSI48 ,
210+ SysClkSource :: HSE ( _) => SWW :: HSE ,
211+ } ;
212+
213+ // use HSI as source
214+ rcc. cfgr . write ( |w| unsafe {
218215 w. ppre ( )
219216 . bits ( ppre_bits)
220217 . hpre ( )
221218 . bits ( hpre_bits)
222219 . sw ( )
223- . bits ( SysClkSource :: PLL as u8 )
220+ . variant ( sw_var )
224221 } ) ;
225- } else {
226- // No PLL required.
227- // Setup requested clocks.
228- if self . enable_hsi48 {
229- rcc. cfgr . modify ( |_, w| unsafe {
230- w. ppre ( )
231- . bits ( ppre_bits)
232- . hpre ( )
233- . bits ( hpre_bits)
234- . sw ( )
235- . bits ( SysClkSource :: HSI48 as u8 )
236- } ) ;
237- } else if self . enable_hsi {
238- rcc. cfgr . modify ( |_, w| unsafe {
239- w. ppre ( )
240- . bits ( ppre_bits)
241- . hpre ( )
242- . bits ( hpre_bits)
243- . sw ( )
244- . bits ( SysClkSource :: HSI as u8 )
245- } ) ;
246- } else {
247- // Default to HSI
248- rcc. cfgr . modify ( |_, w| unsafe {
249- w. ppre ( )
250- . bits ( ppre_bits)
251- . hpre ( )
252- . bits ( hpre_bits)
253- . sw ( )
254- . bits ( SysClkSource :: HSI as u8 )
255- } ) ;
256- }
257222 }
258223
259224 Clocks {
0 commit comments