@@ -39,11 +39,15 @@ impl RccExt for RCC {
39
39
lse : None ,
40
40
lsi : None ,
41
41
use_pll : false ,
42
- use_pll48clk : false ,
42
+ pll48clk : None ,
43
43
pllm : 2 ,
44
44
plln : 50 ,
45
45
pllp : PLLP :: Div2 ,
46
46
pllq : 2 ,
47
+ use_pllsai : false ,
48
+ pllsain : 192 ,
49
+ pllsaip : PLLSAIP :: Div2 ,
50
+ pllsaiq : 2 ,
47
51
use_plli2s : false ,
48
52
plli2sr : 2 ,
49
53
plli2sq : 2 ,
@@ -223,6 +227,24 @@ pub enum MCOPRE {
223
227
Div5 ,
224
228
}
225
229
230
+ /// PLL48CLK clock source selection
231
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
232
+ pub enum PLL48CLK {
233
+ /// 48 MHz clock from PLLQ is selected
234
+ Pllq ,
235
+ /// 48 MHz clock from PLLSAI is selected
236
+ Pllsai ,
237
+ }
238
+
239
+ /// PLLSAIP division factors.
240
+ #[ derive( Clone , Copy , Debug , PartialEq , Eq ) ]
241
+ pub enum PLLSAIP {
242
+ Div2 = 0b00 ,
243
+ Div4 = 0b01 ,
244
+ Div6 = 0b10 ,
245
+ Div8 = 0b11 ,
246
+ }
247
+
226
248
/// Microcontroller clock output 1
227
249
///
228
250
/// Value on reset: HSI
@@ -293,11 +315,15 @@ pub struct CFGR {
293
315
lse : Option < LSEClock > ,
294
316
lsi : Option < Hertz > ,
295
317
use_pll : bool ,
296
- use_pll48clk : bool ,
318
+ pll48clk : Option < PLL48CLK > ,
297
319
pllm : u8 ,
298
320
plln : u16 ,
299
321
pllp : PLLP ,
300
322
pllq : u8 ,
323
+ use_pllsai : bool ,
324
+ pllsain : u16 ,
325
+ pllsaip : PLLSAIP ,
326
+ pllsaiq : u8 ,
301
327
use_plli2s : bool ,
302
328
plli2sr : u8 ,
303
329
plli2sq : u8 ,
@@ -413,9 +439,9 @@ impl CFGR {
413
439
self
414
440
}
415
441
416
- /// Sets the 48 MHz clock source to the main PLL .
417
- pub fn use_pll48clk ( mut self ) -> Self {
418
- self . use_pll48clk = true ;
442
+ /// Sets the 48 MHz clock source.
443
+ pub fn use_pll48clk ( mut self , pll48clk : PLL48CLK ) -> Self {
444
+ self . pll48clk = Some ( pll48clk ) ;
419
445
self
420
446
}
421
447
@@ -434,7 +460,7 @@ impl CFGR {
434
460
///
435
461
/// # Panics
436
462
///
437
- /// Panics if the multiplication factor isn't between 50 and 432.
463
+ /// Panics if the multiplication factor isn't between 50 and 432 (inclusive) .
438
464
pub fn plln ( mut self , plln : u16 ) -> Self {
439
465
assert ! ( ( 50 ..=432 ) . contains( & plln) ) ;
440
466
self . plln = plln;
@@ -450,14 +476,48 @@ impl CFGR {
450
476
/// Sets the PLL division factor for the 48 MHz clock.
451
477
/// # Panics
452
478
///
453
- /// Panics if the division factor isn't between 2 and 15.
479
+ /// Panics if the division factor isn't between 2 and 15 (inclusive) .
454
480
pub fn pllq ( mut self , pllq : u8 ) -> Self {
455
481
assert ! ( ( 2 ..=15 ) . contains( & pllq) ) ;
456
482
self . pllq = pllq;
457
483
self
458
484
}
459
485
460
- /// Enables the Plli2S clock source.
486
+ /// Enables the PLLSAI clock source.
487
+ pub fn use_pllsai ( mut self ) -> Self {
488
+ self . use_pllsai = true ;
489
+ self
490
+ }
491
+
492
+ /// Sets the PLLSAIN multiplication factor for PLLSAI.
493
+ ///
494
+ /// # Panics
495
+ ///
496
+ /// Panics if the multiplication factor isn't between 50 and 432.
497
+ pub fn pllsain ( mut self , pllsain : u16 ) -> Self {
498
+ assert ! ( ( 50 ..=432 ) . contains( & pllsain) ) ;
499
+ self . pllsain = pllsain;
500
+ self
501
+ }
502
+
503
+ /// Sets the PLLSAIP division factor for PLLSAI.
504
+ pub fn pllsaip ( mut self , pllsaip : PLLSAIP ) -> Self {
505
+ self . pllsaip = pllsaip;
506
+ self
507
+ }
508
+
509
+ /// Sets the PLLSAIQ division factor for PLLSAIS.
510
+ ///
511
+ /// # Panics
512
+ ///
513
+ /// Panics if the division factor isn't between 2 and 15.
514
+ pub fn pllsaiq ( mut self , pllsaiq : u8 ) -> Self {
515
+ assert ! ( ( 2 ..=15 ) . contains( & pllsaiq) ) ;
516
+ self . pllsaiq = pllsaiq;
517
+ self
518
+ }
519
+
520
+ /// Enables the PLLI2S clock source.
461
521
pub fn use_plli2s ( mut self ) -> Self {
462
522
self . use_plli2s = true ;
463
523
self
@@ -547,13 +607,37 @@ impl CFGR {
547
607
} ;
548
608
}
549
609
550
- if self . use_pll48clk {
551
- pll48clk_valid = {
552
- let pll48clk =
553
- base_clk as u64 * self . plln as u64 / self . pllm as u64 / self . pllq as u64 ;
554
- ( 48_000_000 - 120_000 ..=48_000_000 + 120_000 ) . contains ( & pll48clk)
555
- } ;
610
+ // Check if pll48clk is valid
611
+ if let Some ( pll48clk) = self . pll48clk {
612
+ match pll48clk {
613
+ PLL48CLK :: Pllq => {
614
+ pll48clk_valid = {
615
+ let pll48clk = base_clk as u64 * self . plln as u64
616
+ / self . pllm as u64
617
+ / self . pllq as u64 ;
618
+ ( 48_000_000 - 120_000 ..=48_000_000 + 120_000 ) . contains ( & pll48clk)
619
+ }
620
+ }
621
+ PLL48CLK :: Pllsai => {
622
+ pll48clk_valid = {
623
+ if self . use_pllsai {
624
+ let pll48clk = base_clk as u64 * self . pllsain as u64
625
+ / self . pllm as u64
626
+ / match self . pllsaip {
627
+ PLLSAIP :: Div2 => 2 ,
628
+ PLLSAIP :: Div4 => 4 ,
629
+ PLLSAIP :: Div6 => 6 ,
630
+ PLLSAIP :: Div8 => 8 ,
631
+ } ;
632
+ ( 48_000_000 - 120_000 ..=48_000_000 + 120_000 ) . contains ( & pll48clk)
633
+ } else {
634
+ false
635
+ }
636
+ }
637
+ }
638
+ }
556
639
}
640
+
557
641
// SYSCLK, must be <= 216 Mhz. By default, HSI/HSE frequency is chosen
558
642
assert ! ( sysclk <= 216_000_000 ) ;
559
643
let sysclk = sysclk as u32 ;
@@ -809,7 +893,7 @@ impl CFGR {
809
893
Some ( ( sysclk - 1 , sysclk + 1 ) )
810
894
} ;
811
895
812
- let q = if self . use_pll48clk {
896
+ let q = if let Some ( PLL48CLK :: Pllq ) = self . pll48clk {
813
897
Some ( ( 48_000_000 - 120_000 , 48_000_000 + 120_000 ) )
814
898
} else {
815
899
None
@@ -903,7 +987,7 @@ impl CFGR {
903
987
}
904
988
905
989
// Enable sequence follows by RM 4.1.4 Entering Overdrive mode.
906
- if self . use_pll || self . use_pll48clk {
990
+ if self . use_pll || self . pll48clk . is_some ( ) {
907
991
// Disable PLL
908
992
// Since the main-PLL configuration parameters cannot be changed once PLL is enabled, it is
909
993
// recommended to configure PLL before enabling it (selection of the HSI or HSE oscillator as
@@ -967,9 +1051,39 @@ impl CFGR {
967
1051
while rcc. csr . read ( ) . lsirdy ( ) . is_not_ready ( ) { }
968
1052
}
969
1053
970
- if self . use_pll48clk {
971
- // set source clock for 48 MHz to main PLL
972
- rcc. dckcfgr2 . modify ( |_, w| w. ck48msel ( ) . bit ( false ) ) ;
1054
+ if self . use_pllsai {
1055
+ let pllsain_freq = match self . hse . as_ref ( ) {
1056
+ Some ( hse) => hse. freq . integer ( ) as u64 / self . pllm as u64 * self . pllsain as u64 ,
1057
+ None => 16_000_000 / self . pllm as u64 * self . pllsain as u64 ,
1058
+ } ;
1059
+ let pllsaip_freq = pllsain_freq
1060
+ / match self . pllsaip {
1061
+ PLLSAIP :: Div2 => 2 ,
1062
+ PLLSAIP :: Div4 => 4 ,
1063
+ PLLSAIP :: Div6 => 6 ,
1064
+ PLLSAIP :: Div8 => 8 ,
1065
+ } ;
1066
+ // let pllsaiq_freq = pllsain_freq / self.pllsaiq as u64;
1067
+
1068
+ // The reference manual (RM0410 Rev 4, Page 212), says the following
1069
+ // "Caution: The software has to set these bits correctly to ensure that the VCO output frequency is between 100 and 432 MHz.",
1070
+ // but STM32CubeMX states 192 MHz as the minimum. SSo the stricter requirement was chosen.
1071
+ assert ! ( ( 192_000_000 ..=432_000_000 ) . contains( & pllsain_freq) ) ;
1072
+ assert ! ( pllsaip_freq <= 48_000_000 ) ;
1073
+
1074
+ rcc. pllsaicfgr . modify ( |_, w| unsafe {
1075
+ w. pllsain ( ) . bits ( self . pllsain ) ;
1076
+ w. pllsaip ( ) . bits ( self . pllsaip as u8 ) ;
1077
+ w. pllsaiq ( ) . bits ( self . pllsaiq )
1078
+ } ) ;
1079
+ rcc. cr . modify ( |_, w| w. pllsaion ( ) . on ( ) ) ;
1080
+ }
1081
+
1082
+ if let Some ( pll48clk) = self . pll48clk {
1083
+ match pll48clk {
1084
+ PLL48CLK :: Pllq => rcc. dckcfgr2 . modify ( |_, w| w. ck48msel ( ) . bit ( false ) ) ,
1085
+ PLL48CLK :: Pllsai => rcc. dckcfgr2 . modify ( |_, w| w. ck48msel ( ) . bit ( true ) ) ,
1086
+ }
973
1087
}
974
1088
975
1089
if self . use_plli2s {
@@ -1365,7 +1479,7 @@ mod tests {
1365
1479
1366
1480
#[ test]
1367
1481
fn test_rcc_calc1 ( ) {
1368
- use super :: { HSEClock , HSEClockMode , MCO1 , MCO2 , MCOPRE , PLLP } ;
1482
+ use super :: { HSEClock , HSEClockMode , MCO1 , MCO2 , MCOPRE , PLL48CLK , PLLP , PLLSAIP } ;
1369
1483
1370
1484
let cfgr = CFGR {
1371
1485
hse : None ,
@@ -1376,11 +1490,15 @@ mod tests {
1376
1490
lse : None ,
1377
1491
lsi : None ,
1378
1492
use_pll : false ,
1379
- use_pll48clk : false ,
1493
+ pll48clk : None ,
1380
1494
pllm : 2 ,
1381
1495
plln : 50 ,
1382
1496
pllp : PLLP :: Div2 ,
1383
1497
pllq : 2 ,
1498
+ use_pllsai : false ,
1499
+ pllsain : 192 ,
1500
+ pllsaip : PLLSAIP :: Div2 ,
1501
+ pllsaiq : 2 ,
1384
1502
use_plli2s : false ,
1385
1503
plli2sr : 2 ,
1386
1504
plli2sq : 2 ,
@@ -1394,7 +1512,7 @@ mod tests {
1394
1512
let mut cfgr = cfgr
1395
1513
. hse ( HSEClock :: new ( 25_000_000 . Hz ( ) , HSEClockMode :: Bypass ) )
1396
1514
. use_pll ( )
1397
- . use_pll48clk ( )
1515
+ . use_pll48clk ( PLL48CLK :: Pllq )
1398
1516
. sysclk ( 216_000_000 . Hz ( ) ) ;
1399
1517
cfgr. pll_configure ( ) ;
1400
1518
@@ -1407,7 +1525,7 @@ mod tests {
1407
1525
1408
1526
#[ test]
1409
1527
fn test_rcc_calc2 ( ) {
1410
- use super :: { HSEClock , HSEClockMode , MCO1 , MCO2 , MCOPRE , PLLP } ;
1528
+ use super :: { HSEClock , HSEClockMode , MCO1 , MCO2 , MCOPRE , PLL48CLK , PLLP , PLLSAIP } ;
1411
1529
1412
1530
let cfgr = CFGR {
1413
1531
hse : None ,
@@ -1418,11 +1536,15 @@ mod tests {
1418
1536
lse : None ,
1419
1537
lsi : None ,
1420
1538
use_pll : false ,
1421
- use_pll48clk : false ,
1539
+ pll48clk : None ,
1422
1540
pllm : 2 ,
1423
1541
plln : 50 ,
1424
1542
pllp : PLLP :: Div2 ,
1425
1543
pllq : 2 ,
1544
+ use_pllsai : false ,
1545
+ pllsain : 192 ,
1546
+ pllsaip : PLLSAIP :: Div2 ,
1547
+ pllsaiq : 2 ,
1426
1548
use_plli2s : false ,
1427
1549
plli2sr : 2 ,
1428
1550
plli2sq : 2 ,
@@ -1435,7 +1557,7 @@ mod tests {
1435
1557
1436
1558
let mut cfgr = cfgr
1437
1559
. hse ( HSEClock :: new ( 25_000_000 . Hz ( ) , HSEClockMode :: Bypass ) )
1438
- . use_pll48clk ( )
1560
+ . use_pll48clk ( PLL48CLK :: Pllq )
1439
1561
. sysclk ( 216_000_000 . Hz ( ) ) ;
1440
1562
cfgr. pll_configure ( ) ;
1441
1563
@@ -1448,7 +1570,7 @@ mod tests {
1448
1570
1449
1571
#[ test]
1450
1572
fn test_rcc_calc3 ( ) {
1451
- use super :: { HSEClock , HSEClockMode , MCO1 , MCO2 , MCOPRE , PLLP } ;
1573
+ use super :: { HSEClock , HSEClockMode , MCO1 , MCO2 , MCOPRE , PLL48CLK , PLLP , PLLSAIP } ;
1452
1574
1453
1575
let cfgr = CFGR {
1454
1576
hse : None ,
@@ -1459,11 +1581,15 @@ mod tests {
1459
1581
lse : None ,
1460
1582
lsi : None ,
1461
1583
use_pll : false ,
1462
- use_pll48clk : false ,
1584
+ pll48clk : None ,
1463
1585
pllm : 2 ,
1464
1586
plln : 50 ,
1465
1587
pllp : PLLP :: Div2 ,
1466
1588
pllq : 2 ,
1589
+ use_pllsai : false ,
1590
+ pllsain : 192 ,
1591
+ pllsaip : PLLSAIP :: Div2 ,
1592
+ pllsaiq : 2 ,
1467
1593
use_plli2s : false ,
1468
1594
plli2sr : 2 ,
1469
1595
plli2sq : 2 ,
@@ -1476,7 +1602,7 @@ mod tests {
1476
1602
1477
1603
let mut cfgr = cfgr
1478
1604
. hse ( HSEClock :: new ( 25_000_000 . Hz ( ) , HSEClockMode :: Bypass ) )
1479
- . use_pll48clk ( )
1605
+ . use_pll48clk ( PLL48CLK :: Pllq )
1480
1606
. set_defaults ( ) ;
1481
1607
cfgr. pll_configure ( ) ;
1482
1608
@@ -1489,7 +1615,7 @@ mod tests {
1489
1615
1490
1616
#[ test]
1491
1617
fn test_rcc_default ( ) {
1492
- use super :: { MCO1 , MCO2 , MCOPRE , PLLP } ;
1618
+ use super :: { MCO1 , MCO2 , MCOPRE , PLLP , PLLSAIP } ;
1493
1619
1494
1620
let mut cfgr = CFGR {
1495
1621
hse : None ,
@@ -1500,11 +1626,15 @@ mod tests {
1500
1626
lse : None ,
1501
1627
lsi : None ,
1502
1628
use_pll : false ,
1503
- use_pll48clk : false ,
1629
+ pll48clk : None ,
1504
1630
pllm : 2 ,
1505
1631
plln : 50 ,
1506
1632
pllp : PLLP :: Div2 ,
1507
1633
pllq : 2 ,
1634
+ use_pllsai : false ,
1635
+ pllsain : 192 ,
1636
+ pllsaip : PLLSAIP :: Div2 ,
1637
+ pllsaiq : 2 ,
1508
1638
use_plli2s : false ,
1509
1639
plli2sr : 2 ,
1510
1640
plli2sq : 2 ,
0 commit comments