Alexandros Liarokapis 2b7e76efe9 Fix dma nvic issues on dual core lines
This commit addresses #3256 by disabling dma NVIC interrupt enablement at startup.
Instead, per-channel NVIC interrupt enablement is now done with the rest of the dma channel configuration.
This ensures that each core will only handle the interrupts of the DMA channels that it uses.
2024-08-17 16:54:41 +03:00

177 lines
4.5 KiB
Rust

pub use crate::pac::pwr::vals::Vos as VoltageScale;
use crate::pac::rcc::regs::Cfgr1;
pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsepre as HsePrescaler, Ppre as APBPrescaler, Sw as Sysclk};
use crate::pac::{FLASH, RCC};
use crate::time::Hertz;
/// HSI speed
pub const HSI_FREQ: Hertz = Hertz(16_000_000);
// HSE speed
pub const HSE_FREQ: Hertz = Hertz(32_000_000);
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Hse {
pub prescaler: HsePrescaler,
}
/// Clocks configuration
#[derive(Clone, Copy)]
pub struct Config {
// base clock sources
pub hsi: bool,
pub hse: Option<Hse>,
// sysclk, buses.
pub sys: Sysclk,
pub ahb_pre: AHBPrescaler,
pub apb1_pre: APBPrescaler,
pub apb2_pre: APBPrescaler,
pub apb7_pre: APBPrescaler,
// low speed LSI/LSE/RTC
pub ls: super::LsConfig,
pub voltage_scale: VoltageScale,
/// Per-peripheral kernel clock selection muxes
pub mux: super::mux::ClockMux,
}
impl Default for Config {
#[inline]
fn default() -> Config {
Config {
hse: None,
hsi: true,
sys: Sysclk::HSI,
ahb_pre: AHBPrescaler::DIV1,
apb1_pre: APBPrescaler::DIV1,
apb2_pre: APBPrescaler::DIV1,
apb7_pre: APBPrescaler::DIV1,
ls: Default::default(),
voltage_scale: VoltageScale::RANGE2,
mux: Default::default(),
}
}
}
fn hsi_enable() {
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
}
pub(crate) unsafe fn init(config: Config) {
// Switch to HSI to prevent problems with PLL configuration.
if !RCC.cr().read().hsion() {
hsi_enable()
}
if RCC.cfgr1().read().sws() != Sysclk::HSI {
// Set HSI as a clock source, reset prescalers.
RCC.cfgr1().write_value(Cfgr1::default());
// Wait for clock switch status bits to change.
while RCC.cfgr1().read().sws() != Sysclk::HSI {}
}
// Set voltage scale
crate::pac::PWR.vosr().write(|w| w.set_vos(config.voltage_scale));
while !crate::pac::PWR.vosr().read().vosrdy() {}
let rtc = config.ls.init();
let hsi = config.hsi.then(|| {
hsi_enable();
HSI_FREQ
});
let hse = config.hse.map(|hse| {
RCC.cr().write(|w| {
w.set_hseon(true);
w.set_hsepre(hse.prescaler);
});
while !RCC.cr().read().hserdy() {}
HSE_FREQ
});
let sys_clk = match config.sys {
Sysclk::HSE => hse.unwrap(),
Sysclk::HSI => hsi.unwrap(),
Sysclk::_RESERVED_1 => unreachable!(),
Sysclk::PLL1_R => todo!(),
};
assert!(sys_clk.0 <= 100_000_000);
let hclk1 = sys_clk / config.ahb_pre;
let hclk2 = hclk1;
let hclk4 = hclk1;
// TODO: hclk5
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
let (pclk7, _) = super::util::calc_pclk(hclk1, config.apb7_pre);
// Set flash wait states
let flash_latency = match config.voltage_scale {
VoltageScale::RANGE1 => match sys_clk.0 {
..=32_000_000 => 0,
..=64_000_000 => 1,
..=96_000_000 => 2,
..=100_000_000 => 3,
_ => 4,
},
VoltageScale::RANGE2 => match sys_clk.0 {
..=8_000_000 => 0,
..=16_000_000 => 1,
_ => 2,
},
};
FLASH.acr().modify(|w| w.set_latency(flash_latency));
while FLASH.acr().read().latency() != flash_latency {}
// Set sram wait states
let _sram_latency = match config.voltage_scale {
VoltageScale::RANGE1 => 0,
VoltageScale::RANGE2 => match sys_clk.0 {
..=12_000_000 => 0,
..=16_000_000 => 1,
_ => 2,
},
};
// TODO: Set the SRAM wait states
RCC.cfgr1().modify(|w| {
w.set_sw(config.sys);
});
while RCC.cfgr1().read().sws() != config.sys {}
RCC.cfgr2().modify(|w| {
w.set_hpre(config.ahb_pre);
w.set_ppre1(config.apb1_pre);
w.set_ppre2(config.apb2_pre);
});
config.mux.init();
set_clocks!(
sys: Some(sys_clk),
hclk1: Some(hclk1),
hclk2: Some(hclk2),
hclk4: Some(hclk4),
pclk1: Some(pclk1),
pclk2: Some(pclk2),
pclk7: Some(pclk7),
pclk1_tim: Some(pclk1_tim),
pclk2_tim: Some(pclk2_tim),
rtc: rtc,
hse: hse,
hsi: hsi,
// TODO
lse: None,
lsi: None,
pll1_q: None,
);
}