Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for HSE bypass and CSS #156

Merged
merged 3 commits into from
Oct 29, 2020
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 42 additions & 15 deletions src/rcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,7 @@ impl RccExt for RCC {
apb1: APB1 { _0: () },
apb2: APB2 { _0: () },
bdcr: BDCR { _0: () },
cfgr: CFGR {
hse: None,
hclk: None,
pclk1: None,
pclk2: None,
sysclk: None,
},
cfgr: CFGR::default(),
}
}
}
Expand Down Expand Up @@ -87,7 +81,7 @@ impl AHB {
/// ```
/// let dp = pac::Peripherals::take().unwrap();
/// let rcc = dp.RCC.constrain();
/// use_ahb(&mut rcc.apb1)
/// use_apb1(&mut rcc.apb1)
/// ```
pub struct APB1 {
_0: (),
Expand All @@ -112,7 +106,7 @@ impl APB1 {
/// ```
/// let dp = pac::Peripherals::take().unwrap();
/// let rcc = dp.RCC.constrain();
/// use_ahb(&mut rcc.apb2)
/// use_apb2(&mut rcc.apb2)
/// ```
pub struct APB2 {
_0: (),
Expand Down Expand Up @@ -212,10 +206,13 @@ impl BDCR {
/// ```
/// let dp = pac::Peripherals::take().unwrap();
/// let rcc = dp.RCC.constrain();
/// use_ahb(&mut rcc.cfgr)
/// use_cfgr(&mut rcc.cfgr)
/// ```
#[derive(Default)]
pub struct CFGR {
hse: Option<u32>,
hse_bypass: bool,
css: bool,
hclk: Option<u32>,
pclk1: Option<u32>,
pclk2: Option<u32>,
Expand Down Expand Up @@ -286,13 +283,34 @@ fn into_pre_div(div: u8) -> cfgr2::PREDIV_A {
}

impl CFGR {
/// Uses HSE (external oscillator) instead of HSI (internal RC oscillator) as the clock source.
/// Enable HSE (external clock) in crystal mode.
/// Uses 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.
pub fn use_hse<F>(mut self, freq: F) -> Self
where
F: Into<Hertz>,
{
self.hse = Some(freq.into().0);
self.hse_bypass = false;
self
}

/// Enable HSE (external clock) in bypass mode.
/// Uses user provided clock instead of HSI (internal RC oscillator) as the clock source.
/// Will result in a hang if an external clock source is not connected.
pub fn use_hse_bypass<F>(mut self, freq: F) -> Self
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make it more clear, what the purpose of the bypass mode is?
I had to google to understand, what hse_bypass is for.

HSE crystal oscillator bypassed with external clock

is used for the documentation of the bypass flag.
Maybe:

Suggested change
/// Enable HSE (external clock) in bypass mode.
/// Uses user provided clock instead of HSI (internal RC oscillator) as the clock source.
/// Will result in a hang if an external clock source is not connected.
pub fn use_hse_bypass<F>(mut self, freq: F) -> Self
/// Enable HSE (external clock) in bypass mode.
/// Uses user provided clock instead of a crystal oscillator.
/// Will result in a hang if an external clock source is not connected.
pub fn use_hse_bypass<F>(mut self, freq: F) -> Self

Which makes it more clear, that with bypass mode enabled, the microcontroller won't drive the XTAL pins anymore, as it would do, if an external crystal would be present and (bypass mode inactive).

where
F: Into<Hertz>,
{
self.hse = Some(freq.into().0);
self.hse_bypass = true;
self
}

/// Enable CSS (Clock Security System).
/// No effect if HSE is not enabled.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a note, that a CSS Event can be catched via CSSI (RM0316 9.2.7)?

pub fn enable_css(mut self) -> Self {
self.css = true;
self
}

Expand Down Expand Up @@ -376,10 +394,11 @@ impl CFGR {
}

// PLL_MUL maximal value is 16
assert!(divisor <= 16);
// PRE_DIV maximal value is 16
assert!(multiplier <= 16);

// PRE_DIV maximal value is 16
assert!(divisor <= 16);

(multiplier, Some(divisor))
}
// HSI division is always divided by 2 and has no adjustable division
Expand Down Expand Up @@ -583,9 +602,17 @@ impl CFGR {

let rcc = unsafe { &*RCC::ptr() };

// enable HSE and wait for it to be ready
if self.hse.is_some() {
// enable HSE and wait for it to be ready
rcc.cr.modify(|_, w| w.hseon().on());
rcc.cr.modify(|_, w| {
if self.css {
w.csson().on();
}
if self.hse_bypass {
w.hsebyp().bypassed();
}
w.hseon().on()
});

while rcc.cr.read().hserdy().is_not_ready() {}
}
Expand Down