diff --git a/CHANGELOG.md b/CHANGELOG.md index e06da2d..028246f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- Support for CRS for devices with USB and HSI48 + +### Changed + +- Revised feature flags for HSI48 clock support + ## [v0.14.0] - 2019-04-25 ### Changed diff --git a/src/rcc.rs b/src/rcc.rs index 52f8468..dbcfddf 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -14,6 +14,18 @@ impl RccExt for RCC { pclk: None, sysclk: None, clock_src: SysClkSource::HSI, + /// CRS is only available on devices with USB and HSI48 + #[cfg(any( + feature = "stm32f031", // TODO: May be an SVD bug + feature = "stm32f038", // TODO: May be an SVD bug + feature = "stm32f042", + feature = "stm32f048", + feature = "stm32f051", // TODO: May be an SVD bug + feature = "stm32f058", // TODO: May be an SVD bug + feature = "stm32f072", + feature = "stm32f078", + ))] + crs: None, rcc: self, } } @@ -25,16 +37,12 @@ pub struct Rcc { pub(crate) regs: RCC, } -#[cfg(any(feature = "stm32f030", - feature = "stm32f070", +#[cfg(any( + feature = "stm32f030", + feature = "stm32f070", ))] mod inner { - use crate::stm32::{ - RCC, - rcc::{ - cfgr::SWW - } - }; + use crate::stm32::{rcc::cfgr::SWW, RCC}; pub(super) const HSI: u32 = 8_000_000; // Hz @@ -56,7 +64,8 @@ mod inner { // Enable the requested clock match c_src { SysClkSource::HSE(_) => { - rcc.cr.modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed()); + rcc.cr + .modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed()); while !rcc.cr.read().hserdy().bit_is_set() {} } @@ -67,21 +76,27 @@ mod inner { } } - pub(super) fn enable_pll(rcc: &mut RCC, c_src: &SysClkSource, pllmul_bits: u8, ppre_bits: u8, hpre_bits: u8) { + pub(super) fn enable_pll( + rcc: &mut RCC, + c_src: &SysClkSource, + pllmul_bits: u8, + ppre_bits: u8, + hpre_bits: u8, + ) { let pllsrc_bit: bool = match c_src { SysClkSource::HSI => false, SysClkSource::HSE(_) => true, }; // Set PLL source and multiplier - rcc.cfgr.modify(|_, w| unsafe { w.pllsrc().bit(pllsrc_bit).pllmul().bits(pllmul_bits) }); + rcc.cfgr + .modify(|_, w| unsafe { w.pllsrc().bit(pllsrc_bit).pllmul().bits(pllmul_bits) }); rcc.cr.write(|w| w.pllon().set_bit()); while rcc.cr.read().pllrdy().bit_is_clear() {} - rcc.cfgr.modify(|_, w| unsafe { - w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() - }); + rcc.cfgr + .modify(|_, w| unsafe { w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() }); } pub(super) fn get_sww(c_src: &SysClkSource) -> SWW { @@ -92,25 +107,21 @@ mod inner { } } -#[cfg(any(feature = "stm32f031", // TODO: May be an SVD bug - feature = "stm32f038", - feature = "stm32f042", - feature = "stm32f048", - feature = "stm32f051", - feature = "stm32f058", - feature = "stm32f071", - feature = "stm32f072", - feature = "stm32f078", - feature = "stm32f091", - feature = "stm32f098", +#[cfg(any( + feature = "stm32f031", // TODO: May be an SVD bug + feature = "stm32f038", // TODO: May be an SVD bug + feature = "stm32f042", + feature = "stm32f048", + feature = "stm32f051", // TODO: May be an SVD bug + feature = "stm32f058", // TODO: May be an SVD bug + feature = "stm32f071", + feature = "stm32f072", + feature = "stm32f078", + feature = "stm32f091", + feature = "stm32f098", ))] mod inner { - use crate::stm32::{ - RCC, - rcc::{ - cfgr::SWW - } - }; + use crate::stm32::{rcc::cfgr::SWW, RCC}; pub(super) const HSI: u32 = 8_000_000; // Hz pub(super) const HSI48: u32 = 48_000_000; // Hz @@ -135,7 +146,8 @@ mod inner { // Enable the requested clock match c_src { SysClkSource::HSE(_) => { - rcc.cr.modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed()); + rcc.cr + .modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed()); while !rcc.cr.read().hserdy().bit_is_set() {} } @@ -150,7 +162,13 @@ mod inner { } } - pub(super) fn enable_pll(rcc: &mut RCC, c_src: &SysClkSource, pllmul_bits: u8, ppre_bits: u8, hpre_bits: u8) { + pub(super) fn enable_pll( + rcc: &mut RCC, + c_src: &SysClkSource, + pllmul_bits: u8, + ppre_bits: u8, + hpre_bits: u8, + ) { let pllsrc_bit: u8 = match c_src { SysClkSource::HSI => 0b00, SysClkSource::HSI48 => 0b11, @@ -158,14 +176,14 @@ mod inner { }; // Set PLL source and multiplier - rcc.cfgr.modify(|_, w| unsafe { w.pllsrc().bits(pllsrc_bit).pllmul().bits(pllmul_bits) }); + rcc.cfgr + .modify(|_, w| unsafe { w.pllsrc().bits(pllsrc_bit).pllmul().bits(pllmul_bits) }); rcc.cr.write(|w| w.pllon().set_bit()); while rcc.cr.read().pllrdy().bit_is_clear() {} - rcc.cfgr.modify(|_, w| unsafe { - w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() - }); + rcc.cfgr + .modify(|_, w| unsafe { w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() }); } pub(super) fn get_sww(c_src: &SysClkSource) -> SWW { @@ -184,6 +202,18 @@ pub struct CFGR { pclk: Option, sysclk: Option, clock_src: SysClkSource, + /// CRS is only available on devices with USB and HSI48 + #[cfg(any( + feature = "stm32f031", // TODO: May be an SVD bug + feature = "stm32f038", // TODO: May be an SVD bug + feature = "stm32f042", + feature = "stm32f048", + feature = "stm32f051", // TODO: May be an SVD bug + feature = "stm32f058", // TODO: May be an SVD bug + feature = "stm32f072", + feature = "stm32f078", + ))] + crs: Option, rcc: RCC, } @@ -196,17 +226,14 @@ impl CFGR { self } - #[cfg(any(feature = "stm32f031", // TODO: May be an SVD bug - feature = "stm32f038", - feature = "stm32f042", - feature = "stm32f048", - feature = "stm32f051", - feature = "stm32f058", - feature = "stm32f071", - feature = "stm32f072", - feature = "stm32f078", - feature = "stm32f091", - feature = "stm32f098", + #[cfg(any( + feature = "stm32f042", + feature = "stm32f048", + feature = "stm32f071", + feature = "stm32f072", + feature = "stm32f078", + feature = "stm32f091", + feature = "stm32f098", ))] pub fn hsi48(mut self) -> Self { self.clock_src = SysClkSource::HSI48; @@ -237,6 +264,17 @@ impl CFGR { self } + #[cfg(any( + feature = "stm32f042", + feature = "stm32f048", + feature = "stm32f072", + feature = "stm32f078", + ))] + pub fn enable_crs(mut self, crs: crate::stm32::CRS) -> Self { + self.crs = Some(crs); + self + } + pub fn freeze(mut self, flash: &mut crate::stm32::FLASH) -> Rcc { // Default to lowest frequency clock on all systems. let sysclk = self.sysclk.unwrap_or(self::inner::HSI); @@ -322,10 +360,36 @@ impl CFGR { // Enable PLL if let Some(pllmul_bits) = pllmul_bits { - self::inner::enable_pll(&mut self.rcc, &self.clock_src, pllmul_bits, ppre_bits, hpre_bits); + self::inner::enable_pll( + &mut self.rcc, + &self.clock_src, + pllmul_bits, + ppre_bits, + hpre_bits, + ); } else { let sw_var = self::inner::get_sww(&self.clock_src); + // CRS is only available on devices with USB and HSI48 + #[cfg(any( + feature = "stm32f042", + feature = "stm32f048", + feature = "stm32f072", + feature = "stm32f078", + ))] + match self.crs { + Some(crs) => { + self.rcc.apb1enr.modify(|_, w| w.crsen().set_bit()); + + // Initialize clock recovery + // Set autotrim enabled. + crs.cr.modify(|_, w| w.autotrimen().set_bit()); + // Enable CR + crs.cr.modify(|_, w| w.cen().set_bit()); + } + _ => {} + } + // use HSI as source self.rcc.cfgr.write(|w| unsafe { w.ppre()