Skip to content

Commit 1e391da

Browse files
committed
Improve configuration of 48 MHz clock.
1 parent 4035c7c commit 1e391da

File tree

2 files changed

+99
-25
lines changed

2 files changed

+99
-25
lines changed

examples/rng.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::hal::prelude::*;
1212
use crate::hal::serial::{Config, Serial};
1313
use crate::hal::stm32;
1414
use hal::hal::blocking::rng::Read;
15+
use hal::rcc::Clk48Source;
1516

1617
macro_rules! uprint {
1718
($serial:expr, $($arg:tt)*) => {
@@ -39,7 +40,7 @@ fn main() -> ! {
3940

4041
let clocks = rcc
4142
.cfgr
42-
.hsi48(true) // needed for RNG
43+
.clk48_source(Clk48Source::Hsi48) // needed for RNG
4344
.sysclk(64.MHz())
4445
.pclk1(32.MHz())
4546
.freeze(&mut flash.acr, &mut pwr);

src/rcc.rs

Lines changed: 97 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ impl RccExt for RCC {
8181
hse: None,
8282
lse: None,
8383
msi: None,
84-
hsi48: false,
84+
clk48_source: None,
8585
lsi: false,
8686
hclk: None,
8787
pclk1: None,
@@ -148,11 +148,13 @@ impl CRRCR {
148148
}
149149

150150
/// Checks if the 48 MHz HSI is enabled
151+
#[inline]
151152
pub fn is_hsi48_on(&mut self) -> bool {
152153
self.crrcr().read().hsi48on().bit()
153154
}
154155

155156
/// Checks if the 48 MHz HSI is ready
157+
#[inline]
156158
pub fn is_hsi48_ready(&mut self) -> bool {
157159
self.crrcr().read().hsi48rdy().bit()
158160
}
@@ -347,14 +349,14 @@ pub struct CFGR {
347349
hse: Option<HseConfig>,
348350
lse: Option<LseConfig>,
349351
msi: Option<MsiFreq>,
350-
hsi48: bool,
351352
lsi: bool,
352353
hclk: Option<u32>,
353354
pclk1: Option<u32>,
354355
pclk2: Option<u32>,
355356
sysclk: Option<u32>,
356357
pll_source: Option<PllSource>,
357358
pll_config: Option<PllConfig>,
359+
clk48_source: Option<Clk48Source>,
358360
}
359361

360362
impl CFGR {
@@ -382,12 +384,6 @@ impl CFGR {
382384
self
383385
}
384386

385-
/// Enable the 48 MHz USB, RNG, SDMMC HSI clock source. Not available on all stm32l4x6 series
386-
pub fn hsi48(mut self, on: bool) -> Self {
387-
self.hsi48 = on;
388-
self
389-
}
390-
391387
/// Enables the MSI with the specified speed
392388
pub fn msi(mut self, range: MsiFreq) -> Self {
393389
self.msi = Some(range);
@@ -431,6 +427,11 @@ impl CFGR {
431427
self
432428
}
433429

430+
pub fn clk48_source(mut self, source: Clk48Source) -> Self {
431+
self.clk48_source = Some(source);
432+
self
433+
}
434+
434435
/// Freezes the clock configuration, making it effective
435436
pub fn freeze(&self, acr: &mut ACR, pwr: &mut Pwr) -> Clocks {
436437
let rcc = unsafe { &*RCC::ptr() };
@@ -553,18 +554,40 @@ impl CFGR {
553554
while rcc.cr.read().msirdy().bit_is_clear() {}
554555
}
555556

556-
// Turn on USB, RNG Clock using the HSI48 CLK source
557-
if self.hsi48 {
558-
// p. 180 in ref-manual
559-
rcc.crrcr.modify(|_, w| w.hsi48on().set_bit());
560-
561-
// Wait until HSI48 is running
562-
while rcc.crrcr.read().hsi48rdy().bit_is_clear() {}
563-
}
557+
// Select 48 MHz clock source for SDMMC, USB, RNG, etc.
558+
match self.clk48_source {
559+
None => {
560+
unsafe { rcc.ccipr.modify(|_, w| w.clk48sel().bits(0b00)) };
561+
}
562+
#[cfg(any(
563+
feature = "stm32l476",
564+
feature = "stm32l486",
565+
feature = "stm32l496",
566+
feature = "stm32l4a6"
567+
))]
568+
Some(Clk48Source::Hsi48) => {
569+
// Turn on USB, RNG Clock using the HSI48 CLK source.
570+
571+
// p. 180 in ref-manual
572+
rcc.crrcr.modify(|_, w| w.hsi48on().set_bit());
573+
574+
// Wait until HSI48 is running.
575+
while rcc.crrcr.read().hsi48rdy().bit_is_clear() {}
576+
577+
unsafe { rcc.ccipr.modify(|_, w| w.clk48sel().bits(0b00)) };
578+
}
579+
Some(Clk48Source::PllSai1) => {
580+
unsafe { rcc.ccipr.modify(|_, w| w.clk48sel().bits(0b01)) };
564581

565-
// Select MSI as clock source for usb48, rng ...
566-
if let Some(MsiFreq::RANGE48M) = self.msi {
567-
unsafe { rcc.ccipr.modify(|_, w| w.clk48sel().bits(0b11)) };
582+
unimplemented!()
583+
}
584+
Some(Clk48Source::Pll) => {
585+
unsafe { rcc.ccipr.modify(|_, w| w.clk48sel().bits(0b10)) };
586+
}
587+
Some(Clk48Source::Msi) => {
588+
assert_eq!(Some(MsiFreq::RANGE48M), self.msi);
589+
unsafe { rcc.ccipr.modify(|_, w| w.clk48sel().bits(0b11)) };
590+
}
568591
}
569592

570593
//
@@ -716,14 +739,23 @@ impl CFGR {
716739
})
717740
}
718741

742+
let mut pll48m1clk = None;
743+
719744
let sysclk_src_bits;
720745
let mut msi = self.msi;
721746
if let Some(pllconf) = pllconf {
722747
// Sanity-checks per RM0394, 6.4.4 PLL configuration register (RCC_PLLCFGR)
723748
let r = pllconf.r.to_division_factor();
724749
let clock_speed = clock_speed / (pllconf.m as u32 + 1);
725750
let vco = clock_speed * pllconf.n as u32;
726-
let output_clock = vco / r;
751+
let pllclk = vco / r;
752+
753+
let q = (vco + 48_000_000 - 1) / 48_000_000;
754+
pll48m1clk = Some((vco / q).Hz());
755+
756+
if self.clk48_source == Some(Clk48Source::Pll) {
757+
assert_eq!(q, 48_000_000);
758+
}
727759

728760
assert!(r <= 8); // Allowed max output divider
729761
assert!(pllconf.n >= 8); // Allowed min multiplier
@@ -732,7 +764,7 @@ impl CFGR {
732764
assert!(clock_speed <= 16_000_000); // VCO input clock max
733765
assert!(vco >= 64_000_000); // VCO output min
734766
assert!(vco <= 334_000_000); // VCO output max
735-
assert!(output_clock <= 80_000_000); // Max output clock
767+
assert!(pllclk <= 80_000_000); // Max output clock
736768

737769
// use PLL as source
738770
sysclk_src_bits = 0b11;
@@ -750,6 +782,8 @@ impl CFGR {
750782
.bits(pllconf.r.to_bits())
751783
.plln()
752784
.bits(pllconf.n)
785+
.pllq()
786+
.bits(q as u8)
753787
});
754788

755789
rcc.cr.modify(|_, w| w.pllon().set_bit());
@@ -810,15 +844,16 @@ impl CFGR {
810844
lsi: lsi_used,
811845
lse: self.lse.is_some(),
812846
msi,
813-
hsi48: self.hsi48,
814847
pclk1: pclk1.Hz(),
815848
pclk2: pclk2.Hz(),
816849
ppre1,
817850
ppre2,
851+
pll48m1clk,
818852
sysclk: sysclk.Hz(),
819853
timclk1: timclk1.Hz(),
820854
timclk2: timclk2.Hz(),
821855
pll_source: pllconf.map(|_| pll_source),
856+
clk48_source: self.clk48_source,
822857
}
823858
}
824859
}
@@ -900,24 +935,44 @@ impl PllSource {
900935
}
901936
}
902937

938+
#[derive(Clone, Copy, Debug, PartialEq)]
939+
/// 48 MHz clock source used by USB OTG FS, RNG and SDMMC.
940+
pub enum Clk48Source {
941+
/// HSI48 clock
942+
#[cfg(any(
943+
feature = "stm32l476",
944+
feature = "stm32l486",
945+
feature = "stm32l496",
946+
feature = "stm32l4a6"
947+
))]
948+
Hsi48,
949+
/// PLLSAI1 “Q” clock (PLL48M2CLK)
950+
PllSai1,
951+
/// PLL “Q” clock (PLL48M1CLK)
952+
Pll,
953+
/// MSI clock
954+
Msi,
955+
}
956+
903957
/// Frozen clock frequencies
904958
///
905959
/// The existence of this value indicates that the clock configuration can no longer be changed
906960
#[derive(Clone, Copy, Debug)]
907961
pub struct Clocks {
908962
hclk: Hertz,
909-
hsi48: bool,
910963
msi: Option<MsiFreq>,
911964
lsi: bool,
912965
lse: bool,
913966
pclk1: Hertz,
914967
pclk2: Hertz,
915968
ppre1: u8,
916969
ppre2: u8,
970+
pll48m1clk: Option<Hertz>,
917971
sysclk: Hertz,
918972
timclk1: Hertz,
919973
timclk2: Hertz,
920974
pll_source: Option<PllSource>,
975+
clk48_source: Option<Clk48Source>,
921976
}
922977

923978
impl Clocks {
@@ -928,7 +983,25 @@ impl Clocks {
928983

929984
/// Returns status of HSI48
930985
pub fn hsi48(&self) -> bool {
931-
self.hsi48
986+
#[cfg(any(
987+
feature = "stm32l476",
988+
feature = "stm32l486",
989+
feature = "stm32l496",
990+
feature = "stm32l4a6"
991+
))]
992+
{
993+
self.clk48_source == Some(Clk48Source::Hsi48)
994+
}
995+
996+
#[cfg(not(any(
997+
feature = "stm32l476",
998+
feature = "stm32l486",
999+
feature = "stm32l496",
1000+
feature = "stm32l4a6"
1001+
)))]
1002+
{
1003+
false
1004+
}
9321005
}
9331006

9341007
// Returns the status of the MSI

0 commit comments

Comments
 (0)