@@ -8,13 +8,42 @@ use crate::stm32::{rcc, RCC};
8
8
use crate :: flash:: ACR ;
9
9
use crate :: time:: Hertz ;
10
10
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
+
11
39
/// Extension trait that constrains the `RCC` peripheral
12
40
pub trait RccExt {
13
41
/// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
14
42
fn constrain ( self ) -> Rcc ;
15
43
}
16
44
17
45
impl RccExt for RCC {
46
+
18
47
fn constrain ( self ) -> Rcc {
19
48
Rcc {
20
49
ahb1 : AHB1 { _0 : ( ) } ,
@@ -25,10 +54,13 @@ impl RccExt for RCC {
25
54
apb2 : APB2 { _0 : ( ) } ,
26
55
bdcr : BDCR { _0 : ( ) } ,
27
56
csr : CSR { _0 : ( ) } ,
57
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
28
58
crrcr : CRRCR { _0 : ( ) } ,
29
59
cfgr : CFGR {
30
60
hclk : None ,
61
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
31
62
hsi48 : false ,
63
+ msi : None ,
32
64
lsi : false ,
33
65
pclk1 : None ,
34
66
pclk2 : None ,
@@ -60,6 +92,7 @@ pub struct Rcc {
60
92
/// Control/Status Register
61
93
pub csr : CSR ,
62
94
/// Clock recovery RC register
95
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
63
96
pub crrcr : CRRCR ,
64
97
}
65
98
@@ -78,17 +111,20 @@ impl CSR {
78
111
}
79
112
80
113
/// Clock recovery RC register
114
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
81
115
pub struct CRRCR {
82
116
_0 : ( ) ,
83
117
}
84
118
119
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
85
120
impl CRRCR {
86
121
// TODO remove `allow`
87
122
#[ allow( dead_code) ]
88
123
pub ( crate ) fn crrcr ( & mut self ) -> & rcc:: CRRCR {
89
124
// NOTE(unsafe) this proxy grants exclusive access to this register
90
125
unsafe { & ( * RCC :: ptr ( ) ) . crrcr }
91
126
}
127
+
92
128
pub fn is_hsi48_on ( & mut self ) -> bool {
93
129
self . crrcr ( ) . read ( ) . hsi48on ( ) . bit ( )
94
130
}
@@ -228,7 +264,9 @@ const HSI: u32 = 16_000_000; // Hz
228
264
pub struct CFGR {
229
265
hclk : Option < u32 > ,
230
266
// should we use an option? it can really only be on/off
267
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
231
268
hsi48 : bool ,
269
+ msi : Option < MsiFreq > ,
232
270
lsi : bool ,
233
271
pclk1 : Option < u32 > ,
234
272
pclk2 : Option < u32 > ,
@@ -246,13 +284,20 @@ impl CFGR {
246
284
self
247
285
}
248
286
249
- /// Sets HSI48 clock on or off (the default)
287
+ /// Enable the 48Mh USB, RNG, SDMMC clock source.
288
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
250
289
pub fn hsi48 ( mut self , on : bool ) -> Self
251
290
{
252
291
self . hsi48 = on;
253
292
self
254
293
}
255
294
295
+ pub fn msi ( mut self , range : MsiFreq ) -> Self
296
+ {
297
+ self . msi = Some ( range) ;
298
+ self
299
+ }
300
+
256
301
/// Sets LSI clock on (the default) or off
257
302
pub fn lsi ( mut self , on : bool ) -> Self
258
303
{
@@ -298,7 +343,7 @@ impl CFGR {
298
343
}
299
344
300
345
/// 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 ) {
302
347
303
348
let pllconf = if self . pllcfg . is_none ( ) {
304
349
let plln = ( 2 * self . sysclk . unwrap_or ( HSI ) ) / HSI ;
@@ -456,27 +501,73 @@ impl CFGR {
456
501
while rcc. csr . read ( ) . lsirdy ( ) . bit_is_clear ( ) { }
457
502
}
458
503
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 {
461
523
// p. 180 in ref-manual
462
524
rcc. crrcr . modify ( |_, w| w. hsi48on ( ) . set_bit ( ) ) ;
463
525
// Wait until HSI48 is running
464
526
while rcc. crrcr . read ( ) . hsi48rdy ( ) . bit_is_clear ( ) { }
527
+ usb_rng = true ;
465
528
}
466
529
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 {
467
546
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
+ }
468
557
469
558
Clocks {
470
- hclk : Hertz ( hclk) ,
471
- hsi48 : self . hsi48 ,
559
+ hclk,
472
560
lsi : self . lsi ,
473
- pclk1 : Hertz ( pclk1) ,
474
- pclk2 : Hertz ( pclk2) ,
561
+ usb_rng,
562
+ msi : self . msi ,
563
+ pclk1,
564
+ pclk2,
475
565
ppre1,
476
566
ppre2,
477
- sysclk : Hertz ( sysclk ) ,
567
+ sysclk,
478
568
}
479
569
}
570
+
480
571
}
481
572
482
573
#[ derive( Clone , Copy ) ]
@@ -496,7 +587,10 @@ pub struct PllConfig {
496
587
#[ derive( Clone , Copy , Debug ) ]
497
588
pub struct Clocks {
498
589
hclk : Hertz ,
590
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
499
591
hsi48 : bool ,
592
+ usb_rng : bool ,
593
+ msi : Option < MsiFreq > ,
500
594
lsi : bool ,
501
595
pclk1 : Hertz ,
502
596
pclk2 : Hertz ,
@@ -514,10 +608,16 @@ impl Clocks {
514
608
}
515
609
516
610
/// Returns status of HSI48
611
+ #[ cfg( not( feature = "stm32l47x" ) ) ]
517
612
pub fn hsi48 ( & self ) -> bool {
518
613
self . hsi48
519
614
}
520
615
616
+ /// Returns if usb rng clock is available
617
+ pub fn usb_rng ( & self ) -> bool {
618
+ self . usb_rng
619
+ }
620
+
521
621
/// Returns status of HSI48
522
622
pub fn lsi ( & self ) -> bool {
523
623
self . lsi
0 commit comments