Skip to content

Commit a372a82

Browse files
authored
Merge pull request #16 from MabezDev/pll-config
RCC/PLL:
2 parents f9c7752 + b258828 commit a372a82

File tree

2 files changed

+138
-27
lines changed

2 files changed

+138
-27
lines changed

examples/pll_config.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//! Test the serial interface
2+
//!
3+
//! This example requires you to short (connect) the TX and RX pins.
4+
#![deny(unsafe_code)]
5+
#![deny(warnings)]
6+
#![no_main]
7+
#![no_std]
8+
9+
extern crate cortex_m;
10+
#[macro_use(entry, exception)]
11+
extern crate cortex_m_rt as rt;
12+
#[macro_use(block)]
13+
extern crate nb;
14+
extern crate panic_semihosting;
15+
16+
extern crate stm32l432xx_hal as hal;
17+
// #[macro_use(block)]
18+
// extern crate nb;
19+
20+
use cortex_m::asm;
21+
use hal::prelude::*;
22+
use hal::serial::Serial;
23+
use hal::stm32l4::stm32l4x2;
24+
use hal::rcc::PllConfig;
25+
use rt::ExceptionFrame;
26+
27+
entry!(main);
28+
29+
fn main() -> ! {
30+
let p = stm32l4x2::Peripherals::take().unwrap();
31+
32+
let mut flash = p.FLASH.constrain();
33+
let mut rcc = p.RCC.constrain();
34+
let mut gpioa = p.GPIOA.split(&mut rcc.ahb2);
35+
// let mut gpiob = p.GPIOB.split(&mut rcc.ahb2);
36+
37+
// clock configuration using the default settings (all clocks run at 8 MHz)
38+
// let clocks = rcc.cfgr.freeze(&mut flash.acr);
39+
// TRY this alternate clock configuration (clocks run at nearly the maximum frequency)
40+
// let clocks = rcc.cfgr.sysclk(80.mhz()).pclk1(80.mhz()).pclk2(80.mhz()).freeze(&mut flash.acr);
41+
let plls = PllConfig {
42+
m: 0b001, // / 2
43+
n: 0b1000, // * 8
44+
r: 0b11 // /8
45+
};
46+
// NOTE: it is up to the user to make sure the pll config matches the given sysclk
47+
let clocks = rcc.cfgr.sysclk_with_pll(8.mhz(), plls).pclk1(8.mhz()).pclk2(8.mhz()).freeze(&mut flash.acr);
48+
49+
// The Serial API is highly generic
50+
// TRY the commented out, different pin configurations
51+
let tx = gpioa.pa9.into_af7(&mut gpioa.moder, &mut gpioa.afrh);
52+
// let tx = gpiob.pb6.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
53+
54+
let rx = gpioa.pa10.into_af7(&mut gpioa.moder, &mut gpioa.afrh);
55+
// let rx = gpiob.pb7.into_af7(&mut gpiob.moder, &mut gpiob.afrl);
56+
57+
// TRY using a different USART peripheral here
58+
let serial = Serial::usart1(p.USART1, (tx, rx), 9_600.bps(), clocks, &mut rcc.apb2);
59+
let (mut tx, mut rx) = serial.split();
60+
61+
let sent = b'X';
62+
63+
// The `block!` macro makes an operation block until it finishes
64+
// NOTE the error type is `!`
65+
66+
block!(tx.write(sent)).ok();
67+
68+
let received = block!(rx.read()).unwrap();
69+
70+
assert_eq!(received, sent);
71+
72+
// if all goes well you should reach this breakpoint
73+
asm::bkpt();
74+
75+
loop {}
76+
}
77+
78+
exception!(HardFault, hard_fault);
79+
80+
fn hard_fault(ef: &ExceptionFrame) -> ! {
81+
panic!("{:#?}", ef);
82+
}
83+
84+
exception!(*, default_handler);
85+
86+
fn default_handler(irqn: i16) {
87+
panic!("Unhandled exception (IRQn = {})", irqn);
88+
}

src/rcc.rs

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ impl RccExt for RCC {
3030
pclk1: None,
3131
pclk2: None,
3232
sysclk: None,
33+
pllcfg: None,
3334
},
3435
}
3536
}
@@ -204,6 +205,7 @@ pub struct CFGR {
204205
pclk1: Option<u32>,
205206
pclk2: Option<u32>,
206207
sysclk: Option<u32>,
208+
pllcfg: Option<PllConfig>
207209
}
208210

209211
impl CFGR {
@@ -243,17 +245,41 @@ impl CFGR {
243245
self
244246
}
245247

248+
/// Sets the system (core) frequency with some pll configuration
249+
pub fn sysclk_with_pll<F>(mut self, freq: F, cfg: PllConfig) -> Self
250+
where
251+
F: Into<Hertz>,
252+
{
253+
self.pllcfg = Some(cfg);
254+
self.sysclk = Some(freq.into().0);
255+
self
256+
}
257+
246258
/// Freezes the clock configuration, making it effective
247259
pub fn freeze(self, acr: &mut ACR) -> Clocks {
248-
let pllmul = (2 * self.sysclk.unwrap_or(HSI)) / HSI;
249-
let pllmul = cmp::min(cmp::max(pllmul, 2), 16);
250-
let pllmul_bits = if pllmul == 2 {
251-
None
260+
261+
let pllconf = if self.pllcfg.is_none() {
262+
let plln = (2 * self.sysclk.unwrap_or(HSI)) / HSI;
263+
let plln = cmp::min(cmp::max(plln, 2), 16);
264+
if plln == 2 {
265+
None
266+
} else {
267+
// create a best effort pll config, just multiply n
268+
// TODO should we reject this configuration as the clocks stored in RCC could cause timing issues?
269+
let conf = PllConfig {
270+
m: 0b0,
271+
r: 0b0,
272+
n: plln as u8
273+
};
274+
Some(conf)
275+
}
276+
252277
} else {
253-
Some(pllmul as u8) // - 2
278+
let conf = self.pllcfg.unwrap();
279+
Some(conf)
254280
};
255281

256-
let sysclk = pllmul * HSI / 2;
282+
let sysclk = self.sysclk.unwrap_or(HSI);
257283

258284
assert!(sysclk <= 80_000_000);
259285

@@ -274,7 +300,7 @@ impl CFGR {
274300

275301
let hclk = sysclk / (1 << (hpre_bits));
276302

277-
assert!(hclk <= 80_000_000);
303+
assert!(hclk <= sysclk);
278304

279305
let ppre1_bits = self.pclk1
280306
.map(|pclk1| match hclk / pclk1 {
@@ -290,21 +316,7 @@ impl CFGR {
290316
let ppre1 = 1 << (ppre1_bits);
291317
let pclk1 = hclk / u32(ppre1);
292318

293-
assert!(pclk1 <= 80_000_000);
294-
295-
// let ppre2_bits = self.pclk2
296-
// .map(|pclk2| match hclk / pclk2 {
297-
// 0 => unreachable!(),
298-
// 1 => 0b011,
299-
// 2 => 0b100,
300-
// 3...5 => 0b101,
301-
// 6...11 => 0b110,
302-
// _ => 0b111,
303-
// })
304-
// .unwrap_or(0b011);
305-
306-
// let ppre2 = 1 << (ppre2_bits - 0b011);
307-
// let pclk2 = hclk / u32(ppre2);
319+
assert!(pclk1 <= sysclk);
308320

309321
let ppre2_bits = self.pclk2
310322
.map(|pclk2| match hclk / pclk2 {
@@ -320,7 +332,7 @@ impl CFGR {
320332
let ppre2 = 1 << (ppre2_bits);
321333
let pclk2 = hclk / u32(ppre2);
322334

323-
assert!(pclk2 <= 80_000_000);
335+
assert!(pclk2 <= sysclk);
324336

325337
// adjust flash wait states
326338
unsafe {
@@ -337,7 +349,7 @@ impl CFGR {
337349

338350
let rcc = unsafe { &*RCC::ptr() };
339351
let sysclk_src_bits;
340-
if let Some(pllmul_bits) = pllmul_bits {
352+
if let Some(pllconf) = pllconf {
341353
// use PLL as source
342354
sysclk_src_bits = 0b11;
343355
rcc.cr.modify(|_, w| w.pllon().clear_bit());
@@ -351,9 +363,9 @@ impl CFGR {
351363
.modify(|_, w| unsafe {
352364
w.pllsrc()
353365
.bits(pllsrc_bits)
354-
.pllm().bits(0b0) // no division, how to calculate?
355-
.pllr().bits(0b0) // no division, how to calculate?
356-
.plln().bits(pllmul_bits)
366+
.pllm().bits(pllconf.m)
367+
.pllr().bits(pllconf.r)
368+
.plln().bits(pllconf.n)
357369
});
358370

359371
rcc.cr.modify(|_, w| w.pllon().set_bit());
@@ -414,6 +426,17 @@ impl CFGR {
414426
}
415427
}
416428

429+
#[derive(Clone, Copy)]
430+
/// Pll Configuration - Calculation = ((SourceClk / m) * n) / r
431+
pub struct PllConfig {
432+
/// Main PLL Division factor
433+
pub m: u8,
434+
/// Main Pll Multiplication factor
435+
pub n: u8,
436+
/// Main PLL division factor for PLLCLK (system clock)
437+
pub r: u8,
438+
}
439+
417440
/// Frozen clock frequencies
418441
///
419442
/// The existence of this value indicates that the clock configuration can no longer be changed

0 commit comments

Comments
 (0)