Merge pull request #254 from thalesfragoso/f0-rcc

F0 rcc
This commit is contained in:
Thales 2021-06-24 20:39:51 -03:00 committed by GitHub
commit e1880a19df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 428 additions and 113 deletions

View file

@ -45,6 +45,79 @@ net = ["embassy-net", "vcell"]
# BEGIN GENERATED FEATURES
# Generated by gen_features.py. DO NOT EDIT.
stm32f030c6 = [ "stm32-metapac/stm32f030c6",]
stm32f030c8 = [ "stm32-metapac/stm32f030c8",]
stm32f030cc = [ "stm32-metapac/stm32f030cc",]
stm32f030f4 = [ "stm32-metapac/stm32f030f4",]
stm32f030k6 = [ "stm32-metapac/stm32f030k6",]
stm32f030r8 = [ "stm32-metapac/stm32f030r8",]
stm32f030rc = [ "stm32-metapac/stm32f030rc",]
stm32f031c4 = [ "stm32-metapac/stm32f031c4",]
stm32f031c6 = [ "stm32-metapac/stm32f031c6",]
stm32f031e6 = [ "stm32-metapac/stm32f031e6",]
stm32f031f4 = [ "stm32-metapac/stm32f031f4",]
stm32f031f6 = [ "stm32-metapac/stm32f031f6",]
stm32f031g4 = [ "stm32-metapac/stm32f031g4",]
stm32f031g6 = [ "stm32-metapac/stm32f031g6",]
stm32f031k4 = [ "stm32-metapac/stm32f031k4",]
stm32f031k6 = [ "stm32-metapac/stm32f031k6",]
stm32f038c6 = [ "stm32-metapac/stm32f038c6",]
stm32f038e6 = [ "stm32-metapac/stm32f038e6",]
stm32f038f6 = [ "stm32-metapac/stm32f038f6",]
stm32f038g6 = [ "stm32-metapac/stm32f038g6",]
stm32f038k6 = [ "stm32-metapac/stm32f038k6",]
stm32f042c4 = [ "stm32-metapac/stm32f042c4",]
stm32f042c6 = [ "stm32-metapac/stm32f042c6",]
stm32f042f4 = [ "stm32-metapac/stm32f042f4",]
stm32f042f6 = [ "stm32-metapac/stm32f042f6",]
stm32f042g4 = [ "stm32-metapac/stm32f042g4",]
stm32f042g6 = [ "stm32-metapac/stm32f042g6",]
stm32f042k4 = [ "stm32-metapac/stm32f042k4",]
stm32f042k6 = [ "stm32-metapac/stm32f042k6",]
stm32f042t6 = [ "stm32-metapac/stm32f042t6",]
stm32f048c6 = [ "stm32-metapac/stm32f048c6",]
stm32f048g6 = [ "stm32-metapac/stm32f048g6",]
stm32f048t6 = [ "stm32-metapac/stm32f048t6",]
stm32f051c4 = [ "stm32-metapac/stm32f051c4",]
stm32f051c6 = [ "stm32-metapac/stm32f051c6",]
stm32f051c8 = [ "stm32-metapac/stm32f051c8",]
stm32f051k4 = [ "stm32-metapac/stm32f051k4",]
stm32f051k6 = [ "stm32-metapac/stm32f051k6",]
stm32f051k8 = [ "stm32-metapac/stm32f051k8",]
stm32f051r4 = [ "stm32-metapac/stm32f051r4",]
stm32f051r6 = [ "stm32-metapac/stm32f051r6",]
stm32f051r8 = [ "stm32-metapac/stm32f051r8",]
stm32f051t8 = [ "stm32-metapac/stm32f051t8",]
stm32f058c8 = [ "stm32-metapac/stm32f058c8",]
stm32f058r8 = [ "stm32-metapac/stm32f058r8",]
stm32f058t8 = [ "stm32-metapac/stm32f058t8",]
stm32f070c6 = [ "stm32-metapac/stm32f070c6",]
stm32f070cb = [ "stm32-metapac/stm32f070cb",]
stm32f070f6 = [ "stm32-metapac/stm32f070f6",]
stm32f070rb = [ "stm32-metapac/stm32f070rb",]
stm32f071c8 = [ "stm32-metapac/stm32f071c8",]
stm32f071cb = [ "stm32-metapac/stm32f071cb",]
stm32f071rb = [ "stm32-metapac/stm32f071rb",]
stm32f071v8 = [ "stm32-metapac/stm32f071v8",]
stm32f071vb = [ "stm32-metapac/stm32f071vb",]
stm32f072c8 = [ "stm32-metapac/stm32f072c8",]
stm32f072cb = [ "stm32-metapac/stm32f072cb",]
stm32f072r8 = [ "stm32-metapac/stm32f072r8",]
stm32f072rb = [ "stm32-metapac/stm32f072rb",]
stm32f072v8 = [ "stm32-metapac/stm32f072v8",]
stm32f072vb = [ "stm32-metapac/stm32f072vb",]
stm32f078cb = [ "stm32-metapac/stm32f078cb",]
stm32f078rb = [ "stm32-metapac/stm32f078rb",]
stm32f078vb = [ "stm32-metapac/stm32f078vb",]
stm32f091cb = [ "stm32-metapac/stm32f091cb",]
stm32f091cc = [ "stm32-metapac/stm32f091cc",]
stm32f091rb = [ "stm32-metapac/stm32f091rb",]
stm32f091rc = [ "stm32-metapac/stm32f091rc",]
stm32f091vb = [ "stm32-metapac/stm32f091vb",]
stm32f091vc = [ "stm32-metapac/stm32f091vc",]
stm32f098cc = [ "stm32-metapac/stm32f098cc",]
stm32f098rc = [ "stm32-metapac/stm32f098rc",]
stm32f098vc = [ "stm32-metapac/stm32f098vc",]
stm32f401cb = [ "stm32-metapac/stm32f401cb",]
stm32f401cc = [ "stm32-metapac/stm32f401cc",]
stm32f401cd = [ "stm32-metapac/stm32f401cd",]

View file

@ -33,10 +33,6 @@ if len(c) > 1:
with open(f'{data_path}/chips/{chip_name}.yaml', 'r') as f:
chip = yaml.load(f, Loader=SafeLoader)
# ======= load GPIO AF
with open(f'{data_path}/gpio_af/{chip["gpio_af"]}.yaml', 'r') as f:
af = yaml.load(f, Loader=SafeLoader)
# ======= Generate!
with open(output_file, 'w') as f:
singletons = [] # USART1, PA5, EXTI8

View file

@ -13,6 +13,7 @@ dname = os.path.dirname(abspath)
os.chdir(dname)
supported_families = [
"STM32F0",
'STM32F4',
'STM32L0',
'STM32L4',

View file

@ -0,0 +1,111 @@
#![macro_use]
macro_rules! foreach_exti_irq {
($action:ident) => {
crate::pac::interrupts!(
(EXTI0) => { $action!(EXTI0); };
(EXTI1) => { $action!(EXTI1); };
(EXTI2) => { $action!(EXTI2); };
(EXTI3) => { $action!(EXTI3); };
(EXTI4) => { $action!(EXTI4); };
(EXTI5) => { $action!(EXTI5); };
(EXTI6) => { $action!(EXTI6); };
(EXTI7) => { $action!(EXTI7); };
(EXTI8) => { $action!(EXTI8); };
(EXTI9) => { $action!(EXTI9); };
(EXTI10) => { $action!(EXTI10); };
(EXTI11) => { $action!(EXTI11); };
(EXTI12) => { $action!(EXTI12); };
(EXTI13) => { $action!(EXTI13); };
(EXTI14) => { $action!(EXTI14); };
(EXTI15) => { $action!(EXTI15); };
// plus the weird ones
(EXTI0_1) => { $action!( EXTI0_1 ); };
(EXTI15_10) => { $action!(EXTI15_10); };
(EXTI15_4) => { $action!(EXTI15_4); };
(EXTI1_0) => { $action!(EXTI1_0); };
(EXTI2_3) => { $action!(EXTI2_3); };
(EXTI2_TSC) => { $action!(EXTI2_TSC); };
(EXTI3_2) => { $action!(EXTI3_2); };
(EXTI4_15) => { $action!(EXTI4_15); };
(EXTI9_5) => { $action!(EXTI9_5); };
);
};
}
#[cfg_attr(exti_v1, path = "v1.rs")]
#[cfg_attr(exti_wb55, path = "v2.rs")]
mod _version;
#[allow(unused)]
pub use _version::*;
use crate::peripherals;
use embassy_extras::unsafe_impl_unborrow;
pub(crate) mod sealed {
pub trait Channel {}
}
pub trait Channel: sealed::Channel + Sized {
fn number(&self) -> usize;
fn degrade(self) -> AnyChannel {
AnyChannel {
number: self.number() as u8,
}
}
}
pub struct AnyChannel {
number: u8,
}
unsafe_impl_unborrow!(AnyChannel);
impl sealed::Channel for AnyChannel {}
impl Channel for AnyChannel {
fn number(&self) -> usize {
self.number as usize
}
}
macro_rules! impl_exti {
($type:ident, $number:expr) => {
impl sealed::Channel for peripherals::$type {}
impl Channel for peripherals::$type {
fn number(&self) -> usize {
$number as usize
}
}
};
}
impl_exti!(EXTI0, 0);
impl_exti!(EXTI1, 1);
impl_exti!(EXTI2, 2);
impl_exti!(EXTI3, 3);
impl_exti!(EXTI4, 4);
impl_exti!(EXTI5, 5);
impl_exti!(EXTI6, 6);
impl_exti!(EXTI7, 7);
impl_exti!(EXTI8, 8);
impl_exti!(EXTI9, 9);
impl_exti!(EXTI10, 10);
impl_exti!(EXTI11, 11);
impl_exti!(EXTI12, 12);
impl_exti!(EXTI13, 13);
impl_exti!(EXTI14, 14);
impl_exti!(EXTI15, 15);
macro_rules! enable_irq {
($e:ident) => {
crate::interrupt::$e::steal().enable();
};
}
/// safety: must be called only once
pub(crate) unsafe fn init() {
use embassy::interrupt::Interrupt;
use embassy::interrupt::InterruptExt;
foreach_exti_irq!(enable_irq);
}

View file

@ -1,4 +1,3 @@
#![macro_use]
use core::convert::Infallible;
use core::future::Future;
use core::marker::PhantomData;
@ -6,14 +5,12 @@ use core::pin::Pin;
use core::task::{Context, Poll};
use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
use embassy::util::{AtomicWaker, Unborrow};
use embassy_extras::unsafe_impl_unborrow;
use embedded_hal::digital::v2::InputPin;
use pac::exti::{regs, vals};
use crate::gpio::{AnyPin, Input, Pin as GpioPin};
use crate::pac;
use crate::pac::{EXTI, SYSCFG};
use crate::peripherals;
const EXTI_COUNT: usize = 16;
const NEW_AW: AtomicWaker = AtomicWaker::new();
@ -160,106 +157,6 @@ impl<'a> Future for ExtiInputFuture<'a> {
}
}
pub(crate) mod sealed {
pub trait Channel {}
}
pub trait Channel: sealed::Channel + Sized {
fn number(&self) -> usize;
fn degrade(self) -> AnyChannel {
AnyChannel {
number: self.number() as u8,
}
}
}
pub struct AnyChannel {
number: u8,
}
unsafe_impl_unborrow!(AnyChannel);
impl sealed::Channel for AnyChannel {}
impl Channel for AnyChannel {
fn number(&self) -> usize {
self.number as usize
}
}
macro_rules! impl_exti {
($type:ident, $number:expr) => {
impl sealed::Channel for peripherals::$type {}
impl Channel for peripherals::$type {
fn number(&self) -> usize {
$number as usize
}
}
};
}
impl_exti!(EXTI0, 0);
impl_exti!(EXTI1, 1);
impl_exti!(EXTI2, 2);
impl_exti!(EXTI3, 3);
impl_exti!(EXTI4, 4);
impl_exti!(EXTI5, 5);
impl_exti!(EXTI6, 6);
impl_exti!(EXTI7, 7);
impl_exti!(EXTI8, 8);
impl_exti!(EXTI9, 9);
impl_exti!(EXTI10, 10);
impl_exti!(EXTI11, 11);
impl_exti!(EXTI12, 12);
impl_exti!(EXTI13, 13);
impl_exti!(EXTI14, 14);
impl_exti!(EXTI15, 15);
macro_rules! foreach_exti_irq {
($action:ident) => {
crate::pac::interrupts!(
(EXTI0) => { $action!(EXTI0); };
(EXTI1) => { $action!(EXTI1); };
(EXTI2) => { $action!(EXTI2); };
(EXTI3) => { $action!(EXTI3); };
(EXTI4) => { $action!(EXTI4); };
(EXTI5) => { $action!(EXTI5); };
(EXTI6) => { $action!(EXTI6); };
(EXTI7) => { $action!(EXTI7); };
(EXTI8) => { $action!(EXTI8); };
(EXTI9) => { $action!(EXTI9); };
(EXTI10) => { $action!(EXTI10); };
(EXTI11) => { $action!(EXTI11); };
(EXTI12) => { $action!(EXTI12); };
(EXTI13) => { $action!(EXTI13); };
(EXTI14) => { $action!(EXTI14); };
(EXTI15) => { $action!(EXTI15); };
// plus the weird ones
(EXTI0_1) => { $action!( EXTI0_1 ); };
(EXTI15_10) => { $action!(EXTI15_10); };
(EXTI15_4) => { $action!(EXTI15_4); };
(EXTI1_0) => { $action!(EXTI1_0); };
(EXTI2_3) => { $action!(EXTI2_3); };
(EXTI2_TSC) => { $action!(EXTI2_TSC); };
(EXTI3_2) => { $action!(EXTI3_2); };
(EXTI4_15) => { $action!(EXTI4_15); };
(EXTI9_5) => { $action!(EXTI9_5); };
);
};
}
macro_rules! enable_irq {
($e:ident) => {
crate::interrupt::$e::steal().enable();
};
}
/// safety: must be called only once
pub(crate) unsafe fn init() {
use embassy::interrupt::Interrupt;
use embassy::interrupt::InterruptExt;
foreach_exti_irq!(enable_irq);
}
use crate::interrupt;
macro_rules! impl_irq {

View file

@ -0,0 +1 @@

View file

@ -16,7 +16,6 @@ pub mod interrupt;
pub mod time;
// Always-present hardware
pub mod exti;
pub mod gpio;
pub mod rcc;
@ -31,6 +30,8 @@ pub mod dac;
pub mod dma;
#[cfg(all(eth, feature = "net"))]
pub mod eth;
#[cfg(exti)]
pub mod exti;
#[cfg(i2c)]
pub mod i2c;
#[cfg(pwr)]
@ -83,10 +84,9 @@ pub fn init(config: Config) -> Peripherals {
let p = Peripherals::take();
unsafe {
exti::init();
#[cfg(dma)]
dma::init();
#[cfg(exti)]
exti::init();
rcc::init(config.rcc);
}

View file

@ -0,0 +1,231 @@
use core::marker::PhantomData;
use embassy::util::Unborrow;
use crate::pac::{DBGMCU, FLASH, RCC};
use crate::peripherals;
use crate::time::Hertz;
use super::{set_freqs, Clocks};
const HSI: u32 = 8_000_000;
/// Configuration of the clocks
///
/// hse takes precedence over hsi48 if both are enabled
#[non_exhaustive]
#[derive(Default)]
pub struct Config {
pub hse: Option<Hertz>,
pub bypass_hse: bool,
pub usb_pll: bool,
#[cfg(rcc_f0)]
pub hsi48: bool,
pub sys_ck: Option<Hertz>,
pub hclk: Option<Hertz>,
pub pclk: Option<Hertz>,
pub enable_debug_wfe: bool,
}
pub struct Rcc<'d> {
inner: PhantomData<&'d ()>,
config: Config,
}
impl<'d> Rcc<'d> {
pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self {
Self {
inner: PhantomData,
config,
}
}
pub fn freeze(self) -> Clocks {
use crate::pac::rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Sw, Usbsw};
let sysclk = self.config.sys_ck.map(|v| v.0).unwrap_or(HSI);
let (src_clk, use_hsi48) = self.config.hse.map(|v| (v.0, false)).unwrap_or_else(|| {
#[cfg(rcc_f0)]
if self.config.hsi48 {
return (48_000_000, true);
}
(HSI, false)
});
let (pllmul_bits, real_sysclk) = if sysclk == src_clk {
(None, sysclk)
} else {
let prediv = if self.config.hse.is_some() { 1 } else { 2 };
let pllmul = (2 * prediv * sysclk + src_clk) / src_clk / 2;
let pllmul = pllmul.max(2).min(16);
let pllmul_bits = pllmul as u8 - 2;
let real_sysclk = pllmul * src_clk / prediv;
(Some(pllmul_bits), real_sysclk)
};
let hpre_bits = self
.config
.hclk
.map(|hclk| match real_sysclk / hclk.0 {
0 => unreachable!(),
1 => 0b0111,
2 => 0b1000,
3..=5 => 0b1001,
6..=11 => 0b1010,
12..=39 => 0b1011,
40..=95 => 0b1100,
96..=191 => 0b1101,
192..=383 => 0b1110,
_ => 0b1111,
})
.unwrap_or(0b0111);
let hclk = real_sysclk / (1 << (hpre_bits - 0b0111));
let ppre_bits = self
.config
.pclk
.map(|pclk| match hclk / pclk.0 {
0 => unreachable!(),
1 => 0b011,
2 => 0b100,
3..=5 => 0b101,
6..=11 => 0b110,
_ => 0b111,
})
.unwrap_or(0b011);
let ppre: u8 = 1 << (ppre_bits - 0b011);
let pclk = hclk / u32::from(ppre);
let timer_mul = if ppre == 1 { 1 } else { 2 };
// NOTE(safety) Atomic write
unsafe {
FLASH.acr().write(|w| {
let latency = if real_sysclk <= 24_000_000 {
0
} else if real_sysclk <= 48_000_000 {
1
} else {
2
};
w.latency().0 = latency;
});
}
// NOTE(unsafe) We have exclusive access to the RCC
unsafe {
match (self.config.hse.is_some(), use_hsi48) {
(true, _) => {
RCC.cr().modify(|w| {
w.set_csson(true);
w.set_hseon(true);
if self.config.bypass_hse {
w.set_hsebyp(Hsebyp::BYPASSED);
}
});
while !RCC.cr().read().hserdy() {}
if pllmul_bits.is_some() {
RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSE_DIV_PREDIV))
}
}
(false, true) => {
// use_hsi48 will always be false for rcc_f0x0
#[cfg(rcc_f0)]
RCC.cr2().modify(|w| w.set_hsi48on(true));
#[cfg(rcc_f0)]
while !RCC.cr2().read().hsi48rdy() {}
#[cfg(rcc_f0)]
if pllmul_bits.is_some() {
RCC.cfgr()
.modify(|w| w.set_pllsrc(Pllsrc::HSI48_DIV_PREDIV))
}
}
_ => {
RCC.cr().modify(|w| w.set_hsion(true));
while !RCC.cr().read().hsirdy() {}
if pllmul_bits.is_some() {
RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSI_DIV2))
}
}
}
if self.config.usb_pll {
RCC.cfgr3().modify(|w| w.set_usbsw(Usbsw::PLLCLK));
}
// TODO: Option to use CRS (Clock Recovery)
if let Some(pllmul_bits) = pllmul_bits {
RCC.cfgr().modify(|w| w.set_pllmul(Pllmul(pllmul_bits)));
RCC.cr().modify(|w| w.set_pllon(true));
while !RCC.cr().read().pllrdy() {}
RCC.cfgr().modify(|w| {
w.set_ppre(Ppre(ppre_bits));
w.set_hpre(Hpre(hpre_bits));
w.set_sw(Sw::PLL)
});
} else {
RCC.cfgr().modify(|w| {
w.set_ppre(Ppre(ppre_bits));
w.set_hpre(Hpre(hpre_bits));
if self.config.hse.is_some() {
w.set_sw(Sw::HSE);
} else if use_hsi48 {
#[cfg(rcc_f0)]
w.set_sw(Sw::HSI48);
} else {
w.set_sw(Sw::HSI)
}
})
}
if self.config.enable_debug_wfe {
RCC.ahbenr().modify(|w| w.set_dmaen(true));
critical_section::with(|_| {
DBGMCU.cr().modify(|w| {
w.set_dbg_standby(true);
w.set_dbg_stop(true);
});
});
}
}
Clocks {
sys: Hertz(real_sysclk),
apb1: Hertz(pclk),
apb1_tim: Hertz(pclk * timer_mul),
apb2_tim: Hertz(0),
ahb: Hertz(hclk),
}
}
}
pub unsafe fn init(config: Config) {
RCC.ahbenr().modify(|w| {
w.set_iopaen(true);
w.set_iopben(true);
w.set_iopcen(true);
w.set_iopden(true);
#[cfg(rcc_f0)]
w.set_iopeen(true);
w.set_iopfen(true);
});
let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config);
let clocks = rcc.freeze();
set_freqs(clocks);
}

View file

@ -9,11 +9,14 @@ mod types;
pub struct Clocks {
pub sys: Hertz,
pub apb1: Hertz,
#[cfg(not(any(rcc_f0, rcc_f0x0)))]
pub apb2: Hertz,
pub apb1_tim: Hertz,
pub apb2_tim: Hertz,
#[cfg(any(rcc_l0))]
#[cfg(any(rcc_l0, rcc_f0, rcc_f0x0))]
pub ahb: Hertz,
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55, rcc_wl5x))]
@ -65,6 +68,9 @@ cfg_if::cfg_if! {
} else if #[cfg(rcc_wl5x)] {
mod wl5x;
pub use wl5x::*;
} else if #[cfg(any(rcc_f0, rcc_f0x0))] {
mod f0;
pub use f0::*;
}
}

@ -1 +1 @@
Subproject commit 18f86c83123771048f971350c99c4f810385d7d1
Subproject commit eb76ee900ac67b51497196572250323e82666b4c

View file

@ -19,7 +19,6 @@ pub struct Chip {
pub cores: Vec<Core>,
pub flash: u32,
pub ram: u32,
pub gpio_af: String,
pub packages: Vec<Package>,
}