Skip to content

Commit 57dcc18

Browse files
authored
Merge pull request #43 from Sh3Rm4n/rcc-variant
Add rcc variants
2 parents 030e95a + 39e29be commit 57dcc18

File tree

2 files changed

+110
-85
lines changed

2 files changed

+110
-85
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1717

1818
- Wrong frequency reported by `MonoTimer` ([#56](https://github.com/stm32-rs/stm32f3xx-hal/pull/56))
1919
- Use automatic mode with I2C autoend on `Read` ([#72](https://github.com/stm32-rs/stm32f3xx-hal/pull/72))
20+
- Wrong calculation of HCLK prescaler, if using a prescaler value equal or
21+
higher than 64 ([#42](https://github.com/stm32-rs/stm32f3xx-hal/pull/42))
2022

2123
### Changed
2224

src/rcc.rs

Lines changed: 108 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
33
use core::cmp;
44

5-
use crate::stm32::{rcc, RCC};
6-
use cast::u32;
5+
use crate::stm32::{
6+
rcc::{self, cfgr},
7+
RCC,
8+
};
79

810
use crate::flash::ACR;
911
use crate::time::Hertz;
@@ -99,8 +101,14 @@ const HSI: u32 = 8_000_000; // Hz
99101
// some microcontrollers do not have USB
100102
#[cfg(any(feature = "stm32f301", feature = "stm32f334",))]
101103
mod usb_clocking {
102-
pub fn has_usb() -> bool {
103-
false
104+
use crate::stm32::rcc::cfgr;
105+
106+
pub fn is_valid(
107+
_sysclk: &u32,
108+
_hse: &Option<u32>,
109+
_pll_options: &Option<(cfgr::PLLMUL_A, cfgr::PLLSRC_A)>,
110+
) -> (bool, bool) {
111+
(false, false)
104112
}
105113

106114
pub fn set_usbpre<W>(w: &mut W, _: bool) -> &mut W {
@@ -119,19 +127,29 @@ mod usb_clocking {
119127
feature = "stm32f398",
120128
))]
121129
mod usb_clocking {
122-
use crate::stm32::rcc;
130+
use crate::stm32::rcc::cfgr;
123131

124-
pub fn has_usb() -> bool {
125-
true
132+
pub fn is_valid(
133+
sysclk: &u32,
134+
hse: &Option<u32>,
135+
pll_options: &Option<(cfgr::PLLMUL_A, cfgr::PLLSRC_A)>,
136+
) -> (cfgr::USBPRE_A, bool) {
137+
// the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
138+
// PLL output frequency is a supported one.
139+
// usbpre == false: divide clock by 1.5, otherwise no division
140+
let usb_ok = hse.is_some() && pll_options.is_some();
141+
match (usb_ok, sysclk) {
142+
(true, 72_000_000) => (cfgr::USBPRE_A::DIV1_5, true),
143+
(true, 48_000_000) => (cfgr::USBPRE_A::DIV1, true),
144+
_ => (cfgr::USBPRE_A::DIV1, false),
145+
}
126146
}
127147

128-
pub fn set_usbpre(w: &mut rcc::cfgr::W, bit: bool) -> &mut rcc::cfgr::W {
129-
w.usbpre().bit(bit)
148+
pub fn set_usbpre(w: &mut cfgr::W, usb_prescale: cfgr::USBPRE_A) -> &mut cfgr::W {
149+
w.usbpre().variant(usb_prescale)
130150
}
131151
}
132152

133-
use self::usb_clocking::{has_usb, set_usbpre};
134-
135153
/// Clock configuration
136154
pub struct CFGR {
137155
hse: Option<u32>,
@@ -195,14 +213,14 @@ impl CFGR {
195213
feature = "stm32f303xe",
196214
feature = "stm32f398"
197215
)))]
198-
fn calc_pll(&self) -> (u32, u32, rcc::cfgr::PLLSRC_A) {
216+
fn calc_pll(&self) -> (u32, u32, cfgr::PLLSRC_A) {
199217
let pllsrcclk = self.hse.unwrap_or(HSI / 2);
200218
let pllmul = self.sysclk.unwrap_or(pllsrcclk) / pllsrcclk;
201219

202220
let pllsrc = if self.hse.is_some() {
203-
rcc::cfgr::PLLSRC_A::HSE_DIV_PREDIV
221+
cfgr::PLLSRC_A::HSE_DIV_PREDIV
204222
} else {
205-
rcc::cfgr::PLLSRC_A::HSI_DIV2
223+
cfgr::PLLSRC_A::HSI_DIV2
206224
};
207225
(pllsrcclk, pllmul, pllsrc)
208226
}
@@ -214,92 +232,108 @@ impl CFGR {
214232
feature = "stm32f303xe",
215233
feature = "stm32f398",
216234
))]
217-
fn calc_pll(&self) -> (u32, u32, rcc::cfgr::PLLSRC_A) {
235+
fn calc_pll(&self) -> (u32, u32, cfgr::PLLSRC_A) {
218236
let mut pllsrcclk = self.hse.unwrap_or(HSI / 2);
219237
let mut pllmul = self.sysclk.unwrap_or(pllsrcclk) / pllsrcclk;
220238

221239
let pllsrc = if self.hse.is_some() {
222-
rcc::cfgr::PLLSRC_A::HSE_DIV_PREDIV
240+
cfgr::PLLSRC_A::HSE_DIV_PREDIV
223241
} else if pllmul > 16 {
224242
pllmul /= 2;
225243
pllsrcclk *= 2;
226-
rcc::cfgr::PLLSRC_A::HSI_DIV_PREDIV
244+
cfgr::PLLSRC_A::HSI_DIV_PREDIV
227245
} else {
228-
rcc::cfgr::PLLSRC_A::HSI_DIV2
246+
cfgr::PLLSRC_A::HSI_DIV2
229247
};
230248
(pllsrcclk, pllmul, pllsrc)
231249
}
232250

233251
/// Returns a tuple containing the effective sysclk rate and optional pll settings.
234-
fn calc_sysclk(&self) -> (u32, Option<(u8, rcc::cfgr::PLLSRC_A)>) {
252+
fn calc_sysclk(&self) -> (u32, Option<(cfgr::PLLMUL_A, cfgr::PLLSRC_A)>) {
235253
let (pllsrcclk, pllmul, pllsrc) = self.calc_pll();
236254
if pllmul == 1 {
237255
return (pllsrcclk, None);
238256
}
239257

240258
let pllmul = cmp::min(cmp::max(pllmul, 2), 16);
241-
let sysclk = pllmul * pllsrcclk;
259+
let sysclk = pllsrcclk * pllmul;
242260
assert!(sysclk <= 72_000_000);
243261

244-
let pllmul_bits = pllmul as u8 - 2;
245-
(sysclk, Some((pllmul_bits, pllsrc)))
262+
// NOTE From<u8> for PLLMUL_A is not implemented
263+
let pllmul_mul = match pllmul as u8 {
264+
2 => cfgr::PLLMUL_A::MUL2,
265+
3 => cfgr::PLLMUL_A::MUL3,
266+
4 => cfgr::PLLMUL_A::MUL4,
267+
5 => cfgr::PLLMUL_A::MUL5,
268+
6 => cfgr::PLLMUL_A::MUL6,
269+
7 => cfgr::PLLMUL_A::MUL7,
270+
8 => cfgr::PLLMUL_A::MUL8,
271+
9 => cfgr::PLLMUL_A::MUL9,
272+
10 => cfgr::PLLMUL_A::MUL10,
273+
11 => cfgr::PLLMUL_A::MUL11,
274+
12 => cfgr::PLLMUL_A::MUL12,
275+
13 => cfgr::PLLMUL_A::MUL13,
276+
14 => cfgr::PLLMUL_A::MUL14,
277+
15 => cfgr::PLLMUL_A::MUL15,
278+
16 => cfgr::PLLMUL_A::MUL16,
279+
_ => unreachable!(),
280+
};
281+
(sysclk, Some((pllmul_mul, pllsrc)))
246282
}
247283

248284
/// Freezes the clock configuration, making it effective
249285
pub fn freeze(self, acr: &mut ACR) -> Clocks {
250286
let (sysclk, pll_options) = self.calc_sysclk();
251287

252-
let hpre_bits = self
288+
let (hpre_bits, hpre) = self
253289
.hclk
254290
.map(|hclk| match sysclk / hclk {
255291
0 => unreachable!(),
256-
1 => 0b0111,
257-
2 => 0b1000,
258-
3..=5 => 0b1001,
259-
6..=11 => 0b1010,
260-
12..=39 => 0b1011,
261-
40..=95 => 0b1100,
262-
96..=191 => 0b1101,
263-
192..=383 => 0b1110,
264-
_ => 0b1111,
292+
1 => (cfgr::HPRE_A::DIV1, 1),
293+
2 => (cfgr::HPRE_A::DIV2, 2),
294+
3..=5 => (cfgr::HPRE_A::DIV4, 4),
295+
6..=11 => (cfgr::HPRE_A::DIV8, 8),
296+
12..=39 => (cfgr::HPRE_A::DIV16, 16),
297+
40..=95 => (cfgr::HPRE_A::DIV64, 64),
298+
96..=191 => (cfgr::HPRE_A::DIV128, 128),
299+
192..=383 => (cfgr::HPRE_A::DIV256, 256),
300+
_ => (cfgr::HPRE_A::DIV512, 512),
265301
})
266-
.unwrap_or(0b0111);
302+
.unwrap_or((cfgr::HPRE_A::DIV1, 1));
267303

268-
let hclk = sysclk / (1 << (hpre_bits - 0b0111));
304+
let hclk: u32 = sysclk / hpre;
269305

270306
assert!(hclk <= 72_000_000);
271307

272-
let ppre1_bits = self
308+
let (ppre1_bits, ppre1) = self
273309
.pclk1
274310
.map(|pclk1| match hclk / pclk1 {
275311
0 => unreachable!(),
276-
1 => 0b011,
277-
2 => 0b100,
278-
3..=5 => 0b101,
279-
6..=11 => 0b110,
280-
_ => 0b111,
312+
1 => (cfgr::PPRE1_A::DIV1, 1),
313+
2 => (cfgr::PPRE1_A::DIV2, 2),
314+
3..=5 => (cfgr::PPRE1_A::DIV4, 4),
315+
6..=11 => (cfgr::PPRE1_A::DIV8, 8),
316+
_ => (cfgr::PPRE1_A::DIV16, 16),
281317
})
282-
.unwrap_or(0b011);
318+
.unwrap_or((cfgr::PPRE1_A::DIV1, 1));
283319

284-
let ppre1 = 1 << (ppre1_bits - 0b011);
285-
let pclk1 = hclk / u32(ppre1);
320+
let pclk1 = hclk / u32::from(ppre1);
286321

287322
assert!(pclk1 <= 36_000_000);
288323

289-
let ppre2_bits = self
324+
let (ppre2_bits, ppre2) = self
290325
.pclk2
291326
.map(|pclk2| match hclk / pclk2 {
292327
0 => unreachable!(),
293-
1 => 0b011,
294-
2 => 0b100,
295-
3..=5 => 0b101,
296-
6..=11 => 0b110,
297-
_ => 0b111,
328+
1 => (cfgr::PPRE2_A::DIV1, 1),
329+
2 => (cfgr::PPRE2_A::DIV2, 2),
330+
3..=5 => (cfgr::PPRE2_A::DIV4, 4),
331+
6..=11 => (cfgr::PPRE2_A::DIV8, 8),
332+
_ => (cfgr::PPRE2_A::DIV16, 16),
298333
})
299-
.unwrap_or(0b011);
334+
.unwrap_or((cfgr::PPRE2_A::DIV1, 1));
300335

301-
let ppre2 = 1 << (ppre2_bits - 0b011);
302-
let pclk2 = hclk / u32(ppre2);
336+
let pclk2 = hclk / u32::from(ppre2);
303337

304338
assert!(pclk2 <= 72_000_000);
305339

@@ -316,56 +350,45 @@ impl CFGR {
316350
})
317351
}
318352

319-
// the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
320-
// PLL output frequency is a supported one.
321-
// usbpre == false: divide clock by 1.5, otherwise no division
322-
let usb_ok = has_usb() && self.hse.is_some() && pll_options.is_some();
323-
let (usbpre, usbclk_valid) = match (usb_ok, sysclk) {
324-
(true, 72_000_000) => (false, true),
325-
(true, 48_000_000) => (true, true),
326-
_ => (true, false),
327-
};
353+
let (usbpre, usbclk_valid) = usb_clocking::is_valid(&sysclk, &self.hse, &pll_options);
328354

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

331357
if self.hse.is_some() {
332358
// enable HSE and wait for it to be ready
359+
rcc.cr.modify(|_, w| w.hseon().on());
333360

334-
rcc.cr.modify(|_, w| w.hseon().set_bit());
335-
336-
while rcc.cr.read().hserdy().bit_is_clear() {}
361+
while rcc.cr.read().hserdy().is_not_ready() {}
337362
}
338363

339-
if let Some((pllmul_bits, pllsrc)) = pll_options {
364+
if let Some((pllmul_mul, pllsrc)) = pll_options {
340365
// enable PLL and wait for it to be ready
341366
rcc.cfgr
342-
.modify(|_, w| w.pllmul().bits(pllmul_bits).pllsrc().variant(pllsrc));
367+
.modify(|_, w| w.pllmul().variant(pllmul_mul).pllsrc().variant(pllsrc));
343368

344-
rcc.cr.modify(|_, w| w.pllon().set_bit());
369+
rcc.cr.modify(|_, w| w.pllon().on());
345370

346-
while rcc.cr.read().pllrdy().bit_is_clear() {}
371+
while rcc.cr.read().pllrdy().is_not_ready() {}
347372
}
348373

349374
// set prescalers and clock source
350-
rcc.cfgr.modify(|_, w| unsafe {
351-
set_usbpre(w, usbpre)
352-
.ppre2()
353-
.bits(ppre2_bits)
375+
rcc.cfgr.modify(|_, w| {
376+
usb_clocking::set_usbpre(w, usbpre);
377+
378+
w.ppre2()
379+
.variant(ppre2_bits)
354380
.ppre1()
355-
.bits(ppre1_bits)
381+
.variant(ppre1_bits)
356382
.hpre()
357-
.bits(hpre_bits)
358-
.sw()
359-
.bits(if pll_options.is_some() {
360-
// PLL
361-
0b10
362-
} else if self.hse.is_some() {
363-
// HSE
364-
0b01
365-
} else {
366-
// HSI
367-
0b00
368-
})
383+
.variant(hpre_bits);
384+
385+
if pll_options.is_some() {
386+
w.sw().pll()
387+
} else if self.hse.is_some() {
388+
w.sw().hse()
389+
} else {
390+
w.sw().hsi()
391+
}
369392
});
370393

371394
Clocks {

0 commit comments

Comments
 (0)