Skip to content

Commit 0015970

Browse files
grodinomvertescher
authored andcommitted
Corrected some logic errors
1 parent cdbd481 commit 0015970

File tree

1 file changed

+52
-66
lines changed

1 file changed

+52
-66
lines changed

src/rcc.rs

Lines changed: 52 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use core::cmp::min;
22

3+
use cortex_m_semihosting::hprintln;
4+
use micromath::F32Ext;
5+
36
use crate::device::{rcc, FLASH, RCC};
47
use crate::time::Hertz;
58

@@ -106,15 +109,17 @@ pub struct HSEClock {
106109

107110
impl HSEClock {
108111
/// Provide HSE frequence. Must be between 4 and 26 MHz
109-
pub fn freq<F>(mut self, freq: F) -> Self
112+
pub fn new<F>(freq: F, mode: HSEClockMode) -> Self
110113
where
111114
F: Into<Hertz>,
112115
{
113116
let f: u32 = freq.into().0;
114117

115118
assert!(4_000_000 <= f && f <= 26_000_000);
116-
self.freq = f;
117-
self
119+
HSEClock{
120+
freq: f,
121+
mode: mode
122+
}
118123
}
119124
}
120125

@@ -228,7 +233,6 @@ impl CFGR {
228233
0 => HSI,
229234
_ => hse_freq
230235
};
231-
assert!(sysclk <= base_clk);
232236

233237
if sysclk <= base_clk { // We can use the base clock directly
234238
match &self.hse {
@@ -243,63 +247,40 @@ impl CFGR {
243247
// must be between 2 and 63. In this case, the condition is always
244248
// respected. We set it at 2MHz as recommanded by the user manual.
245249
let pllm = base_clk / 2_000_000;
250+
let pllp_val: u32;
246251
let vco_clkin = base_clk / pllm;
247252

253+
// Sysclk output divisor, must result in >= 24MHz and <= 216MHz
254+
// needs to be the equivalent of 2, 4, 6 or 8
248255
// We can calculate that:
249256
// * PLLP = 2 => SYSCLK \in [25*vco_clkin ; 216*vco_clkin]
250257
// * PLLP = 4 => SYSCLK \in [12,5*vco_clkin ; 108*vco_clkin]
251258
// * PLLP = 6 => SYSCLK \in [8,33*vco_clkin ; 72*vco_clkin ]
252259
// * PLLP = 8 => SYSCLK \in [6,25*vco_clkin ; 54*vco_clkin ]
253-
let (plln, pllp) = if sysclk >= 25*vco_clkin {
254-
// Main scaler, must result in >= 192MHz and <= 432MHz, min 50, max 432
255-
let plln = (sysclk / vco_clkin) * 2;
256-
257-
// Sysclk output divisor, must result in >= 24MHz and <= 216MHz
258-
// needs to be the equivalent of 2, 4, 6 or 8
259-
let pllp = 0b00;
260-
261-
// Update sysclk with the real value
262-
sysclk = (vco_clkin * plln) / 2;
263-
264-
(plln, pllp)
260+
let pllp = if sysclk >= 25*vco_clkin {
261+
pllp_val = 2;
262+
0b00
265263
} else if sysclk >= 13*vco_clkin {
266-
// Main scaler, must result in >= 192MHz and <= 432MHz, min 50, max 432
267-
let plln = (sysclk / vco_clkin) * 4;
268-
269-
// Sysclk output divisor, must result in >= 24MHz and <= 216MHz
270-
// needs to be the equivalent of 2, 4, 6 or 8
271-
let pllp = 0b01;
272-
273-
// Update sysclk with the real value
274-
sysclk = (vco_clkin * plln) / 4;
275-
276-
(plln, pllp)
264+
pllp_val = 4;
265+
0b01
277266
} else if sysclk >= 9*vco_clkin {
278-
// Main scaler, must result in >= 192MHz and <= 432MHz, min 50, max 432
279-
let plln = (sysclk / vco_clkin) * 6;
280-
281-
// Sysclk output divisor, must result in >= 24MHz and <= 216MHz
282-
// needs to be the equivalent of 2, 4, 6 or 8
283-
let pllp = 0b10;
284-
285-
// Update sysclk with the real value
286-
sysclk = (vco_clkin * plln) / 6;
287-
288-
(plln, pllp)
267+
pllp_val = 6;
268+
0b10
289269
} else {
290-
// Main scaler, must result in >= 192MHz and <= 432MHz, min 50, max 432
291-
let plln = (sysclk / vco_clkin) * 8;
292-
293-
// Sysclk output divisor, must result in >= 24MHz and <= 216MHz
294-
// needs to be the equivalent of 2, 4, 6 or 8
295-
let pllp = 0b11;
296-
297-
// Update sysclk with the real value
298-
sysclk = (vco_clkin * plln) / 8;
299-
300-
(plln, pllp)
270+
pllp_val = 8;
271+
0b11
301272
};
302273

274+
// PLLN, main scaler, must result in >= 192MHz and <= 432MHz, min
275+
// 50, max 432, this constraint is allways respected when vco_clkin
276+
// = 2 MHz
277+
let plln = (sysclk / vco_clkin) * pllp_val;
278+
// Check that the desired SYSCLK is physically feasible. /1000 is to
279+
// avoid u32 overflow
280+
assert!((base_clk / 1_000) * plln >= sysclk / 1_000);
281+
// Update sysclk with the real value
282+
sysclk = (vco_clkin * plln) / pllp_val;
283+
303284
match &self.hse {
304285
// If HSE is provided
305286
Some(hse) => {
@@ -332,29 +313,27 @@ impl CFGR {
332313
.plln().bits(plln as u16)
333314
.pllp().bits(pllp)
334315
});
316+
335317
},
336318
};
337319

338320
// Enable PLL
339321
rcc.cr.modify(|_, w| w.pllon().set_bit());
340322
// Wait for PLL to stabilise
341-
while rcc.cr.read().pllrdy().is_not_ready() {}
323+
while rcc.cr.read().pllrdy().bit_is_set() {}
342324

343325
// Use PLL as SYSCLK
326+
// rcc.cfgr.modify(|_, w| unsafe { w.sw().bits(0b10 as u8) });
344327
rcc.cfgr.modify(|_, w| w.sw().pll() );
345328
}
346329

347-
// HCLK. By default, SYSCLK frequence is chosen
348-
let mut hclk: u32 = self.hclk.unwrap_or(sysclk);
349-
assert!(hclk <= sysclk);
350-
// PCLK1 (APB1). Must be <= 54 Mhz. By default, min(hclk, 54Mhz) is
351-
// chosen
352-
let mut pclk1: u32 = self.pclk1.unwrap_or(min(54_000_000, hclk));
353-
// PCLK2 (APB2). Must be <= 108 Mhz. By default, min(hclk, 108Mhz) is
354-
// chosen
355-
let mut pclk2: u32 = self.pclk1.unwrap_or(min(108_000_000, hclk));
330+
// HCLK. By default, SYSCLK frequence is chosen. Because of the method
331+
// of clock multiplication and division, even if `sysclk` is set to be
332+
// the same as `hclk`, it can be slighly inferior to `sysclk` after
333+
// pllm, pllp... calculations
334+
let mut hclk: u32 = min(sysclk, self.hclk.unwrap_or(sysclk));
356335

357-
// Configure HPRE
336+
// Configure HPRE.
358337
let mut hpre_val: u32 = sysclk / hclk;
359338

360339
// The real value of hpre is computed to be as near as possible to the
@@ -374,8 +353,15 @@ impl CFGR {
374353
// update hclk with the real value
375354
hclk = sysclk / hpre_val;
376355

356+
// PCLK1 (APB1). Must be <= 54 Mhz. By default, min(hclk, 54Mhz) is
357+
// chosen
358+
let mut pclk1: u32 = self.pclk1.unwrap_or(min(54_000_000, hclk));
359+
// PCLK2 (APB2). Must be <= 108 Mhz. By default, min(hclk, 108Mhz) is
360+
// chosen
361+
let mut pclk2: u32 = self.pclk2.unwrap_or(min(108_000_000, hclk));
362+
377363
// Configure PPRE1
378-
let mut ppre1_val: u32 = hclk / pclk1;
364+
let mut ppre1_val: u32 = (hclk as f32 / pclk1 as f32).ceil() as u32;
379365
let ppre1: u32 = match ppre1_val {
380366
0 => unreachable!(),
381367
1 => { ppre1_val = 1; 0b000},
@@ -384,11 +370,11 @@ impl CFGR {
384370
7..=12 => { ppre1_val = 8; 0b110},
385371
_ => { ppre1_val = 16; 0b111},
386372
};
387-
// update pclk1 withe the real value
373+
// update pclk1 with the real value
388374
pclk1 = hclk / ppre1_val;
389375

390376
// Configure PPRE2
391-
let mut ppre2_val: u32 = hclk / pclk2;
377+
let mut ppre2_val: u32 = (hclk as f32 / pclk2 as f32).ceil() as u32;
392378
let ppre2: u32 = match ppre2_val {
393379
0 => unreachable!(),
394380
1 => { ppre2_val = 1; 0b000},
@@ -397,7 +383,7 @@ impl CFGR {
397383
7..=12 => { ppre2_val = 8; 0b110},
398384
_ => { ppre2_val = 16; 0b111},
399385
};
400-
// update pclk2 withe the real value
386+
// update pclk2 with the real value
401387
pclk2 = hclk / ppre2_val;
402388

403389
// Configure HCLK, PCLK1, PCLK2
@@ -409,8 +395,8 @@ impl CFGR {
409395
});
410396

411397
// Assumes TIMPRE bit of RCC_DCKCFGR1 is reset (0)
412-
let timclk1 = if ppre1 == 1 {pclk1} else {2 * pclk1};
413-
let timclk2 = if ppre2 == 1 {pclk2} else {2 * pclk2};
398+
let timclk1 = if ppre1_val == 1 {pclk1} else {2 * pclk1};
399+
let timclk2 = if ppre2_val == 1 {pclk2} else {2 * pclk2};
414400

415401
// Adjust flash wait states
416402
flash.acr.write(|w| {

0 commit comments

Comments
 (0)