@@ -30,6 +30,7 @@ impl RccExt for RCC {
3030 pclk1 : None ,
3131 pclk2 : None ,
3232 sysclk : None ,
33+ pllcfg : None ,
3334 } ,
3435 }
3536 }
@@ -204,6 +205,7 @@ pub struct CFGR {
204205 pclk1 : Option < u32 > ,
205206 pclk2 : Option < u32 > ,
206207 sysclk : Option < u32 > ,
208+ pllcfg : Option < PllConfig >
207209}
208210
209211impl CFGR {
@@ -243,17 +245,41 @@ impl CFGR {
243245 self
244246 }
245247
248+ /// Sets the system (core) frequency with some pll configuration
249+ pub fn sysclk_with_pll < F > ( mut self , freq : F , cfg : PllConfig ) -> Self
250+ where
251+ F : Into < Hertz > ,
252+ {
253+ self . pllcfg = Some ( cfg) ;
254+ self . sysclk = Some ( freq. into ( ) . 0 ) ;
255+ self
256+ }
257+
246258 /// Freezes the clock configuration, making it effective
247259 pub fn freeze ( self , acr : & mut ACR ) -> Clocks {
248- let pllmul = ( 2 * self . sysclk . unwrap_or ( HSI ) ) / HSI ;
249- let pllmul = cmp:: min ( cmp:: max ( pllmul, 2 ) , 16 ) ;
250- let pllmul_bits = if pllmul == 2 {
251- None
260+
261+ let pllconf = if self . pllcfg . is_none ( ) {
262+ let plln = ( 2 * self . sysclk . unwrap_or ( HSI ) ) / HSI ;
263+ let plln = cmp:: min ( cmp:: max ( plln, 2 ) , 16 ) ;
264+ if plln == 2 {
265+ None
266+ } else {
267+ // create a best effort pll config, just multiply n
268+ // TODO should we reject this configuration as the clocks stored in RCC could cause timing issues?
269+ let conf = PllConfig {
270+ m : 0b0 ,
271+ r : 0b0 ,
272+ n : plln as u8
273+ } ;
274+ Some ( conf)
275+ }
276+
252277 } else {
253- Some ( pllmul as u8 ) // - 2
278+ let conf = self . pllcfg . unwrap ( ) ;
279+ Some ( conf)
254280 } ;
255281
256- let sysclk = pllmul * HSI / 2 ;
282+ let sysclk = self . sysclk . unwrap_or ( HSI ) ;
257283
258284 assert ! ( sysclk <= 80_000_000 ) ;
259285
@@ -274,7 +300,7 @@ impl CFGR {
274300
275301 let hclk = sysclk / ( 1 << ( hpre_bits) ) ;
276302
277- assert ! ( hclk <= 80_000_000 ) ;
303+ assert ! ( hclk <= sysclk ) ;
278304
279305 let ppre1_bits = self . pclk1
280306 . map ( |pclk1| match hclk / pclk1 {
@@ -290,21 +316,7 @@ impl CFGR {
290316 let ppre1 = 1 << ( ppre1_bits) ;
291317 let pclk1 = hclk / u32 ( ppre1) ;
292318
293- assert ! ( pclk1 <= 80_000_000 ) ;
294-
295- // let ppre2_bits = self.pclk2
296- // .map(|pclk2| match hclk / pclk2 {
297- // 0 => unreachable!(),
298- // 1 => 0b011,
299- // 2 => 0b100,
300- // 3...5 => 0b101,
301- // 6...11 => 0b110,
302- // _ => 0b111,
303- // })
304- // .unwrap_or(0b011);
305-
306- // let ppre2 = 1 << (ppre2_bits - 0b011);
307- // let pclk2 = hclk / u32(ppre2);
319+ assert ! ( pclk1 <= sysclk) ;
308320
309321 let ppre2_bits = self . pclk2
310322 . map ( |pclk2| match hclk / pclk2 {
@@ -320,7 +332,7 @@ impl CFGR {
320332 let ppre2 = 1 << ( ppre2_bits) ;
321333 let pclk2 = hclk / u32 ( ppre2) ;
322334
323- assert ! ( pclk2 <= 80_000_000 ) ;
335+ assert ! ( pclk2 <= sysclk ) ;
324336
325337 // adjust flash wait states
326338 unsafe {
@@ -337,7 +349,7 @@ impl CFGR {
337349
338350 let rcc = unsafe { & * RCC :: ptr ( ) } ;
339351 let sysclk_src_bits;
340- if let Some ( pllmul_bits ) = pllmul_bits {
352+ if let Some ( pllconf ) = pllconf {
341353 // use PLL as source
342354 sysclk_src_bits = 0b11 ;
343355 rcc. cr . modify ( |_, w| w. pllon ( ) . clear_bit ( ) ) ;
@@ -351,9 +363,9 @@ impl CFGR {
351363 . modify ( |_, w| unsafe {
352364 w. pllsrc ( )
353365 . bits ( pllsrc_bits)
354- . pllm ( ) . bits ( 0b0 ) // no division, how to calculate?
355- . pllr ( ) . bits ( 0b0 ) // no division, how to calculate?
356- . plln ( ) . bits ( pllmul_bits )
366+ . pllm ( ) . bits ( pllconf . m )
367+ . pllr ( ) . bits ( pllconf . r )
368+ . plln ( ) . bits ( pllconf . n )
357369 } ) ;
358370
359371 rcc. cr . modify ( |_, w| w. pllon ( ) . set_bit ( ) ) ;
@@ -414,6 +426,17 @@ impl CFGR {
414426 }
415427}
416428
429+ #[ derive( Clone , Copy ) ]
430+ /// Pll Configuration - Calculation = ((SourceClk / m) * n) / r
431+ pub struct PllConfig {
432+ /// Main PLL Division factor
433+ pub m : u8 ,
434+ /// Main Pll Multiplication factor
435+ pub n : u8 ,
436+ /// Main PLL division factor for PLLCLK (system clock)
437+ pub r : u8 ,
438+ }
439+
417440/// Frozen clock frequencies
418441///
419442/// The existence of this value indicates that the clock configuration can no longer be changed
0 commit comments