daisy/
clocks.rs

1//! Configuration of the onboard clock to accomodate for typical usage focused
2//! on high-performance audio processing.
3
4use crate::hal;
5use hal::pac;
6use hal::prelude::*;
7use hal::pwr;
8use hal::rcc;
9use hal::rcc::rec::AdcClkSel;
10use hal::time::Hertz;
11use hal::time::MegaHertz;
12
13use crate::audio;
14
15// SAI clock uses pll3
16const PLL3_P: Hertz = Hertz::from_raw(audio::FS.to_Hz() * 256);
17
18pub trait SeedCrystal {
19    const CRYSTAL_FREQ: MegaHertz = MegaHertz::from_raw(16);
20
21    fn use_seed_crystal(self) -> Self;
22}
23
24impl SeedCrystal for rcc::Rcc {
25    fn use_seed_crystal(self) -> Self {
26        self.use_hse(Self::CRYSTAL_FREQ.convert())
27    }
28}
29
30/// Configures the 16 MHz crystal, a 480 MHz system clock and PLL3 for
31/// SAI audio.
32///
33/// The Daisy Seed has a 16 MHz crystal wired to the MCU's high-speed
34/// external oscillator pins. We enable that, and use it to drive the
35/// full 480 MHz system clock.
36///
37/// Usage:
38///
39/// ```
40/// let dp = pac::Peripherals::take().unwrap();
41/// let ccdr = configure(dp.PWR.constrain(), dp.RCC.constrain(), &dp.SYSCFG);
42/// let clocks = configure(rcc);
43/// ```
44pub fn configure(pwr: pwr::Pwr, rcc: rcc::Rcc, syscfg: &pac::SYSCFG) -> rcc::Ccdr {
45    let pwrcfg = pwr.vos0(syscfg).freeze();
46
47    let mut ccdr = rcc
48        .use_seed_crystal() // high speed external crystal @ 16 MHz
49        .pll1_strategy(rcc::PllConfigStrategy::Iterative) // pll1 drives system clock
50        .pll1_q_ck(48.MHz()) // required for SPI display
51        .pll3_strategy(rcc::PllConfigStrategy::Fractional) // ensure we get as close as possible to 12.288 MHz (audio clock)
52        .sys_ck(480.MHz()) // system clock @ 480 MHz
53        .pll3_p_ck(PLL3_P) // audio clock  @ 12.288 MHz
54        .freeze(pwrcfg, syscfg);
55
56    // switch adc_ker_ck_input multiplexer to per_ck
57    ccdr.peripheral.kernel_adc_clk_mux(AdcClkSel::Per);
58
59    ccdr
60}