parent
edb3989b57
commit
0dc5e6d3e4
10 changed files with 351 additions and 412 deletions
|
@ -68,7 +68,7 @@ rand_core = "0.6.3"
|
||||||
sdio-host = "0.5.0"
|
sdio-host = "0.5.0"
|
||||||
critical-section = "1.1"
|
critical-section = "1.1"
|
||||||
#stm32-metapac = { version = "15" }
|
#stm32-metapac = { version = "15" }
|
||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-5bf4bec597bdf0d85402789b40c3a37b0f5a8e76" }
|
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ae5bb5fe696a7e61fb41b8b797372aed8103a82" }
|
||||||
vcell = "0.1.3"
|
vcell = "0.1.3"
|
||||||
bxcan = "0.7.0"
|
bxcan = "0.7.0"
|
||||||
nb = "1.0.0"
|
nb = "1.0.0"
|
||||||
|
@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] }
|
||||||
proc-macro2 = "1.0.36"
|
proc-macro2 = "1.0.36"
|
||||||
quote = "1.0.15"
|
quote = "1.0.15"
|
||||||
#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
|
#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
|
||||||
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-5bf4bec597bdf0d85402789b40c3a37b0f5a8e76", default-features = false, features = ["metadata"]}
|
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ae5bb5fe696a7e61fb41b8b797372aed8103a82", default-features = false, features = ["metadata"]}
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|
|
@ -1,208 +1,230 @@
|
||||||
#[cfg(rcc_f3)]
|
|
||||||
use crate::pac::adccommon::vals::Ckmode;
|
|
||||||
use crate::pac::flash::vals::Latency;
|
use crate::pac::flash::vals::Latency;
|
||||||
pub use crate::pac::rcc::vals::Adcpres;
|
pub use crate::pac::rcc::vals::{
|
||||||
use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
|
Adcpres as AdcPllPrescaler, Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Prediv as PllPreDiv,
|
||||||
|
Sw as Sysclk,
|
||||||
|
};
|
||||||
|
use crate::pac::rcc::vals::{Pllsrc, Usbpre};
|
||||||
use crate::pac::{FLASH, RCC};
|
use crate::pac::{FLASH, RCC};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
|
||||||
/// HSI speed
|
/// HSI speed
|
||||||
pub const HSI_FREQ: Hertz = Hertz(8_000_000);
|
pub const HSI_FREQ: Hertz = Hertz(8_000_000);
|
||||||
|
|
||||||
#[cfg(rcc_f3)]
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
impl From<AdcClockSource> for Ckmode {
|
pub enum HseMode {
|
||||||
fn from(value: AdcClockSource) -> Self {
|
/// crystal/ceramic oscillator (HSEBYP=0)
|
||||||
match value {
|
Oscillator,
|
||||||
AdcClockSource::BusDiv1 => Ckmode::SYNCDIV1,
|
/// external analog clock (low swing) (HSEBYP=1)
|
||||||
AdcClockSource::BusDiv2 => Ckmode::SYNCDIV2,
|
Bypass,
|
||||||
AdcClockSource::BusDiv4 => Ckmode::SYNCDIV4,
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
}
|
pub struct Hse {
|
||||||
|
/// HSE frequency.
|
||||||
|
pub freq: Hertz,
|
||||||
|
/// HSE mode.
|
||||||
|
pub mode: HseMode,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||||
|
pub enum PllSource {
|
||||||
|
HSE,
|
||||||
|
HSI,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct Pll {
|
||||||
|
pub src: PllSource,
|
||||||
|
|
||||||
|
/// PLL pre-divider.
|
||||||
|
///
|
||||||
|
/// On some F3 chips, this must be 2 if `src == HSI`. Init will panic if this is not the case.
|
||||||
|
pub prediv: PllPreDiv,
|
||||||
|
|
||||||
|
/// PLL multiplication factor.
|
||||||
|
pub mul: PllMul,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum AdcClockSource {
|
pub enum AdcClockSource {
|
||||||
Pll(Adcpres),
|
Pll(AdcPllPrescaler),
|
||||||
BusDiv1,
|
Hclk(AdcHclkPrescaler),
|
||||||
BusDiv2,
|
|
||||||
BusDiv4,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AdcClockSource {
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub fn bus_div(&self) -> u32 {
|
pub enum AdcHclkPrescaler {
|
||||||
match self {
|
Div1,
|
||||||
Self::BusDiv1 => 1,
|
Div2,
|
||||||
Self::BusDiv2 => 2,
|
Div4,
|
||||||
Self::BusDiv4 => 4,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum HrtimClockSource {
|
pub enum HrtimClockSource {
|
||||||
#[default]
|
|
||||||
BusClk,
|
BusClk,
|
||||||
PllClk,
|
PllClk,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clocks configutation
|
/// Clocks configutation
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
#[derive(Default)]
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// Frequency of HSE oscillator
|
pub hsi: bool,
|
||||||
/// 4MHz to 32MHz
|
pub hse: Option<Hse>,
|
||||||
pub hse: Option<Hertz>,
|
pub sys: Sysclk,
|
||||||
/// Bypass HSE for an external clock
|
|
||||||
pub bypass_hse: bool,
|
pub pll: Option<Pll>,
|
||||||
/// Frequency of the System Clock
|
|
||||||
pub sysclk: Option<Hertz>,
|
pub ahb_pre: AHBPrescaler,
|
||||||
/// Frequency of AHB bus
|
pub apb1_pre: APBPrescaler,
|
||||||
pub hclk: Option<Hertz>,
|
pub apb2_pre: APBPrescaler,
|
||||||
/// Frequency of APB1 bus
|
|
||||||
/// - Max frequency 36MHz
|
#[cfg(not(rcc_f37))]
|
||||||
pub pclk1: Option<Hertz>,
|
pub adc: AdcClockSource,
|
||||||
/// Frequency of APB2 bus
|
#[cfg(all(not(rcc_f37), adc3_common))]
|
||||||
/// - Max frequency with HSE is 72MHz
|
pub adc34: AdcClockSource,
|
||||||
/// - Max frequency without HSE is 64MHz
|
|
||||||
pub pclk2: Option<Hertz>,
|
|
||||||
/// USB clock setup
|
|
||||||
/// It is valid only when,
|
|
||||||
/// - HSE is enabled,
|
|
||||||
/// - The System clock frequency is either 48MHz or 72MHz
|
|
||||||
/// - APB1 clock has a minimum frequency of 10MHz
|
|
||||||
pub pll48: bool,
|
|
||||||
#[cfg(rcc_f3)]
|
|
||||||
/// ADC clock setup
|
|
||||||
/// - For AHB, a psc of 4 or less must be used
|
|
||||||
pub adc: Option<AdcClockSource>,
|
|
||||||
#[cfg(rcc_f3)]
|
|
||||||
/// ADC clock setup
|
|
||||||
/// - For AHB, a psc of 4 or less must be used
|
|
||||||
pub adc34: Option<AdcClockSource>,
|
|
||||||
#[cfg(stm32f334)]
|
#[cfg(stm32f334)]
|
||||||
pub hrtim: HrtimClockSource,
|
pub hrtim: HrtimClockSource,
|
||||||
|
|
||||||
pub ls: super::LsConfig,
|
pub ls: super::LsConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Information required to setup the PLL clock
|
impl Default for Config {
|
||||||
#[derive(Clone, Copy)]
|
fn default() -> Self {
|
||||||
struct PllConfig {
|
Self {
|
||||||
pll_src: Pllsrc,
|
hsi: true,
|
||||||
pll_mul: Pllmul,
|
hse: None,
|
||||||
pll_div: Option<Prediv>,
|
sys: Sysclk::HSI,
|
||||||
|
pll: None,
|
||||||
|
ahb_pre: AHBPrescaler::DIV1,
|
||||||
|
apb1_pre: APBPrescaler::DIV1,
|
||||||
|
apb2_pre: APBPrescaler::DIV1,
|
||||||
|
ls: Default::default(),
|
||||||
|
|
||||||
|
#[cfg(not(rcc_f37))]
|
||||||
|
adc: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
|
||||||
|
#[cfg(all(not(rcc_f37), adc3_common))]
|
||||||
|
adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
|
||||||
|
#[cfg(stm32f334)]
|
||||||
|
hrtim: HrtimClockSource::BusClk,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize and Set the clock frequencies
|
/// Initialize and Set the clock frequencies
|
||||||
pub(crate) unsafe fn init(config: Config) {
|
pub(crate) unsafe fn init(config: Config) {
|
||||||
// Calculate the real System clock, and PLL configuration if applicable
|
// Configure HSI
|
||||||
let (sysclk, pll_config) = get_sysclk(&config);
|
let hsi = match config.hsi {
|
||||||
assert!(sysclk.0 <= 72_000_000);
|
false => {
|
||||||
|
RCC.cr().modify(|w| w.set_hsion(false));
|
||||||
// Calculate real AHB clock
|
None
|
||||||
let hclk = config.hclk.map(|h| h).unwrap_or(sysclk);
|
}
|
||||||
let hpre = match sysclk.0 / hclk.0 {
|
true => {
|
||||||
0 => unreachable!(),
|
RCC.cr().modify(|w| w.set_hsion(true));
|
||||||
1 => Hpre::DIV1,
|
while !RCC.cr().read().hsirdy() {}
|
||||||
2 => Hpre::DIV2,
|
Some(HSI_FREQ)
|
||||||
3..=5 => Hpre::DIV4,
|
}
|
||||||
6..=11 => Hpre::DIV8,
|
|
||||||
12..=39 => Hpre::DIV16,
|
|
||||||
40..=95 => Hpre::DIV64,
|
|
||||||
96..=191 => Hpre::DIV128,
|
|
||||||
192..=383 => Hpre::DIV256,
|
|
||||||
_ => Hpre::DIV512,
|
|
||||||
};
|
};
|
||||||
let hclk = sysclk / hpre;
|
|
||||||
assert!(hclk <= Hertz(72_000_000));
|
|
||||||
|
|
||||||
// Calculate real APB1 clock
|
// Configure HSE
|
||||||
let pclk1 = config.pclk1.unwrap_or(hclk);
|
let hse = match config.hse {
|
||||||
let ppre1 = match hclk / pclk1 {
|
None => {
|
||||||
0 => unreachable!(),
|
RCC.cr().modify(|w| w.set_hseon(false));
|
||||||
1 => Ppre::DIV1,
|
None
|
||||||
2 => Ppre::DIV2,
|
}
|
||||||
3..=5 => Ppre::DIV4,
|
Some(hse) => {
|
||||||
6..=11 => Ppre::DIV8,
|
match hse.mode {
|
||||||
_ => Ppre::DIV16,
|
HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)),
|
||||||
};
|
HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)),
|
||||||
let timer_mul1 = if ppre1 == Ppre::DIV1 { 1u32 } else { 2 };
|
}
|
||||||
let pclk1 = hclk / ppre1;
|
|
||||||
assert!(pclk1 <= Hertz(36_000_000));
|
|
||||||
|
|
||||||
// Calculate real APB2 clock
|
RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator));
|
||||||
let pclk2 = config.pclk2.unwrap_or(hclk);
|
RCC.cr().modify(|w| w.set_hseon(true));
|
||||||
let ppre2 = match hclk / pclk2 {
|
while !RCC.cr().read().hserdy() {}
|
||||||
0 => unreachable!(),
|
Some(hse.freq)
|
||||||
1 => Ppre::DIV1,
|
}
|
||||||
2 => Ppre::DIV2,
|
|
||||||
3..=5 => Ppre::DIV4,
|
|
||||||
6..=11 => Ppre::DIV8,
|
|
||||||
_ => Ppre::DIV16,
|
|
||||||
};
|
};
|
||||||
let timer_mul2 = if ppre2 == Ppre::DIV1 { 1u32 } else { 2 };
|
|
||||||
let pclk2 = hclk / ppre2;
|
// Enable PLL
|
||||||
assert!(pclk2 <= Hertz(72_000_000));
|
// RM0316: "Reserved, must be kept at reset value."
|
||||||
|
let pll = config.pll.map(|pll| {
|
||||||
|
let (src_val, src_freq) = match pll.src {
|
||||||
|
#[cfg(rcc_f3v3)]
|
||||||
|
PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)),
|
||||||
|
#[cfg(not(rcc_f3v3))]
|
||||||
|
PllSource::HSI => {
|
||||||
|
if pll.prediv != PllPreDiv::DIV2 {
|
||||||
|
panic!("if PLL source is HSI, PLL prediv must be 2.");
|
||||||
|
}
|
||||||
|
(Pllsrc::HSI_DIV2, unwrap!(hsi))
|
||||||
|
}
|
||||||
|
PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)),
|
||||||
|
};
|
||||||
|
let in_freq = src_freq / pll.prediv;
|
||||||
|
assert!(max::PLL_IN.contains(&in_freq));
|
||||||
|
let out_freq = in_freq * pll.mul;
|
||||||
|
assert!(max::PLL_OUT.contains(&out_freq));
|
||||||
|
|
||||||
|
RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv));
|
||||||
|
RCC.cfgr().modify(|w| {
|
||||||
|
w.set_pllmul(pll.mul);
|
||||||
|
w.set_pllsrc(src_val);
|
||||||
|
});
|
||||||
|
RCC.cr().modify(|w| w.set_pllon(true));
|
||||||
|
while !RCC.cr().read().pllrdy() {}
|
||||||
|
|
||||||
|
out_freq
|
||||||
|
});
|
||||||
|
|
||||||
|
let usb = match pll {
|
||||||
|
Some(Hertz(72_000_000)) => {
|
||||||
|
RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1_5));
|
||||||
|
Some(Hertz(48_000_000))
|
||||||
|
}
|
||||||
|
Some(Hertz(48_000_000)) => {
|
||||||
|
RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1));
|
||||||
|
Some(Hertz(48_000_000))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configure sysclk
|
||||||
|
let sys = match config.sys {
|
||||||
|
Sysclk::HSI => unwrap!(hsi),
|
||||||
|
Sysclk::HSE => unwrap!(hse),
|
||||||
|
Sysclk::PLL1_P => unwrap!(pll),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let hclk = sys / config.ahb_pre;
|
||||||
|
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
|
||||||
|
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
|
||||||
|
|
||||||
|
assert!(max::HCLK.contains(&hclk));
|
||||||
|
assert!(max::PCLK1.contains(&pclk1));
|
||||||
|
assert!(max::PCLK2.contains(&pclk2));
|
||||||
|
|
||||||
// Set latency based on HCLK frquency
|
// Set latency based on HCLK frquency
|
||||||
// RM0316: "The prefetch buffer must be kept on when using a prescaler
|
let latency = match hclk.0 {
|
||||||
// different from 1 on the AHB clock.", "Half-cycle access cannot be
|
..=24_000_000 => Latency::WS0,
|
||||||
// used when there is a prescaler different from 1 on the AHB clock"
|
..=48_000_000 => Latency::WS1,
|
||||||
|
_ => Latency::WS2,
|
||||||
|
};
|
||||||
FLASH.acr().modify(|w| {
|
FLASH.acr().modify(|w| {
|
||||||
w.set_latency(if hclk <= Hertz(24_000_000) {
|
w.set_latency(latency);
|
||||||
Latency::WS0
|
// RM0316: "The prefetch buffer must be kept on when using a prescaler
|
||||||
} else if hclk <= Hertz(48_000_000) {
|
// different from 1 on the AHB clock.", "Half-cycle access cannot be
|
||||||
Latency::WS1
|
// used when there is a prescaler different from 1 on the AHB clock"
|
||||||
} else {
|
if config.ahb_pre != AHBPrescaler::DIV1 {
|
||||||
Latency::WS2
|
|
||||||
});
|
|
||||||
if hpre != Hpre::DIV1 {
|
|
||||||
w.set_hlfcya(false);
|
w.set_hlfcya(false);
|
||||||
w.set_prftbe(true);
|
w.set_prftbe(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Enable HSE
|
|
||||||
// RM0316: "Bits 31:26 Reserved, must be kept at reset value."
|
|
||||||
if config.hse.is_some() {
|
|
||||||
RCC.cr().modify(|w| {
|
|
||||||
w.set_hsebyp(config.bypass_hse);
|
|
||||||
// We turn on clock security to switch to HSI when HSE fails
|
|
||||||
w.set_csson(true);
|
|
||||||
w.set_hseon(true);
|
|
||||||
});
|
|
||||||
while !RCC.cr().read().hserdy() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enable PLL
|
|
||||||
// RM0316: "Reserved, must be kept at reset value."
|
|
||||||
if let Some(ref pll_config) = pll_config {
|
|
||||||
RCC.cfgr().modify(|w| {
|
|
||||||
w.set_pllmul(pll_config.pll_mul);
|
|
||||||
w.set_pllsrc(pll_config.pll_src);
|
|
||||||
});
|
|
||||||
if let Some(pll_div) = pll_config.pll_div {
|
|
||||||
RCC.cfgr2().modify(|w| w.set_prediv(pll_div));
|
|
||||||
}
|
|
||||||
RCC.cr().modify(|w| w.set_pllon(true));
|
|
||||||
while !RCC.cr().read().pllrdy() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CFGR has been written before (PLL) don't overwrite these settings
|
|
||||||
if config.pll48 {
|
|
||||||
let usb_pre = get_usb_pre(&config, sysclk, pclk1, &pll_config);
|
|
||||||
RCC.cfgr().modify(|w| {
|
|
||||||
w.set_usbpre(usb_pre);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set prescalers
|
// Set prescalers
|
||||||
// CFGR has been written before (PLL, PLL48) don't overwrite these settings
|
// CFGR has been written before (PLL, PLL48) don't overwrite these settings
|
||||||
RCC.cfgr().modify(|w| {
|
RCC.cfgr().modify(|w| {
|
||||||
w.set_ppre2(ppre2);
|
w.set_ppre2(config.apb1_pre);
|
||||||
w.set_ppre1(ppre1);
|
w.set_ppre1(config.apb2_pre);
|
||||||
w.set_hpre(hpre);
|
w.set_hpre(config.ahb_pre);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Wait for the new prescalers to kick in
|
// Wait for the new prescalers to kick in
|
||||||
|
@ -211,53 +233,60 @@ pub(crate) unsafe fn init(config: Config) {
|
||||||
cortex_m::asm::delay(16);
|
cortex_m::asm::delay(16);
|
||||||
|
|
||||||
// CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings
|
// CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings
|
||||||
RCC.cfgr().modify(|w| {
|
RCC.cfgr().modify(|w| w.set_sw(config.sys));
|
||||||
w.set_sw(match (pll_config, config.hse) {
|
|
||||||
(Some(_), _) => Sw::PLL1_P,
|
|
||||||
(None, Some(_)) => Sw::HSE,
|
|
||||||
(None, None) => Sw::HSI,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
#[cfg(rcc_f3)]
|
let rtc = config.ls.init();
|
||||||
let adc = config.adc.map(|adc| match adc {
|
|
||||||
|
#[cfg(not(rcc_f37))]
|
||||||
|
use crate::pac::adccommon::vals::Ckmode;
|
||||||
|
|
||||||
|
#[cfg(not(rcc_f37))]
|
||||||
|
let adc = match config.adc {
|
||||||
AdcClockSource::Pll(adcpres) => {
|
AdcClockSource::Pll(adcpres) => {
|
||||||
RCC.cfgr2().modify(|w| {
|
RCC.cfgr2().modify(|w| w.set_adc12pres(adcpres));
|
||||||
// Make sure that we're using the PLL
|
crate::pac::ADC_COMMON
|
||||||
pll_config.unwrap();
|
.ccr()
|
||||||
w.set_adc12pres(adcpres);
|
.modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
|
||||||
|
|
||||||
sysclk / adcpres
|
unwrap!(pll) / adcpres
|
||||||
})
|
|
||||||
}
|
}
|
||||||
_ => crate::pac::ADC_COMMON.ccr().modify(|w| {
|
AdcClockSource::Hclk(adcpres) => {
|
||||||
assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
|
assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
|
||||||
|
|
||||||
w.set_ckmode(adc.into());
|
let (div, ckmode) = match adcpres {
|
||||||
|
AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
|
||||||
|
AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
|
||||||
|
AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
|
||||||
|
};
|
||||||
|
crate::pac::ADC_COMMON.ccr().modify(|w| w.set_ckmode(ckmode));
|
||||||
|
|
||||||
sysclk / adc.bus_div()
|
hclk / div
|
||||||
}),
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
#[cfg(all(rcc_f3, adc3_common))]
|
#[cfg(all(not(rcc_f37), adc3_common))]
|
||||||
let adc34 = config.adc34.map(|adc| match adc {
|
let adc34 = match config.adc34 {
|
||||||
AdcClockSource::Pll(adcpres) => {
|
AdcClockSource::Pll(adcpres) => {
|
||||||
RCC.cfgr2().modify(|w| {
|
RCC.cfgr2().modify(|w| w.set_adc34pres(adcpres));
|
||||||
// Make sure that we're using the PLL
|
crate::pac::ADC3_COMMON
|
||||||
pll_config.unwrap();
|
.ccr()
|
||||||
w.set_adc34pres(adcpres);
|
.modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
|
||||||
|
|
||||||
sysclk / adcpres
|
unwrap!(pll) / adcpres
|
||||||
})
|
|
||||||
}
|
}
|
||||||
_ => crate::pac::ADC_COMMON.ccr().modify(|w| {
|
AdcClockSource::Hclk(adcpres) => {
|
||||||
assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
|
assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
|
||||||
|
|
||||||
w.set_ckmode(adc.into());
|
let (div, ckmode) = match adcpres {
|
||||||
|
AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
|
||||||
|
AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
|
||||||
|
AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
|
||||||
|
};
|
||||||
|
crate::pac::ADC3_COMMON.ccr().modify(|w| w.set_ckmode(ckmode));
|
||||||
|
|
||||||
sysclk / adc.bus_div()
|
hclk / div
|
||||||
}),
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
#[cfg(stm32f334)]
|
#[cfg(stm32f334)]
|
||||||
let hrtim = match config.hrtim {
|
let hrtim = match config.hrtim {
|
||||||
|
@ -267,195 +296,49 @@ pub(crate) unsafe fn init(config: Config) {
|
||||||
use crate::pac::rcc::vals::Timsw;
|
use crate::pac::rcc::vals::Timsw;
|
||||||
|
|
||||||
// Make sure that we're using the PLL
|
// Make sure that we're using the PLL
|
||||||
pll_config.unwrap();
|
let pll = unwrap!(pll);
|
||||||
assert!((pclk2 == sysclk) || (pclk2 * 2u32 == sysclk));
|
assert!((pclk2 == pll) || (pclk2 * 2u32 == pll));
|
||||||
|
|
||||||
RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL1_P));
|
RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL1_P));
|
||||||
|
|
||||||
Some(sysclk * 2u32)
|
Some(pll * 2u32)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let rtc = config.ls.init();
|
|
||||||
|
|
||||||
set_clocks!(
|
set_clocks!(
|
||||||
hsi: None,
|
hsi: hsi,
|
||||||
lse: None,
|
hse: hse,
|
||||||
pll1_p: None,
|
pll1_p: pll,
|
||||||
sys: Some(sysclk),
|
sys: Some(sys),
|
||||||
pclk1: Some(pclk1),
|
pclk1: Some(pclk1),
|
||||||
pclk2: Some(pclk2),
|
pclk2: Some(pclk2),
|
||||||
pclk1_tim: Some(pclk1 * timer_mul1),
|
pclk1_tim: Some(pclk1_tim),
|
||||||
pclk2_tim: Some(pclk2 * timer_mul2),
|
pclk2_tim: Some(pclk2_tim),
|
||||||
hclk1: Some(hclk),
|
hclk1: Some(hclk),
|
||||||
#[cfg(rcc_f3)]
|
#[cfg(not(rcc_f37))]
|
||||||
adc: adc,
|
adc: Some(adc),
|
||||||
#[cfg(all(rcc_f3, adc3_common))]
|
#[cfg(all(not(rcc_f37), adc3_common))]
|
||||||
adc34: adc34,
|
adc34: Some(adc34),
|
||||||
#[cfg(all(rcc_f3, not(adc3_common)))]
|
|
||||||
adc34: None,
|
|
||||||
#[cfg(stm32f334)]
|
#[cfg(stm32f334)]
|
||||||
hrtim: hrtim,
|
hrtim: hrtim,
|
||||||
rtc: rtc,
|
rtc: rtc,
|
||||||
|
usb: usb,
|
||||||
|
lse: None,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
mod max {
|
||||||
fn get_sysclk(config: &Config) -> (Hertz, Option<PllConfig>) {
|
use core::ops::RangeInclusive;
|
||||||
match (config.sysclk, config.hse) {
|
|
||||||
(Some(sysclk), Some(hse)) if sysclk == hse => (hse, None),
|
|
||||||
(Some(sysclk), None) if sysclk == HSI_FREQ => (HSI_FREQ, None),
|
|
||||||
// If the user selected System clock is different from HSI or HSE
|
|
||||||
// we will have to setup PLL clock source
|
|
||||||
(Some(sysclk), _) => {
|
|
||||||
let (sysclk, pll_config) = calc_pll(config, sysclk);
|
|
||||||
(sysclk, Some(pll_config))
|
|
||||||
}
|
|
||||||
(None, Some(hse)) => (hse, None),
|
|
||||||
(None, None) => (HSI_FREQ, None),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
use crate::time::Hertz;
|
||||||
fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
|
|
||||||
// Calculates the Multiplier and the Divisor to arrive at
|
|
||||||
// the required System clock from PLL source frequency
|
|
||||||
let get_mul_div = |sysclk, pllsrcclk| {
|
|
||||||
let bus_div = gcd(sysclk, pllsrcclk);
|
|
||||||
let mut multiplier = sysclk / bus_div;
|
|
||||||
let mut divisor = pllsrcclk / bus_div;
|
|
||||||
// Minimum PLL multiplier is two
|
|
||||||
if multiplier == 1 {
|
|
||||||
multiplier *= 2;
|
|
||||||
divisor *= 2;
|
|
||||||
}
|
|
||||||
assert!(multiplier <= 16);
|
|
||||||
assert!(divisor <= 16);
|
|
||||||
(multiplier, divisor)
|
|
||||||
};
|
|
||||||
// Based on the source of Pll, we calculate the actual system clock
|
|
||||||
// frequency, PLL's source identifier, multiplier and divisor
|
|
||||||
let (act_sysclk, pll_src, pll_mul, pll_div) = match config.hse {
|
|
||||||
Some(Hertz(hse)) => {
|
|
||||||
let (multiplier, divisor) = get_mul_div(sysclk, hse);
|
|
||||||
(
|
|
||||||
Hertz((hse / divisor) * multiplier),
|
|
||||||
Pllsrc::HSE_DIV_PREDIV,
|
|
||||||
into_pll_mul(multiplier),
|
|
||||||
Some(into_pre_div(divisor)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
// For some chips PREDIV is always two, and cannot be changed
|
|
||||||
if #[cfg(any(flashsize_d, flashsize_e))] {
|
|
||||||
let (multiplier, divisor) = get_mul_div(sysclk, HSI_FREQ.0);
|
|
||||||
(
|
|
||||||
Hertz((HSI_FREQ.0 / divisor) * multiplier),
|
|
||||||
Pllsrc::HSI_DIV_PREDIV,
|
|
||||||
into_pll_mul(multiplier),
|
|
||||||
Some(into_pre_div(divisor)),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let pllsrcclk = HSI_FREQ.0 / 2;
|
|
||||||
let multiplier = sysclk / pllsrcclk;
|
|
||||||
assert!(multiplier <= 16);
|
|
||||||
(
|
|
||||||
Hertz(pllsrcclk * multiplier),
|
|
||||||
Pllsrc::HSI_DIV2,
|
|
||||||
into_pll_mul(multiplier),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
(
|
|
||||||
act_sysclk,
|
|
||||||
PllConfig {
|
|
||||||
pll_src,
|
|
||||||
pll_mul,
|
|
||||||
pll_div,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(32_000_000);
|
||||||
#[allow(unused_variables)]
|
pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(32_000_000);
|
||||||
fn get_usb_pre(config: &Config, sysclk: Hertz, pclk1: Hertz, pll_config: &Option<PllConfig>) -> Usbpre {
|
|
||||||
cfg_if::cfg_if! {
|
|
||||||
// Some chips do not have USB
|
|
||||||
if #[cfg(any(stm32f301, stm32f318, stm32f334))] {
|
|
||||||
panic!("USB clock not supported by the chip");
|
|
||||||
} else {
|
|
||||||
let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= Hertz(10_000_000));
|
|
||||||
match (usb_ok, sysclk) {
|
|
||||||
(true, Hertz(72_000_000)) => Usbpre::DIV1_5,
|
|
||||||
(true, Hertz(48_000_000)) => Usbpre::DIV1,
|
|
||||||
_ => panic!(
|
|
||||||
"USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz"
|
|
||||||
),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function assumes cases when multiplier is one and it
|
pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000);
|
||||||
// being greater than 16 is made impossible
|
pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(36_000_000);
|
||||||
#[inline]
|
pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000);
|
||||||
fn into_pll_mul(multiplier: u32) -> Pllmul {
|
|
||||||
match multiplier {
|
|
||||||
2 => Pllmul::MUL2,
|
|
||||||
3 => Pllmul::MUL3,
|
|
||||||
4 => Pllmul::MUL4,
|
|
||||||
5 => Pllmul::MUL5,
|
|
||||||
6 => Pllmul::MUL6,
|
|
||||||
7 => Pllmul::MUL7,
|
|
||||||
8 => Pllmul::MUL8,
|
|
||||||
9 => Pllmul::MUL9,
|
|
||||||
10 => Pllmul::MUL10,
|
|
||||||
11 => Pllmul::MUL11,
|
|
||||||
12 => Pllmul::MUL12,
|
|
||||||
13 => Pllmul::MUL13,
|
|
||||||
14 => Pllmul::MUL14,
|
|
||||||
15 => Pllmul::MUL15,
|
|
||||||
16 => Pllmul::MUL16,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function assumes the incoming divisor cannot be greater
|
pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(24_000_000);
|
||||||
// than 16
|
pub(crate) const PLL_OUT: RangeInclusive<Hertz> = Hertz(16_000_000)..=Hertz(72_000_000);
|
||||||
#[inline]
|
|
||||||
fn into_pre_div(divisor: u32) -> Prediv {
|
|
||||||
match divisor {
|
|
||||||
1 => Prediv::DIV1,
|
|
||||||
2 => Prediv::DIV2,
|
|
||||||
3 => Prediv::DIV3,
|
|
||||||
4 => Prediv::DIV4,
|
|
||||||
5 => Prediv::DIV5,
|
|
||||||
6 => Prediv::DIV6,
|
|
||||||
7 => Prediv::DIV7,
|
|
||||||
8 => Prediv::DIV8,
|
|
||||||
9 => Prediv::DIV9,
|
|
||||||
10 => Prediv::DIV10,
|
|
||||||
11 => Prediv::DIV11,
|
|
||||||
12 => Prediv::DIV12,
|
|
||||||
13 => Prediv::DIV13,
|
|
||||||
14 => Prediv::DIV14,
|
|
||||||
15 => Prediv::DIV15,
|
|
||||||
16 => Prediv::DIV16,
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine GCD using Euclidean algorithm
|
|
||||||
#[inline]
|
|
||||||
fn gcd(mut a: u32, mut b: u32) -> u32 {
|
|
||||||
while b != 0 {
|
|
||||||
let r = a % b;
|
|
||||||
a = b;
|
|
||||||
b = r;
|
|
||||||
}
|
|
||||||
a
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use embassy_hal_internal::into_ref;
|
||||||
|
|
||||||
use crate::gpio::sealed::AFType;
|
use crate::gpio::sealed::AFType;
|
||||||
use crate::gpio::Speed;
|
use crate::gpio::Speed;
|
||||||
#[cfg(not(stm32f1))]
|
#[cfg(not(any(stm32f1, rcc_f3v1, rcc_f37)))]
|
||||||
pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
|
pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
|
||||||
#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))]
|
#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))]
|
||||||
pub use crate::pac::rcc::vals::Mcosel as McoSource;
|
pub use crate::pac::rcc::vals::Mcosel as McoSource;
|
||||||
|
@ -13,10 +13,16 @@ pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source};
|
||||||
use crate::pac::RCC;
|
use crate::pac::RCC;
|
||||||
use crate::{peripherals, Peripheral};
|
use crate::{peripherals, Peripheral};
|
||||||
|
|
||||||
|
#[cfg(any(stm32f1, rcc_f3v1, rcc_f37))]
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
pub enum McoPrescaler {
|
||||||
|
DIV1,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
pub trait McoInstance {
|
pub trait McoInstance {
|
||||||
type Source;
|
type Source;
|
||||||
unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: super::McoPrescaler);
|
unsafe fn apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +35,7 @@ macro_rules! impl_peri {
|
||||||
impl sealed::McoInstance for peripherals::$peri {
|
impl sealed::McoInstance for peripherals::$peri {
|
||||||
type Source = $source;
|
type Source = $source;
|
||||||
|
|
||||||
unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: McoPrescaler) {
|
unsafe fn apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) {
|
||||||
#[cfg(not(any(stm32u5, stm32wba)))]
|
#[cfg(not(any(stm32u5, stm32wba)))]
|
||||||
let r = RCC.cfgr();
|
let r = RCC.cfgr();
|
||||||
#[cfg(any(stm32u5, stm32wba))]
|
#[cfg(any(stm32u5, stm32wba))]
|
||||||
|
@ -37,8 +43,8 @@ macro_rules! impl_peri {
|
||||||
|
|
||||||
r.modify(|w| {
|
r.modify(|w| {
|
||||||
w.$set_source(source);
|
w.$set_source(source);
|
||||||
#[cfg(not(stm32f1))]
|
#[cfg(not(any(stm32f1, rcc_f3v1, rcc_f37)))]
|
||||||
w.$set_prescaler(prescaler);
|
w.$set_prescaler(_prescaler);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,16 +74,12 @@ impl<'d, T: McoInstance> Mco<'d, T> {
|
||||||
_peri: impl Peripheral<P = T> + 'd,
|
_peri: impl Peripheral<P = T> + 'd,
|
||||||
pin: impl Peripheral<P = impl McoPin<T>> + 'd,
|
pin: impl Peripheral<P = impl McoPin<T>> + 'd,
|
||||||
source: T::Source,
|
source: T::Source,
|
||||||
#[cfg(not(stm32f1))] prescaler: McoPrescaler,
|
prescaler: McoPrescaler,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
|
|
||||||
critical_section::with(|_| unsafe {
|
critical_section::with(|_| unsafe {
|
||||||
T::apply_clock_settings(
|
T::apply_clock_settings(source, prescaler);
|
||||||
source,
|
|
||||||
#[cfg(not(stm32f1))]
|
|
||||||
prescaler,
|
|
||||||
);
|
|
||||||
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
|
pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
|
||||||
pin.set_speed(Speed::VeryHigh);
|
pin.set_speed(Speed::VeryHigh);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,16 +3,13 @@
|
||||||
|
|
||||||
use defmt::info;
|
use defmt::info;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::Hertz;
|
|
||||||
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 _};
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut config = Config::default();
|
let config = Config::default();
|
||||||
config.rcc.hse = Some(Hertz(8_000_000));
|
|
||||||
config.rcc.sysclk = Some(Hertz(16_000_000));
|
|
||||||
let _p = embassy_stm32::init(config);
|
let _p = embassy_stm32::init(config);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -21,11 +21,22 @@ bind_interrupts!(struct Irqs {
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.hse = Some(mhz(8));
|
{
|
||||||
config.rcc.sysclk = Some(mhz(48));
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.pclk1 = Some(mhz(24));
|
config.rcc.hse = Some(Hse {
|
||||||
config.rcc.pclk2 = Some(mhz(24));
|
freq: mhz(8),
|
||||||
config.rcc.pll48 = true;
|
mode: HseMode::Bypass,
|
||||||
|
});
|
||||||
|
config.rcc.pll = Some(Pll {
|
||||||
|
src: PllSource::HSE,
|
||||||
|
prediv: PllPreDiv::DIV1,
|
||||||
|
mul: PllMul::MUL9,
|
||||||
|
});
|
||||||
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.ahb_pre = AHBPrescaler::DIV1;
|
||||||
|
config.rcc.apb1_pre = APBPrescaler::DIV2;
|
||||||
|
config.rcc.apb2_pre = APBPrescaler::DIV1;
|
||||||
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
|
@ -5,7 +5,6 @@ use defmt::info;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::adc::{Adc, SampleTime};
|
use embassy_stm32::adc::{Adc, SampleTime};
|
||||||
use embassy_stm32::peripherals::ADC1;
|
use embassy_stm32::peripherals::ADC1;
|
||||||
use embassy_stm32::rcc::{AdcClockSource, Adcpres};
|
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{adc, bind_interrupts, Config};
|
use embassy_stm32::{adc, bind_interrupts, Config};
|
||||||
use embassy_time::{Delay, Timer};
|
use embassy_time::{Delay, Timer};
|
||||||
|
@ -18,12 +17,23 @@ bind_interrupts!(struct Irqs {
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.sysclk = Some(mhz(64));
|
{
|
||||||
config.rcc.hclk = Some(mhz(64));
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.pclk1 = Some(mhz(32));
|
config.rcc.hse = Some(Hse {
|
||||||
config.rcc.pclk2 = Some(mhz(64));
|
freq: mhz(8),
|
||||||
config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1));
|
mode: HseMode::Bypass,
|
||||||
|
});
|
||||||
|
config.rcc.pll = Some(Pll {
|
||||||
|
src: PllSource::HSE,
|
||||||
|
prediv: PllPreDiv::DIV1,
|
||||||
|
mul: PllMul::MUL9,
|
||||||
|
});
|
||||||
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.ahb_pre = AHBPrescaler::DIV1;
|
||||||
|
config.rcc.apb1_pre = APBPrescaler::DIV2;
|
||||||
|
config.rcc.apb2_pre = APBPrescaler::DIV1;
|
||||||
|
config.rcc.adc = AdcClockSource::Pll(AdcPllPrescaler::DIV1);
|
||||||
|
}
|
||||||
let mut p = embassy_stm32::init(config);
|
let mut p = embassy_stm32::init(config);
|
||||||
|
|
||||||
info!("create adc...");
|
info!("create adc...");
|
||||||
|
|
|
@ -3,16 +3,13 @@
|
||||||
|
|
||||||
use defmt::info;
|
use defmt::info;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::time::Hertz;
|
|
||||||
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 _};
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut config = Config::default();
|
let config = Config::default();
|
||||||
config.rcc.hse = Some(Hertz(8_000_000));
|
|
||||||
config.rcc.sysclk = Some(Hertz(16_000_000));
|
|
||||||
let _p = embassy_stm32::init(config);
|
let _p = embassy_stm32::init(config);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -6,7 +6,6 @@ use embassy_executor::Spawner;
|
||||||
use embassy_stm32::adc::{Adc, SampleTime};
|
use embassy_stm32::adc::{Adc, SampleTime};
|
||||||
use embassy_stm32::opamp::{OpAmp, OpAmpGain};
|
use embassy_stm32::opamp::{OpAmp, OpAmpGain};
|
||||||
use embassy_stm32::peripherals::ADC2;
|
use embassy_stm32::peripherals::ADC2;
|
||||||
use embassy_stm32::rcc::{AdcClockSource, Adcpres};
|
|
||||||
use embassy_stm32::time::mhz;
|
use embassy_stm32::time::mhz;
|
||||||
use embassy_stm32::{adc, bind_interrupts, Config};
|
use embassy_stm32::{adc, bind_interrupts, Config};
|
||||||
use embassy_time::{Delay, Timer};
|
use embassy_time::{Delay, Timer};
|
||||||
|
@ -19,12 +18,23 @@ bind_interrupts!(struct Irqs {
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.rcc.sysclk = Some(mhz(64));
|
{
|
||||||
config.rcc.hclk = Some(mhz(64));
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.pclk1 = Some(mhz(32));
|
config.rcc.hse = Some(Hse {
|
||||||
config.rcc.pclk2 = Some(mhz(64));
|
freq: mhz(8),
|
||||||
config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1));
|
mode: HseMode::Bypass,
|
||||||
|
});
|
||||||
|
config.rcc.pll = Some(Pll {
|
||||||
|
src: PllSource::HSE,
|
||||||
|
prediv: PllPreDiv::DIV1,
|
||||||
|
mul: PllMul::MUL9,
|
||||||
|
});
|
||||||
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.ahb_pre = AHBPrescaler::DIV1;
|
||||||
|
config.rcc.apb1_pre = APBPrescaler::DIV2;
|
||||||
|
config.rcc.apb2_pre = APBPrescaler::DIV1;
|
||||||
|
config.rcc.adc = AdcClockSource::Pll(AdcPllPrescaler::DIV1);
|
||||||
|
}
|
||||||
let mut p = embassy_stm32::init(config);
|
let mut p = embassy_stm32::init(config);
|
||||||
|
|
||||||
info!("create adc...");
|
info!("create adc...");
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::hrtim::*;
|
use embassy_stm32::hrtim::*;
|
||||||
use embassy_stm32::rcc::HrtimClockSource;
|
|
||||||
use embassy_stm32::time::{khz, mhz};
|
use embassy_stm32::time::{khz, mhz};
|
||||||
use embassy_stm32::Config;
|
use embassy_stm32::Config;
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
|
@ -12,14 +11,26 @@ use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let mut config: Config = Default::default();
|
let mut config = Config::default();
|
||||||
config.rcc.sysclk = Some(mhz(64));
|
{
|
||||||
config.rcc.hclk = Some(mhz(64));
|
use embassy_stm32::rcc::*;
|
||||||
config.rcc.pclk1 = Some(mhz(32));
|
config.rcc.hse = Some(Hse {
|
||||||
config.rcc.pclk2 = Some(mhz(64));
|
freq: mhz(8),
|
||||||
config.rcc.hrtim = HrtimClockSource::PllClk;
|
mode: HseMode::Bypass,
|
||||||
|
});
|
||||||
|
config.rcc.pll = Some(Pll {
|
||||||
|
src: PllSource::HSE,
|
||||||
|
prediv: PllPreDiv::DIV1,
|
||||||
|
mul: PllMul::MUL9,
|
||||||
|
});
|
||||||
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.ahb_pre = AHBPrescaler::DIV1;
|
||||||
|
config.rcc.apb1_pre = APBPrescaler::DIV2;
|
||||||
|
config.rcc.apb2_pre = APBPrescaler::DIV1;
|
||||||
|
config.rcc.hrtim = HrtimClockSource::PllClk;
|
||||||
|
}
|
||||||
let p = embassy_stm32::init(config);
|
let p = embassy_stm32::init(config);
|
||||||
|
|
||||||
info!("Hello World!");
|
info!("Hello World!");
|
||||||
|
|
||||||
let ch1 = PwmPin::new_cha(p.PA8);
|
let ch1 = PwmPin::new_cha(p.PA8);
|
||||||
|
|
|
@ -276,6 +276,24 @@ pub fn config() -> Config {
|
||||||
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
config.rcc.apb2_pre = APBPrescaler::DIV2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "stm32f303ze")]
|
||||||
|
{
|
||||||
|
use embassy_stm32::rcc::*;
|
||||||
|
config.rcc.hse = Some(Hse {
|
||||||
|
freq: Hertz(8_000_000),
|
||||||
|
mode: HseMode::Bypass,
|
||||||
|
});
|
||||||
|
config.rcc.pll = Some(Pll {
|
||||||
|
src: PllSource::HSE,
|
||||||
|
prediv: PllPreDiv::DIV1,
|
||||||
|
mul: PllMul::MUL9,
|
||||||
|
});
|
||||||
|
config.rcc.sys = Sysclk::PLL1_P;
|
||||||
|
config.rcc.ahb_pre = AHBPrescaler::DIV1;
|
||||||
|
config.rcc.apb1_pre = APBPrescaler::DIV2;
|
||||||
|
config.rcc.apb2_pre = APBPrescaler::DIV1;
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "stm32f429zi")]
|
#[cfg(feature = "stm32f429zi")]
|
||||||
{
|
{
|
||||||
use embassy_stm32::rcc::*;
|
use embassy_stm32::rcc::*;
|
||||||
|
|
Loading…
Reference in a new issue