[embassy-stm32]: started stm32g4 RCC refactor
* Copied API from f.rs where applicable * HSE and HSI independantly configurable * Boost mode set by user rather * Added HSE, pll1_q and pll1_p frequencies to set_clocks call * Stubbed max module based on f.rs, needs cleanup
This commit is contained in:
@ -1,10 +1,10 @@
|
|||||||
use stm32_metapac::flash::vals::Latency;
|
use stm32_metapac::flash::vals::Latency;
|
||||||
use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
|
use stm32_metapac::rcc::vals::{Adcsel, Sw};
|
||||||
use stm32_metapac::FLASH;
|
use stm32_metapac::FLASH;
|
||||||
|
|
||||||
pub use crate::pac::rcc::vals::{
|
pub use crate::pac::rcc::vals::{
|
||||||
Adcsel as AdcClockSource, Fdcansel as FdCanClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN,
|
Adcsel as AdcClockSource, Clk48sel, Fdcansel as FdCanClockSource, Hpre as AHBPrescaler, Pllm as PllPreDiv,
|
||||||
Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler,
|
Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc, Ppre as APBPrescaler, Sw as Sysclk,
|
||||||
};
|
};
|
||||||
use crate::pac::{PWR, RCC};
|
use crate::pac::{PWR, RCC};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
@ -12,28 +12,20 @@ use crate::time::Hertz;
|
|||||||
/// HSI speed
|
/// HSI speed
|
||||||
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
|
||||||
|
|
||||||
/// System clock mux source
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
#[derive(Clone, Copy)]
|
pub enum HseMode {
|
||||||
pub enum ClockSrc {
|
/// crystal/ceramic oscillator (HSEBYP=0)
|
||||||
HSE(Hertz),
|
Oscillator,
|
||||||
HSI,
|
/// external analog clock (low swing) (HSEBYP=1)
|
||||||
PLL,
|
Bypass,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PLL clock input source
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
pub struct Hse {
|
||||||
pub enum PllSource {
|
/// HSE frequency.
|
||||||
HSI,
|
pub freq: Hertz,
|
||||||
HSE(Hertz),
|
/// HSE mode.
|
||||||
}
|
pub mode: HseMode,
|
||||||
|
|
||||||
impl Into<Pllsrc> for PllSource {
|
|
||||||
fn into(self) -> Pllsrc {
|
|
||||||
match self {
|
|
||||||
PllSource::HSE(..) => Pllsrc::HSE,
|
|
||||||
PllSource::HSI => Pllsrc::HSI,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PLL Configuration
|
/// PLL Configuration
|
||||||
@ -43,22 +35,22 @@ impl Into<Pllsrc> for PllSource {
|
|||||||
/// frequency ranges for each of these settings.
|
/// frequency ranges for each of these settings.
|
||||||
pub struct Pll {
|
pub struct Pll {
|
||||||
/// PLL Source clock selection.
|
/// PLL Source clock selection.
|
||||||
pub source: PllSource,
|
pub source: Pllsrc,
|
||||||
|
|
||||||
/// PLL pre-divider
|
/// PLL pre-divider
|
||||||
pub prediv_m: PllM,
|
pub prediv: PllPreDiv,
|
||||||
|
|
||||||
/// PLL multiplication factor for VCO
|
/// PLL multiplication factor for VCO
|
||||||
pub mul_n: PllN,
|
pub mul: PllMul,
|
||||||
|
|
||||||
/// PLL division factor for P clock (ADC Clock)
|
/// PLL division factor for P clock (ADC Clock)
|
||||||
pub div_p: Option<PllP>,
|
pub divp: Option<PllPDiv>,
|
||||||
|
|
||||||
/// PLL division factor for Q clock (USB, I2S23, SAI1, FDCAN, QSPI)
|
/// PLL division factor for Q clock (USB, I2S23, SAI1, FDCAN, QSPI)
|
||||||
pub div_q: Option<PllQ>,
|
pub divq: Option<PllQDiv>,
|
||||||
|
|
||||||
/// PLL division factor for R clock (SYSCLK)
|
/// PLL division factor for R clock (SYSCLK)
|
||||||
pub div_r: Option<PllR>,
|
pub divr: Option<PllRDiv>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the source for the 48MHz clock to the USB and RNG peripherals.
|
/// Sets the source for the 48MHz clock to the USB and RNG peripherals.
|
||||||
@ -73,39 +65,53 @@ pub enum Clock48MhzSrc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Clocks configutation
|
/// Clocks configutation
|
||||||
|
#[non_exhaustive]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub mux: ClockSrc,
|
pub hsi: bool,
|
||||||
|
pub hse: Option<Hse>,
|
||||||
|
pub sys: Sysclk,
|
||||||
|
pub hsi48: Option<super::Hsi48Config>,
|
||||||
|
|
||||||
|
pub pll: Option<Pll>,
|
||||||
|
|
||||||
|
/// Iff PLL is requested as the main clock source in the `mux` field then the PLL configuration
|
||||||
|
/// MUST turn on the PLLR output.
|
||||||
pub ahb_pre: AHBPrescaler,
|
pub ahb_pre: AHBPrescaler,
|
||||||
pub apb1_pre: APBPrescaler,
|
pub apb1_pre: APBPrescaler,
|
||||||
pub apb2_pre: APBPrescaler,
|
pub apb2_pre: APBPrescaler,
|
||||||
pub low_power_run: bool,
|
pub low_power_run: bool,
|
||||||
/// Iff PLL is requested as the main clock source in the `mux` field then the PLL configuration
|
|
||||||
/// MUST turn on the PLLR output.
|
|
||||||
pub pll: Option<Pll>,
|
|
||||||
/// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals.
|
/// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals.
|
||||||
pub clock_48mhz_src: Option<Clock48MhzSrc>,
|
pub clk48_src: Option<Clock48MhzSrc>,
|
||||||
|
|
||||||
|
pub ls: super::LsConfig,
|
||||||
|
|
||||||
pub adc12_clock_source: AdcClockSource,
|
pub adc12_clock_source: AdcClockSource,
|
||||||
pub adc345_clock_source: AdcClockSource,
|
pub adc345_clock_source: AdcClockSource,
|
||||||
pub fdcan_clock_source: FdCanClockSource,
|
pub fdcan_clock_source: FdCanClockSource,
|
||||||
|
|
||||||
pub ls: super::LsConfig,
|
pub boost: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn default() -> Config {
|
fn default() -> Config {
|
||||||
Config {
|
Config {
|
||||||
mux: ClockSrc::HSI,
|
hsi: true,
|
||||||
|
hse: None,
|
||||||
|
sys: Sysclk::HSI,
|
||||||
|
hsi48: Some(Default::default()),
|
||||||
|
pll: None,
|
||||||
ahb_pre: AHBPrescaler::DIV1,
|
ahb_pre: AHBPrescaler::DIV1,
|
||||||
apb1_pre: APBPrescaler::DIV1,
|
apb1_pre: APBPrescaler::DIV1,
|
||||||
apb2_pre: APBPrescaler::DIV1,
|
apb2_pre: APBPrescaler::DIV1,
|
||||||
low_power_run: false,
|
low_power_run: false,
|
||||||
pll: None,
|
clk48_src: Some(Clock48MhzSrc::Hsi48(Default::default())),
|
||||||
clock_48mhz_src: Some(Clock48MhzSrc::Hsi48(Default::default())),
|
ls: Default::default(),
|
||||||
adc12_clock_source: Adcsel::DISABLE,
|
adc12_clock_source: Adcsel::DISABLE,
|
||||||
adc345_clock_source: Adcsel::DISABLE,
|
adc345_clock_source: Adcsel::DISABLE,
|
||||||
fdcan_clock_source: FdCanClockSource::PCLK1,
|
fdcan_clock_source: FdCanClockSource::PCLK1,
|
||||||
ls: Default::default(),
|
boost: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,34 +123,60 @@ pub struct PllFreq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn init(config: Config) {
|
pub(crate) unsafe fn init(config: Config) {
|
||||||
|
// Configure HSI
|
||||||
|
let hsi = match config.hsi {
|
||||||
|
false => {
|
||||||
|
RCC.cr().modify(|w| w.set_hsion(false));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
true => {
|
||||||
|
RCC.cr().modify(|w| w.set_hsion(true));
|
||||||
|
while !RCC.cr().read().hsirdy() {}
|
||||||
|
Some(HSI_FREQ)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configure HSE
|
||||||
|
let hse = match config.hse {
|
||||||
|
None => {
|
||||||
|
RCC.cr().modify(|w| w.set_hseon(false));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Some(hse) => {
|
||||||
|
match hse.mode {
|
||||||
|
HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)),
|
||||||
|
HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)),
|
||||||
|
}
|
||||||
|
|
||||||
|
RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator));
|
||||||
|
RCC.cr().modify(|w| w.set_hseon(true));
|
||||||
|
while !RCC.cr().read().hserdy() {}
|
||||||
|
Some(hse.freq)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let pll_freq = config.pll.map(|pll_config| {
|
let pll_freq = config.pll.map(|pll_config| {
|
||||||
let src_freq = match pll_config.source {
|
let src_freq = match pll_config.source {
|
||||||
PllSource::HSI => {
|
Pllsrc::HSI => unwrap!(hsi),
|
||||||
RCC.cr().write(|w| w.set_hsion(true));
|
Pllsrc::HSE => unwrap!(hse),
|
||||||
while !RCC.cr().read().hsirdy() {}
|
_ => unreachable!(),
|
||||||
|
|
||||||
HSI_FREQ
|
|
||||||
}
|
|
||||||
PllSource::HSE(freq) => {
|
|
||||||
RCC.cr().write(|w| w.set_hseon(true));
|
|
||||||
while !RCC.cr().read().hserdy() {}
|
|
||||||
freq
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: check PLL input, internal and output frequencies for validity
|
||||||
|
|
||||||
// Disable PLL before configuration
|
// Disable PLL before configuration
|
||||||
RCC.cr().modify(|w| w.set_pllon(false));
|
RCC.cr().modify(|w| w.set_pllon(false));
|
||||||
while RCC.cr().read().pllrdy() {}
|
while RCC.cr().read().pllrdy() {}
|
||||||
|
|
||||||
let internal_freq = src_freq / pll_config.prediv_m * pll_config.mul_n;
|
let internal_freq = src_freq / pll_config.prediv * pll_config.mul;
|
||||||
|
|
||||||
RCC.pllcfgr().write(|w| {
|
RCC.pllcfgr().write(|w| {
|
||||||
w.set_plln(pll_config.mul_n);
|
w.set_plln(pll_config.mul);
|
||||||
w.set_pllm(pll_config.prediv_m);
|
w.set_pllm(pll_config.prediv);
|
||||||
w.set_pllsrc(pll_config.source.into());
|
w.set_pllsrc(pll_config.source.into());
|
||||||
});
|
});
|
||||||
|
|
||||||
let pll_p_freq = pll_config.div_p.map(|div_p| {
|
let pll_p_freq = pll_config.divp.map(|div_p| {
|
||||||
RCC.pllcfgr().modify(|w| {
|
RCC.pllcfgr().modify(|w| {
|
||||||
w.set_pllp(div_p);
|
w.set_pllp(div_p);
|
||||||
w.set_pllpen(true);
|
w.set_pllpen(true);
|
||||||
@ -152,7 +184,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
internal_freq / div_p
|
internal_freq / div_p
|
||||||
});
|
});
|
||||||
|
|
||||||
let pll_q_freq = pll_config.div_q.map(|div_q| {
|
let pll_q_freq = pll_config.divq.map(|div_q| {
|
||||||
RCC.pllcfgr().modify(|w| {
|
RCC.pllcfgr().modify(|w| {
|
||||||
w.set_pllq(div_q);
|
w.set_pllq(div_q);
|
||||||
w.set_pllqen(true);
|
w.set_pllqen(true);
|
||||||
@ -160,7 +192,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
internal_freq / div_q
|
internal_freq / div_q
|
||||||
});
|
});
|
||||||
|
|
||||||
let pll_r_freq = pll_config.div_r.map(|div_r| {
|
let pll_r_freq = pll_config.divr.map(|div_r| {
|
||||||
RCC.pllcfgr().modify(|w| {
|
RCC.pllcfgr().modify(|w| {
|
||||||
w.set_pllr(div_r);
|
w.set_pllr(div_r);
|
||||||
w.set_pllren(true);
|
w.set_pllren(true);
|
||||||
@ -179,22 +211,10 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let (sys_clk, sw) = match config.mux {
|
let (sys_clk, sw) = match config.sys {
|
||||||
ClockSrc::HSI => {
|
Sysclk::HSI => (HSI_FREQ, Sw::HSI),
|
||||||
// Enable HSI
|
Sysclk::HSE => (unwrap!(hse), Sw::HSE),
|
||||||
RCC.cr().write(|w| w.set_hsion(true));
|
Sysclk::PLL1_R => {
|
||||||
while !RCC.cr().read().hsirdy() {}
|
|
||||||
|
|
||||||
(HSI_FREQ, Sw::HSI)
|
|
||||||
}
|
|
||||||
ClockSrc::HSE(freq) => {
|
|
||||||
// Enable HSE
|
|
||||||
RCC.cr().write(|w| w.set_hseon(true));
|
|
||||||
while !RCC.cr().read().hserdy() {}
|
|
||||||
|
|
||||||
(freq, Sw::HSE)
|
|
||||||
}
|
|
||||||
ClockSrc::PLL => {
|
|
||||||
assert!(pll_freq.is_some());
|
assert!(pll_freq.is_some());
|
||||||
assert!(pll_freq.as_ref().unwrap().pll_r.is_some());
|
assert!(pll_freq.as_ref().unwrap().pll_r.is_some());
|
||||||
|
|
||||||
@ -202,10 +222,9 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
|
|
||||||
assert!(freq <= 170_000_000);
|
assert!(freq <= 170_000_000);
|
||||||
|
|
||||||
if freq >= 150_000_000 {
|
if config.boost {
|
||||||
// Enable Core Boost mode on freq >= 150Mhz ([RM0440] p234)
|
// Enable Core Boost mode ([RM0440] p234)
|
||||||
PWR.cr5().modify(|w| w.set_r1mode(false));
|
PWR.cr5().modify(|w| w.set_r1mode(false));
|
||||||
// Set flash wait state in boost mode based on frequency ([RM0440] p191)
|
|
||||||
if freq <= 36_000_000 {
|
if freq <= 36_000_000 {
|
||||||
FLASH.acr().modify(|w| w.set_latency(Latency::WS0));
|
FLASH.acr().modify(|w| w.set_latency(Latency::WS0));
|
||||||
} else if freq <= 68_000_000 {
|
} else if freq <= 68_000_000 {
|
||||||
@ -218,8 +237,8 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
FLASH.acr().modify(|w| w.set_latency(Latency::WS4));
|
FLASH.acr().modify(|w| w.set_latency(Latency::WS4));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Enable Core Boost mode ([RM0440] p234)
|
||||||
PWR.cr5().modify(|w| w.set_r1mode(true));
|
PWR.cr5().modify(|w| w.set_r1mode(true));
|
||||||
// Set flash wait state in normal mode based on frequency ([RM0440] p191)
|
|
||||||
if freq <= 30_000_000 {
|
if freq <= 30_000_000 {
|
||||||
FLASH.acr().modify(|w| w.set_latency(Latency::WS0));
|
FLASH.acr().modify(|w| w.set_latency(Latency::WS0));
|
||||||
} else if freq <= 60_000_000 {
|
} else if freq <= 60_000_000 {
|
||||||
@ -235,6 +254,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
|
|
||||||
(Hertz(freq), Sw::PLL1_R)
|
(Hertz(freq), Sw::PLL1_R)
|
||||||
}
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
RCC.cfgr().modify(|w| {
|
RCC.cfgr().modify(|w| {
|
||||||
@ -263,7 +283,7 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Setup the 48 MHz clock if needed
|
// Setup the 48 MHz clock if needed
|
||||||
if let Some(clock_48mhz_src) = config.clock_48mhz_src {
|
if let Some(clock_48mhz_src) = config.clk48_src {
|
||||||
let source = match clock_48mhz_src {
|
let source = match clock_48mhz_src {
|
||||||
Clock48MhzSrc::PllQ => {
|
Clock48MhzSrc::PllQ => {
|
||||||
// Make sure the PLLQ is enabled and running at 48Mhz
|
// Make sure the PLLQ is enabled and running at 48Mhz
|
||||||
@ -317,9 +337,33 @@ pub(crate) unsafe fn init(config: Config) {
|
|||||||
pclk2_tim: Some(apb2_tim_freq),
|
pclk2_tim: Some(apb2_tim_freq),
|
||||||
adc: adc12_ck,
|
adc: adc12_ck,
|
||||||
adc34: adc345_ck,
|
adc34: adc345_ck,
|
||||||
pll1_p: None,
|
pll1_p: pll_freq.as_ref().and_then(|pll| pll.pll_p),
|
||||||
pll1_q: None, // TODO
|
pll1_q: pll_freq.as_ref().and_then(|pll| pll.pll_p),
|
||||||
hse: None, // TODO
|
hse: hse,
|
||||||
rtc: rtc,
|
rtc: rtc,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: if necessary, make more of these gated behind cfg attrs
|
||||||
|
mod max {
|
||||||
|
use core::ops::RangeInclusive;
|
||||||
|
|
||||||
|
use crate::time::Hertz;
|
||||||
|
|
||||||
|
/// HSE 4-48MHz (RM0440 p280)
|
||||||
|
pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(48_000_000);
|
||||||
|
|
||||||
|
/// External Clock ?-48MHz (RM0440 p280)
|
||||||
|
pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000);
|
||||||
|
|
||||||
|
/// SYSCLK ?-170MHz (RM0440 p282)
|
||||||
|
pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(170_000_000);
|
||||||
|
|
||||||
|
/// PLL Output frequency ?-170MHz (RM0440 p281)
|
||||||
|
pub(crate) const PCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(170_000_000);
|
||||||
|
|
||||||
|
// Left over from f.rs, remove if not necessary
|
||||||
|
pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(12_500_000)..=Hertz(216_000_000);
|
||||||
|
pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(2_100_000);
|
||||||
|
pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(100_000_000)..=Hertz(432_000_000);
|
||||||
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::adc::{Adc, SampleTime};
|
use embassy_stm32::adc::{Adc, SampleTime};
|
||||||
use embassy_stm32::rcc::{AdcClockSource, ClockSrc, Pll, PllM, PllN, PllR, PllSource};
|
use embassy_stm32::rcc::{AdcClockSource, Pll, PllMul, PllPreDiv, PllRDiv, Pllsrc, Sysclk};
|
||||||
use embassy_stm32::Config;
|
use embassy_stm32::Config;
|
||||||
use embassy_time::{Delay, Timer};
|
use embassy_time::{Delay, Timer};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -14,17 +14,17 @@ async fn main(_spawner: Spawner) {
|
|||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
|
|
||||||
config.rcc.pll = Some(Pll {
|
config.rcc.pll = Some(Pll {
|
||||||
source: PllSource::HSI,
|
source: Pllsrc::HSI,
|
||||||
prediv_m: PllM::DIV4,
|
prediv: PllPreDiv::DIV4,
|
||||||
mul_n: PllN::MUL85,
|
mul: PllMul::MUL85,
|
||||||
div_p: None,
|
divp: None,
|
||||||
div_q: None,
|
divq: None,
|
||||||
// Main system clock at 170 MHz
|
// Main system clock at 170 MHz
|
||||||
div_r: Some(PllR::DIV2),
|
divr: Some(PllRDiv::DIV2),
|
||||||
});
|
});
|
||||||
|
|
||||||
config.rcc.adc12_clock_source = AdcClockSource::SYS;
|
config.rcc.adc12_clock_source = AdcClockSource::SYS;
|
||||||
config.rcc.mux = ClockSrc::PLL;
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
|
|
||||||
let mut p = embassy_stm32::init(config);
|
let mut p = embassy_stm32::init(config);
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::rcc::{ClockSrc, Pll, PllM, PllN, PllR, PllSource};
|
use embassy_stm32::rcc::{Pll, PllMul, PllPreDiv, PllRDiv, Pllsrc, Sysclk};
|
||||||
use embassy_stm32::Config;
|
use embassy_stm32::Config;
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
@ -13,16 +13,16 @@ async fn main(_spawner: Spawner) {
|
|||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
|
|
||||||
config.rcc.pll = Some(Pll {
|
config.rcc.pll = Some(Pll {
|
||||||
source: PllSource::HSI,
|
source: Pllsrc::HSI,
|
||||||
prediv_m: PllM::DIV4,
|
prediv: PllPreDiv::DIV4,
|
||||||
mul_n: PllN::MUL85,
|
mul: PllMul::MUL85,
|
||||||
div_p: None,
|
divp: None,
|
||||||
div_q: None,
|
divq: None,
|
||||||
// Main system clock at 170 MHz
|
// Main system clock at 170 MHz
|
||||||
div_r: Some(PllR::DIV2),
|
divr: Some(PllRDiv::DIV2),
|
||||||
});
|
});
|
||||||
|
|
||||||
config.rcc.mux = ClockSrc::PLL;
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
|
|
||||||
let _p = embassy_stm32::init(config);
|
let _p = embassy_stm32::init(config);
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
use defmt::{panic, *};
|
use defmt::{panic, *};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::rcc::{Clock48MhzSrc, ClockSrc, Hsi48Config, Pll, PllM, PllN, PllQ, PllR, PllSource};
|
use embassy_stm32::rcc::{
|
||||||
|
Clock48MhzSrc, Hse, HseMode, Hsi48Config, Pll, PllMul, PllPreDiv, PllQDiv, PllRDiv, Pllsrc, Sysclk,
|
||||||
|
};
|
||||||
use embassy_stm32::time::Hertz;
|
use embassy_stm32::time::Hertz;
|
||||||
use embassy_stm32::usb::{self, Driver, Instance};
|
use embassy_stm32::usb::{self, Driver, Instance};
|
||||||
use embassy_stm32::{bind_interrupts, peripherals, Config};
|
use embassy_stm32::{bind_interrupts, peripherals, Config};
|
||||||
@ -24,25 +26,30 @@ async fn main(_spawner: Spawner) {
|
|||||||
// Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
|
// Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE.
|
||||||
const USE_HSI48: bool = true;
|
const USE_HSI48: bool = true;
|
||||||
|
|
||||||
let plldivq = if USE_HSI48 { None } else { Some(PllQ::DIV6) };
|
let plldivq = if USE_HSI48 { None } else { Some(PllQDiv::DIV6) };
|
||||||
|
|
||||||
config.rcc.pll = Some(Pll {
|
config.rcc.hse = Some(Hse {
|
||||||
source: PllSource::HSE(Hertz(8_000_000)),
|
freq: Hertz(8_000_000),
|
||||||
prediv_m: PllM::DIV2,
|
mode: HseMode::Oscillator,
|
||||||
mul_n: PllN::MUL72,
|
|
||||||
div_p: None,
|
|
||||||
div_q: plldivq,
|
|
||||||
// Main system clock at 144 MHz
|
|
||||||
div_r: Some(PllR::DIV2),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
config.rcc.mux = ClockSrc::PLL;
|
config.rcc.pll = Some(Pll {
|
||||||
|
source: Pllsrc::HSE,
|
||||||
|
prediv: PllPreDiv::DIV2,
|
||||||
|
mul: PllMul::MUL72,
|
||||||
|
divp: None,
|
||||||
|
divq: plldivq,
|
||||||
|
// Main system clock at 144 MHz
|
||||||
|
divr: Some(PllRDiv::DIV2),
|
||||||
|
});
|
||||||
|
|
||||||
|
config.rcc.sys = Sysclk::PLL1_R;
|
||||||
|
|
||||||
if USE_HSI48 {
|
if USE_HSI48 {
|
||||||
// Sets up the Clock Recovery System (CRS) to use the USB SOF to trim the HSI48 oscillator.
|
// Sets up the Clock Recovery System (CRS) to use the USB SOF to trim the HSI48 oscillator.
|
||||||
config.rcc.clock_48mhz_src = Some(Clock48MhzSrc::Hsi48(Hsi48Config { sync_from_usb: true }));
|
config.rcc.clk48_src = Some(Clock48MhzSrc::Hsi48(Hsi48Config { sync_from_usb: true }));
|
||||||
} else {
|
} else {
|
||||||
config.rcc.clock_48mhz_src = Some(Clock48MhzSrc::PllQ);
|
config.rcc.clk48_src = Some(Clock48MhzSrc::PllQ);
|
||||||
}
|
}
|
||||||
|
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
Reference in New Issue
Block a user