Skip to content

Instantly share code, notes, and snippets.

@Disasm
Last active August 28, 2020 09:17
Show Gist options
  • Save Disasm/8ede1b2676e949b27c19f9ccb17bb4f8 to your computer and use it in GitHub Desktop.
Save Disasm/8ede1b2676e949b27c19f9ccb17bb4f8 to your computer and use it in GitHub Desktop.
#![no_main]
#![no_std]
extern crate panic_semihosting;
extern crate stm32f7xx_hal;
use cortex_m_rt::entry;
use stm32f7xx_hal::prelude::*;
use stm32f7xx_hal::pac;
use stm32f7xx_hal::rcc::{Rcc, HSEClock, HSEClockMode};
use cortex_m_semihosting::hprintln;
use stm32f7xx_hal::rcc::Clocks;
use stm32f7xx_hal::time::Hertz;
fn freq_eq_fuzzy(f: u32, target: u32) -> bool {
let p5 = target / 20;
((f as i32 - target as i32).abs() as u32) < p5
}
pub fn dump_clocks(hse: Hertz, clocks: &Clocks) {
let rcc = unsafe { &*pac::RCC::ptr() };
let cfgr = rcc.cfgr.read();
let pllcfgr = rcc.pllcfgr.read();
let pllm = pllcfgr.pllm().bits() as u32;
let plln = pllcfgr.plln().bits() as u32;
let pllp = pllcfgr.pllp().bits();
let pllq = pllcfgr.pllq().bits() as u32;
let pllpv = match pllp {
0b00 => 2,
0b01 => 4,
0b10 => 6,
0b11 => 8,
_ => unreachable!(),
};
hprintln!("PLL settings: m={}, n={}, p={:#b} (/{}), q={}", pllm, plln, pllp, pllpv, pllq).ok();
let vco = ((hse.0 as u64) * (plln as u64) / (pllm as u64)) as u32;
let vco_valid = 100_000_000 <= vco && vco <= 432_000_000;
hprintln!("VCO: {} (valid: {:?})", vco, vco_valid).ok();
let sysclk = vco / pllpv;
hprintln!("SYSCLK: {}", sysclk).ok();
if !freq_eq_fuzzy(sysclk, clocks.sysclk().0) {
hprintln!("[ERROR] SYSCLK does not match! {} != {} in Clocks", sysclk, clocks.sysclk().0).ok();
}
let q = vco / pllq;
// USB specification allow +-0.25%
let q_valid = (48_000_000 - q as i32).abs() <= 48_000_000 * 25 / 10000;
hprintln!("PLLQ: {} (valid: {:?})", q, q_valid).ok();
if let Some(clk) = clocks.pll48clk() {
if !freq_eq_fuzzy(clk.0, q) {
hprintln!("[ERROR] pll48clk does not match! {} != {} in Clocks", q, clk.0).ok();
}
} else {
hprintln!("[WARNING] pll48clk is not valid in Clocks").ok();
}
let hclk = match cfgr.hpre().bits() {
0b1000 => sysclk / 2,
0b1001 => sysclk / 4,
0b1010 => sysclk / 8,
0b1011 => sysclk / 16,
0b1100 => sysclk / 32,
0b1101 => sysclk / 64,
0b1110 => sysclk / 128,
0b1111 => sysclk / 256,
_ => sysclk,
};
let pclk1 = match cfgr.ppre1().bits() {
0b100 => hclk / 2,
0b101 => hclk / 4,
0b110 => hclk / 8,
0b111 => hclk / 16,
_ => hclk,
};
let pclk2 = match cfgr.ppre2().bits() {
0b100 => hclk / 2,
0b101 => hclk / 4,
0b110 => hclk / 8,
0b111 => hclk / 16,
_ => hclk,
};
let pclk1_valid = pclk1 <= 54_000_000;
let pclk2_valid = pclk2 <= 108_000_000;
hprintln!("AHB: {}", hclk).ok();
if !freq_eq_fuzzy(hclk, clocks.hclk().0) {
hprintln!("[ERROR] HCLK does not match! {} != {} in Clocks", hclk, clocks.hclk().0).ok();
}
hprintln!("APB1: {} (valid: {:?})", pclk1, pclk1_valid).ok();
if !freq_eq_fuzzy(pclk1, clocks.pclk1().0) {
hprintln!("[ERROR] PCLK1 does not match! {} != {} in Clocks", pclk1, clocks.pclk1().0).ok();
}
hprintln!("APB2: {} (valid: {:?})", pclk2, pclk2_valid).ok();
if !freq_eq_fuzzy(pclk2, clocks.pclk2().0) {
hprintln!("[ERROR] PCLK2 does not match! {} != {} in Clocks", pclk2, clocks.pclk2().0).ok();
}
}
fn test(rcc: Rcc, hse: impl Into<Hertz>, sysclk: impl Into<Hertz>) {
let hse = hse.into();
hprintln!("Before clock setup").ok();
let clocks = rcc.cfgr
.hse(HSEClock::new(hse, HSEClockMode::Bypass))
.sysclk(sysclk)
.require_pll48clk()
.freeze();
hprintln!("After clock setup").ok();
dump_clocks(hse, &clocks);
}
#[entry]
fn main() -> ! {
let p = pac::Peripherals::take().unwrap();
let rcc = p.RCC.constrain();
//test(rcc, 25.mhz(), 48.mhz());
test(rcc, 25.mhz(), 216.mhz());
//test(rcc, 12.mhz(), 48.mhz());
loop {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment