Skip to content

Stm32f04x additions for RCC #17

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

Merged
merged 21 commits into from
Dec 30, 2018
Merged
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4b39458
Some new logic to select clock source, should work on stm32f04x,stm32…
bentwire Dec 11, 2018
44076c1
Started adding some features for other clock sources.
bentwire Dec 18, 2018
88f4fe1
Merge remote-tracking branch 'upstream/master' into stm32f04x_additions
bentwire Dec 19, 2018
ad42305
Merge remote-tracking branch 'upstream/master' into stm32f04x_additions
bentwire Dec 19, 2018
8bdfb37
Merge branch 'master' of github.com:stm32-rs/stm32f0xx-hal into stm32…
bentwire Dec 22, 2018
b6fe609
Fix error, missing any()
bentwire Dec 22, 2018
4298ccb
Removed some debugging cruft.
bentwire Dec 22, 2018
a81101f
Ran cargo fmt
bentwire Dec 22, 2018
551f510
Temp disable conditional compilation.
bentwire Dec 22, 2018
09dbbd1
Idea for fixing clock tree selection across devices...
bentwire Dec 23, 2018
a0c1ac6
Merge branch 'master' of github.com:stm32-rs/stm32f0xx-hal into stm32…
bentwire Dec 23, 2018
c94376f
Fixed a misplaced,
bentwire Dec 23, 2018
6513e32
Fixed spelling, removed pub from enums.
bentwire Dec 23, 2018
16821f7
Remove references to stm32f072 feature since it does not exist yet
bentwire Dec 23, 2018
b1b26bb
Remove HSI14 related code.
bentwire Dec 23, 2018
0190222
Fixed build.
bentwire Dec 23, 2018
68fb8ba
Get rid of unused enum warnings.
bentwire Dec 23, 2018
8379e3c
Restore clean build with no featurs set.
bentwire Dec 23, 2018
fb152e0
Option<bool> -> bool for enable_ fields.
bentwire Dec 23, 2018
2bcea13
Merge remote-tracking branch 'upstream/master' into stm32f04x_additions
bentwire Dec 30, 2018
c23fb00
Re-add core::cmp...
bentwire Dec 30, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 124 additions & 18 deletions src/rcc.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use core::cmp;
use crate::time::Hertz;

/// Extension trait that constrains the `RCC` peripheral
Expand All @@ -14,6 +15,8 @@ impl RccExt for crate::stm32::RCC {
hclk: None,
pclk: None,
sysclk: None,
enable_hsi: true,
enable_hsi48: false,
},
}
}
Expand All @@ -26,12 +29,32 @@ pub struct Rcc {

#[allow(unused)]
const HSI: u32 = 8_000_000; // Hz
#[allow(unused)]
const HSI48: u32 = 48_000_000; // Hz - (available on STM32F04x, STM32F07x and STM32F09x devices only)

#[allow(unused)]
enum SysClkSource {
HSI = 0b00,
HSE = 0b01,
PLL = 0b10,
HSI48 = 0b11,
}

#[allow(unused)]
enum PllSource {
HSI_DIV2 = 0b00,
HSI = 0b01,
HSE = 0b10,
HSI48 = 0b11,
}

#[allow(unused)]
pub struct CFGR {
hclk: Option<u32>,
pclk: Option<u32>,
sysclk: Option<u32>,
enable_hsi: bool,
enable_hsi48: bool,
}

#[cfg(feature = "device-selected")]
Expand Down Expand Up @@ -60,20 +83,58 @@ impl CFGR {
self
}

pub fn enable_hsi(mut self, is_enabled: bool) -> Self {
self.enable_hsi = is_enabled;
self
}

#[cfg(feature = "stm32f042")]
pub fn enable_hsi48(mut self, is_enabled: bool) -> Self {
self.enable_hsi48 = is_enabled;
self
}

pub fn freeze(self) -> Clocks {
let pllmul = (4 * self.sysclk.unwrap_or(HSI) + HSI) / HSI / 2;
let pllmul = core::cmp::min(core::cmp::max(pllmul, 2), 16);
let sysclk = pllmul * HSI / 2;
// Default to lowest frequency clock on all systems.
let sysclk = self.sysclk.unwrap_or(HSI);

let r_sysclk; // The "real" sysclock value, calculated below
let src_clk_freq; // Frequency of source clock for PLL and etc, HSI, or HSI48 on supported systems.
let pllmul_bits;

let pllmul_bits = if pllmul == 2 {
None
// Select clock source based on user input and capability
// Highest selected frequency source available takes precedent.
// For F04x, F07x, F09x parts, use HSI48 if requested.
if self.enable_hsi48 {
src_clk_freq = HSI48; // Use HSI48 if requested and available.
} else if self.enable_hsi {
src_clk_freq = HSI; // HSI if requested
} else {
Some(pllmul as u8 - 2)
};
src_clk_freq = HSI; // If no clock source is selected use HSI.
}

// Pll check
if sysclk == src_clk_freq {
// Bypass pll if src clk and requested sysclk are the same, to save power.
// The only reason to override this behaviour is if the sysclk source were HSI, and you
// were running the USB off the PLL...
pllmul_bits = None;
r_sysclk = src_clk_freq;
} else {
let pllmul = (4 * self.sysclk.unwrap_or(src_clk_freq) + src_clk_freq) / src_clk_freq / 2;
let pllmul = cmp::min(cmp::max(pllmul, 2), 16);
r_sysclk = pllmul * src_clk_freq / 2;

pllmul_bits = if pllmul == 2 {
None
} else {
Some(pllmul as u8 - 2)
};
}

let hpre_bits = self
.hclk
.map(|hclk| match sysclk / hclk {
.map(|hclk| match r_sysclk / hclk {
0 => unreachable!(),
1 => 0b0111,
2 => 0b1000,
Expand Down Expand Up @@ -119,24 +180,69 @@ impl CFGR {
}

let rcc = unsafe { &*crate::stm32::RCC::ptr() };
if let Some(pllmul_bits) = pllmul_bits {
// use PLL as source

// Set up rcc based on above calculated configuration.

// Enable requested clock sources
// HSI
if self.enable_hsi {
rcc.cr.write(|w| w.hsion().set_bit());
while rcc.cr.read().hsirdy().bit_is_clear() { }
}
// HSI48
if self.enable_hsi48 {
rcc.cr2.modify(|_, w| w.hsi48on().set_bit());
while rcc.cr2.read().hsi48rdy().bit_is_clear() { }
}

// Enable PLL
if let Some(pllmul_bits) = pllmul_bits {
rcc.cfgr.write(|w| unsafe { w.pllmul().bits(pllmul_bits) });

rcc.cr.write(|w| w.pllon().set_bit());
// Set PLL source based on configuration.
if self.enable_hsi48 {
rcc.cfgr.modify(|_, w| w.pllsrc().bits(PllSource::HSI48 as u8));
} else if self.enable_hsi {
rcc.cfgr.modify(|_, w| w.pllsrc().bits(PllSource::HSI_DIV2 as u8));
} else {
rcc.cfgr.modify(|_, w| w.pllsrc().bits(PllSource::HSI_DIV2 as u8));
}

while rcc.cr.read().pllrdy().bit_is_clear() {}
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().bits(2)
w.ppre()
.bits(ppre_bits)
.hpre()
.bits(hpre_bits)
.sw()
.bits(SysClkSource::PLL as u8)
});
} else {
// use HSI as source
rcc.cfgr
.write(|w| unsafe { w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().bits(0) });
}

} else { // No PLL required.
// Setup requested clocks.
if self.enable_hsi48 {
rcc.cfgr.modify(|_, w| unsafe {
w.ppre().bits(ppre_bits)
.hpre().bits(hpre_bits)
.sw().bits(SysClkSource::HSI48 as u8)
});
} else if self.enable_hsi {
rcc.cfgr.modify(|_, w| unsafe {
w.ppre().bits(ppre_bits)
.hpre().bits(hpre_bits)
.sw().bits(SysClkSource::HSI as u8)
});
} else { // Default to HSI
rcc.cfgr.modify(|_, w| unsafe {
w.ppre().bits(ppre_bits)
.hpre().bits(hpre_bits)
.sw().bits(SysClkSource::HSI as u8)
});
}
}

Clocks {
hclk: Hertz(hclk),
pclk: Hertz(pclk),
Expand Down