Skip to content

Commit 23be76c

Browse files
zklapowtherealprof
authored andcommitted
RCC: Add ability to use HSE clock source (#25)
* allow enabling hse * enable hse pll src correctly * fix build + warning * rusfmt * updated CHANGELOG
1 parent 6f13445 commit 23be76c

File tree

2 files changed

+61
-95
lines changed

2 files changed

+61
-95
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
- Support for STM32F091 - @jessebraham
13+
- Support for HSE as a system clocksource (#25 - breaking change) - @zklapow
1314

1415
## [v0.11.1] - 2019-01-05
1516

src/rcc.rs

Lines changed: 60 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::stm32::rcc::cfgr::SWW;
12
use crate::time::Hertz;
23

34
/// Extension trait that constrains the `RCC` peripheral
@@ -14,8 +15,7 @@ impl RccExt for crate::stm32::RCC {
1415
hclk: None,
1516
pclk: None,
1617
sysclk: None,
17-
enable_hsi: true,
18-
enable_hsi48: false,
18+
clock_src: SysClkSource::HSI,
1919
},
2020
}
2121
}
@@ -26,38 +26,34 @@ pub struct Rcc {
2626
pub cfgr: CFGR,
2727
}
2828

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

3432
#[allow(unused)]
3533
enum SysClkSource {
36-
HSI = 0b00,
37-
HSE = 0b01,
38-
PLL = 0b10,
39-
HSI48 = 0b11,
40-
}
41-
42-
#[allow(unused)]
43-
enum PllSource {
44-
HSI_DIV2 = 0b00,
45-
HSI = 0b01,
46-
HSE = 0b10,
47-
HSI48 = 0b11,
34+
HSI,
35+
HSE(u32),
36+
HSI48,
4837
}
4938

5039
#[allow(unused)]
5140
pub struct CFGR {
5241
hclk: Option<u32>,
5342
pclk: Option<u32>,
5443
sysclk: Option<u32>,
55-
enable_hsi: bool,
56-
enable_hsi48: bool,
44+
clock_src: SysClkSource,
5745
}
5846

5947
#[cfg(feature = "device-selected")]
6048
impl CFGR {
49+
pub fn hse<F>(mut self, freq: F) -> Self
50+
where
51+
F: Into<Hertz>,
52+
{
53+
self.clock_src = SysClkSource::HSE(freq.into().0);
54+
self
55+
}
56+
6157
pub fn hclk<F>(mut self, freq: F) -> Self
6258
where
6359
F: Into<Hertz>,
@@ -82,35 +78,21 @@ impl CFGR {
8278
self
8379
}
8480

85-
pub fn enable_hsi(mut self, is_enabled: bool) -> Self {
86-
self.enable_hsi = is_enabled;
87-
self
88-
}
89-
90-
#[cfg(any(feature = "stm32f042", feature = "stm32f091"))]
91-
pub fn enable_hsi48(mut self, is_enabled: bool) -> Self {
92-
self.enable_hsi48 = is_enabled;
93-
self
94-
}
95-
9681
pub fn freeze(self) -> Clocks {
9782
// Default to lowest frequency clock on all systems.
9883
let sysclk = self.sysclk.unwrap_or(HSI);
9984

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

10488
// Select clock source based on user input and capability
10589
// Highest selected frequency source available takes precedent.
10690
// For F04x, F07x, F09x parts, use HSI48 if requested.
107-
if self.enable_hsi48 {
108-
src_clk_freq = HSI48; // Use HSI48 if requested and available.
109-
} else if self.enable_hsi {
110-
src_clk_freq = HSI; // HSI if requested
111-
} else {
112-
src_clk_freq = HSI; // If no clock source is selected use HSI.
113-
}
91+
let src_clk_freq = match self.clock_src {
92+
SysClkSource::HSE(freq) => freq,
93+
SysClkSource::HSI48 => HSI48,
94+
_ => HSI,
95+
};
11496

11597
// Pll check
11698
if sysclk == src_clk_freq {
@@ -165,6 +147,8 @@ impl CFGR {
165147
let ppre: u8 = 1 << (ppre_bits - 0b011);
166148
let pclk = hclk / cast::u32(ppre);
167149

150+
let rcc = unsafe { &*crate::stm32::RCC::ptr() };
151+
168152
// adjust flash wait states
169153
unsafe {
170154
let flash = &*crate::stm32::FLASH::ptr();
@@ -179,81 +163,62 @@ impl CFGR {
179163
})
180164
}
181165

166+
// Enable the requested clock
167+
match self.clock_src {
168+
SysClkSource::HSE(_) => {
169+
rcc.cr
170+
.modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed());
171+
172+
while !rcc.cr.read().hserdy().bit_is_set() {}
173+
}
174+
SysClkSource::HSI48 => {
175+
rcc.cr2.modify(|_, w| w.hsi48on().set_bit());
176+
while rcc.cr2.read().hsi48rdy().bit_is_clear() {}
177+
}
178+
SysClkSource::HSI => {
179+
rcc.cr.write(|w| w.hsion().set_bit());
180+
while rcc.cr.read().hsirdy().bit_is_clear() {}
181+
}
182+
};
183+
182184
let rcc = unsafe { &*crate::stm32::RCC::ptr() };
183185

184186
// Set up rcc based on above calculated configuration.
185187

186-
// Enable requested clock sources
187-
// HSI
188-
if self.enable_hsi {
189-
rcc.cr.write(|w| w.hsion().set_bit());
190-
while rcc.cr.read().hsirdy().bit_is_clear() {}
191-
}
192-
// HSI48
193-
if self.enable_hsi48 {
194-
rcc.cr2.modify(|_, w| w.hsi48on().set_bit());
195-
while rcc.cr2.read().hsi48rdy().bit_is_clear() {}
196-
}
197-
198188
// Enable PLL
199189
if let Some(pllmul_bits) = pllmul_bits {
200-
rcc.cfgr.write(|w| unsafe { w.pllmul().bits(pllmul_bits) });
201-
202-
// Set PLL source based on configuration.
203-
if self.enable_hsi48 {
204-
rcc.cfgr
205-
.modify(|_, w| w.pllsrc().bits(PllSource::HSI48 as u8));
206-
} else if self.enable_hsi {
207-
rcc.cfgr
208-
.modify(|_, w| w.pllsrc().bits(PllSource::HSI_DIV2 as u8));
209-
} else {
210-
rcc.cfgr
211-
.modify(|_, w| w.pllsrc().bits(PllSource::HSI_DIV2 as u8));
212-
}
190+
let pllsrc_bit: u8 = match self.clock_src {
191+
SysClkSource::HSI => 0b00,
192+
SysClkSource::HSI48 => 0b11,
193+
SysClkSource::HSE(_) => 0b01,
194+
};
195+
196+
// Set PLL source and multiplier
197+
rcc.cfgr
198+
.write(|w| unsafe { w.pllsrc().bits(pllsrc_bit).pllmul().bits(pllmul_bits) });
213199

214200
rcc.cr.write(|w| w.pllon().set_bit());
215201
while rcc.cr.read().pllrdy().bit_is_clear() {}
216202

217203
rcc.cfgr.modify(|_, w| unsafe {
204+
w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll()
205+
});
206+
} else {
207+
let sw_var = match self.clock_src {
208+
SysClkSource::HSI => SWW::HSI,
209+
SysClkSource::HSI48 => SWW::HSI48,
210+
SysClkSource::HSE(_) => SWW::HSE,
211+
};
212+
213+
// use HSI as source
214+
rcc.cfgr.write(|w| unsafe {
218215
w.ppre()
219216
.bits(ppre_bits)
220217
.hpre()
221218
.bits(hpre_bits)
222219
.sw()
223-
.bits(SysClkSource::PLL as u8)
220+
.variant(sw_var)
224221
});
225-
} else {
226-
// No PLL required.
227-
// Setup requested clocks.
228-
if self.enable_hsi48 {
229-
rcc.cfgr.modify(|_, w| unsafe {
230-
w.ppre()
231-
.bits(ppre_bits)
232-
.hpre()
233-
.bits(hpre_bits)
234-
.sw()
235-
.bits(SysClkSource::HSI48 as u8)
236-
});
237-
} else if self.enable_hsi {
238-
rcc.cfgr.modify(|_, w| unsafe {
239-
w.ppre()
240-
.bits(ppre_bits)
241-
.hpre()
242-
.bits(hpre_bits)
243-
.sw()
244-
.bits(SysClkSource::HSI as u8)
245-
});
246-
} else {
247-
// Default to HSI
248-
rcc.cfgr.modify(|_, w| unsafe {
249-
w.ppre()
250-
.bits(ppre_bits)
251-
.hpre()
252-
.bits(hpre_bits)
253-
.sw()
254-
.bits(SysClkSource::HSI as u8)
255-
});
256-
}
257222
}
258223

259224
Clocks {

0 commit comments

Comments
 (0)