-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rcc: Add basic structure of RCC module
- Loading branch information
1 parent
3f5d112
commit 521d77e
Showing
3 changed files
with
186 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,188 @@ | ||
//! Reset and Clock Control | ||
//! | ||
use crate::stm32::RCC; | ||
use crate::time::Hertz; | ||
|
||
#[cfg(feature = "log")] | ||
use log::debug; | ||
|
||
mod core_clocks; | ||
mod reset_reason; | ||
|
||
pub use core_clocks::CoreClocks; | ||
pub use reset_reason::ResetReason; | ||
|
||
/// Configuration of the core clocks | ||
pub struct Config { | ||
hse: Option<u32>, | ||
bypass_hse: bool, | ||
lse: Option<u32>, | ||
sys_ck: Option<u32>, | ||
per_ck: Option<u32>, | ||
audio_ck: Option<u32>, | ||
rcc_hclk: Option<u32>, | ||
rcc_pclk1: Option<u32>, | ||
rcc_pclk2: Option<u32>, | ||
rcc_pclk3: Option<u32>, | ||
#[cfg(feature = "rm0481")] | ||
rcc_pclk4: Option<u32>, | ||
} | ||
|
||
/// Extension trait that constrains the `RCC` peripheral | ||
pub trait RccExt { | ||
/// Constrains the `RCC` peripheral so it plays nicely with the | ||
/// other abstractions | ||
fn constrain(self) -> Rcc; | ||
} | ||
|
||
impl RccExt for RCC { | ||
fn constrain(self) -> Rcc { | ||
Rcc { | ||
config: Config { | ||
hse: None, | ||
bypass_hse: false, | ||
lse: None, | ||
sys_ck: None, | ||
per_ck: None, | ||
audio_ck: None, | ||
rcc_hclk: None, | ||
rcc_pclk1: None, | ||
rcc_pclk2: None, | ||
rcc_pclk3: None, | ||
#[cfg(feature = "rm0481")] | ||
rcc_pclk4: None, | ||
}, | ||
rb: self, | ||
} | ||
} | ||
} | ||
|
||
/// Constrained RCC peripheral | ||
/// | ||
/// Generated by calling `constrain` on the PAC's RCC peripheral. | ||
/// | ||
/// ```rust | ||
/// let dp = stm32::Peripherals::take().unwrap(); | ||
/// let rcc = dp.RCC.constrain(); | ||
/// ``` | ||
pub struct Rcc { | ||
config: Config, | ||
pub(crate) rb: RCC, | ||
} | ||
|
||
impl Rcc { | ||
/// Gets and clears the reason of why the mcu was reset | ||
pub fn get_reset_reason(&mut self) -> ResetReason { | ||
reset_reason::get_reset_reason(&mut self.rb) | ||
} | ||
} | ||
|
||
/// Core Clock Distribution and Reset (CCDR) | ||
/// | ||
/// Generated when the RCC is frozen. The configuration of the Sys_Ck `sys_ck`, | ||
/// AHB clocks `hclk`, APB clocks `pclkN` and PLL outputs `pllN_X_ck` are | ||
/// frozen. However the distribution of some clocks may still be modified and | ||
/// peripherals enabled / reset by passing this object to other implementations | ||
/// in this stack. | ||
pub struct Ccdr { | ||
/// A record of the frozen core clock frequencies | ||
pub clocks: CoreClocks, | ||
} | ||
|
||
const MAX_SYSCLK_FREQ_HZ: u32 = 250_000_000; | ||
|
||
/// Setter defintion for pclk 1 - 4 | ||
macro_rules! pclk_setter { | ||
($($name:ident: $pclk:ident,)+) => { | ||
$( | ||
/// Set the peripheral clock frequency for APB | ||
/// peripherals. | ||
#[must_use] | ||
pub fn $name(mut self, freq: Hertz) -> Self { | ||
assert!(freq.raw() <= MAX_SYSCLK_FREQ_HZ, | ||
"Max frequency is {MAX_SYSCLK_FREQ_HZ}Hz"); | ||
self.config.$pclk = Some(freq.raw()); | ||
self | ||
} | ||
)+ | ||
}; | ||
} | ||
|
||
impl Rcc { | ||
/// Uses HSE (external oscillator) instead of HSI (internal RC | ||
/// oscillator) as the clock source. Will result in a hang if an | ||
/// external oscillator is not connected or it fails to start. | ||
#[must_use] | ||
pub fn use_hse(mut self, freq: Hertz) -> Self { | ||
self.config.hse = Some(freq.raw()); | ||
self | ||
} | ||
|
||
/// Use an external clock signal rather than a crystal oscillator, | ||
/// bypassing the XTAL driver. | ||
#[must_use] | ||
pub fn bypass_hse(mut self) -> Self { | ||
self.config.bypass_hse = true; | ||
self | ||
} | ||
|
||
/// Set SYSCLK frequency | ||
#[must_use] | ||
pub fn sys_ck(mut self, freq: Hertz) -> Self { | ||
assert!( | ||
freq.raw() <= MAX_SYSCLK_FREQ_HZ, | ||
"Max frequency is {MAX_SYSCLK_FREQ_HZ}Hz" | ||
); | ||
self.config.sys_ck = Some(freq.raw()); | ||
self | ||
} | ||
|
||
/// Set SYSCLK frequency - ALIAS | ||
#[must_use] | ||
pub fn sysclk(self, freq: Hertz) -> Self { | ||
self.sys_ck(freq) | ||
} | ||
|
||
/// Set peripheral clock frequency | ||
#[must_use] | ||
pub fn per_ck(mut self, freq: Hertz) -> Self { | ||
self.config.per_ck = Some(freq.raw()); | ||
self | ||
} | ||
|
||
/// Set low speed external clock frequency | ||
pub fn lse_ck(mut self, freq: Hertz) -> Self { | ||
self.config.lse = Some(freq.raw()); | ||
self | ||
} | ||
|
||
/// Set external AUDIOCLK frequency | ||
#[must_use] | ||
pub fn audio_ck(mut self, freq: Hertz) -> Self { | ||
self.config.audio_ck = Some(freq.raw()); | ||
self | ||
} | ||
|
||
/// Set the peripheral clock frequency for AHB peripherals. | ||
#[must_use] | ||
pub fn hclk(mut self, freq: Hertz) -> Self { | ||
assert!( | ||
freq.raw() <= MAX_SYSCLK_FREQ_HZ, | ||
"Max frequency is {MAX_SYSCLK_FREQ_HZ}Hz" | ||
); | ||
self.config.rcc_hclk = Some(freq.raw()); | ||
self | ||
} | ||
|
||
pclk_setter! { | ||
pclk1: rcc_pclk1, | ||
pclk2: rcc_pclk2, | ||
pclk3: rcc_pclk3, | ||
} | ||
|
||
#[cfg(feature = "rm0481")] | ||
pclk_setter! { | ||
pclk4: rcc_pclk4, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters