commit
e1880a19df
11 changed files with 428 additions and 113 deletions
|
@ -45,6 +45,79 @@ net = ["embassy-net", "vcell"]
|
||||||
|
|
||||||
# BEGIN GENERATED FEATURES
|
# BEGIN GENERATED FEATURES
|
||||||
# Generated by gen_features.py. DO NOT EDIT.
|
# 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",]
|
stm32f401cb = [ "stm32-metapac/stm32f401cb",]
|
||||||
stm32f401cc = [ "stm32-metapac/stm32f401cc",]
|
stm32f401cc = [ "stm32-metapac/stm32f401cc",]
|
||||||
stm32f401cd = [ "stm32-metapac/stm32f401cd",]
|
stm32f401cd = [ "stm32-metapac/stm32f401cd",]
|
||||||
|
|
|
@ -33,10 +33,6 @@ if len(c) > 1:
|
||||||
with open(f'{data_path}/chips/{chip_name}.yaml', 'r') as f:
|
with open(f'{data_path}/chips/{chip_name}.yaml', 'r') as f:
|
||||||
chip = yaml.load(f, Loader=SafeLoader)
|
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!
|
# ======= Generate!
|
||||||
with open(output_file, 'w') as f:
|
with open(output_file, 'w') as f:
|
||||||
singletons = [] # USART1, PA5, EXTI8
|
singletons = [] # USART1, PA5, EXTI8
|
||||||
|
|
|
@ -13,6 +13,7 @@ dname = os.path.dirname(abspath)
|
||||||
os.chdir(dname)
|
os.chdir(dname)
|
||||||
|
|
||||||
supported_families = [
|
supported_families = [
|
||||||
|
"STM32F0",
|
||||||
'STM32F4',
|
'STM32F4',
|
||||||
'STM32L0',
|
'STM32L0',
|
||||||
'STM32L4',
|
'STM32L4',
|
||||||
|
|
111
embassy-stm32/src/exti/mod.rs
Normal file
111
embassy-stm32/src/exti/mod.rs
Normal 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);
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
#![macro_use]
|
|
||||||
use core::convert::Infallible;
|
use core::convert::Infallible;
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
@ -6,14 +5,12 @@ use core::pin::Pin;
|
||||||
use core::task::{Context, Poll};
|
use core::task::{Context, Poll};
|
||||||
use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
|
use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
|
||||||
use embassy::util::{AtomicWaker, Unborrow};
|
use embassy::util::{AtomicWaker, Unborrow};
|
||||||
use embassy_extras::unsafe_impl_unborrow;
|
|
||||||
use embedded_hal::digital::v2::InputPin;
|
use embedded_hal::digital::v2::InputPin;
|
||||||
use pac::exti::{regs, vals};
|
use pac::exti::{regs, vals};
|
||||||
|
|
||||||
use crate::gpio::{AnyPin, Input, Pin as GpioPin};
|
use crate::gpio::{AnyPin, Input, Pin as GpioPin};
|
||||||
use crate::pac;
|
use crate::pac;
|
||||||
use crate::pac::{EXTI, SYSCFG};
|
use crate::pac::{EXTI, SYSCFG};
|
||||||
use crate::peripherals;
|
|
||||||
|
|
||||||
const EXTI_COUNT: usize = 16;
|
const EXTI_COUNT: usize = 16;
|
||||||
const NEW_AW: AtomicWaker = AtomicWaker::new();
|
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;
|
use crate::interrupt;
|
||||||
|
|
||||||
macro_rules! impl_irq {
|
macro_rules! impl_irq {
|
1
embassy-stm32/src/exti/v2.rs
Normal file
1
embassy-stm32/src/exti/v2.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -16,7 +16,6 @@ pub mod interrupt;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
|
|
||||||
// Always-present hardware
|
// Always-present hardware
|
||||||
pub mod exti;
|
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
pub mod rcc;
|
pub mod rcc;
|
||||||
|
|
||||||
|
@ -31,6 +30,8 @@ pub mod dac;
|
||||||
pub mod dma;
|
pub mod dma;
|
||||||
#[cfg(all(eth, feature = "net"))]
|
#[cfg(all(eth, feature = "net"))]
|
||||||
pub mod eth;
|
pub mod eth;
|
||||||
|
#[cfg(exti)]
|
||||||
|
pub mod exti;
|
||||||
#[cfg(i2c)]
|
#[cfg(i2c)]
|
||||||
pub mod i2c;
|
pub mod i2c;
|
||||||
#[cfg(pwr)]
|
#[cfg(pwr)]
|
||||||
|
@ -83,10 +84,9 @@ pub fn init(config: Config) -> Peripherals {
|
||||||
let p = Peripherals::take();
|
let p = Peripherals::take();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
exti::init();
|
|
||||||
|
|
||||||
#[cfg(dma)]
|
#[cfg(dma)]
|
||||||
dma::init();
|
dma::init();
|
||||||
|
#[cfg(exti)]
|
||||||
exti::init();
|
exti::init();
|
||||||
rcc::init(config.rcc);
|
rcc::init(config.rcc);
|
||||||
}
|
}
|
||||||
|
|
231
embassy-stm32/src/rcc/f0/mod.rs
Normal file
231
embassy-stm32/src/rcc/f0/mod.rs
Normal 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);
|
||||||
|
}
|
|
@ -9,11 +9,14 @@ mod types;
|
||||||
pub struct Clocks {
|
pub struct Clocks {
|
||||||
pub sys: Hertz,
|
pub sys: Hertz,
|
||||||
pub apb1: Hertz,
|
pub apb1: Hertz,
|
||||||
|
|
||||||
|
#[cfg(not(any(rcc_f0, rcc_f0x0)))]
|
||||||
pub apb2: Hertz,
|
pub apb2: Hertz,
|
||||||
|
|
||||||
pub apb1_tim: Hertz,
|
pub apb1_tim: Hertz,
|
||||||
pub apb2_tim: Hertz,
|
pub apb2_tim: Hertz,
|
||||||
|
|
||||||
#[cfg(any(rcc_l0))]
|
#[cfg(any(rcc_l0, rcc_f0, rcc_f0x0))]
|
||||||
pub ahb: Hertz,
|
pub ahb: Hertz,
|
||||||
|
|
||||||
#[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55, rcc_wl5x))]
|
#[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)] {
|
} else if #[cfg(rcc_wl5x)] {
|
||||||
mod wl5x;
|
mod wl5x;
|
||||||
pub use 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
|
|
@ -19,7 +19,6 @@ pub struct Chip {
|
||||||
pub cores: Vec<Core>,
|
pub cores: Vec<Core>,
|
||||||
pub flash: u32,
|
pub flash: u32,
|
||||||
pub ram: u32,
|
pub ram: u32,
|
||||||
pub gpio_af: String,
|
|
||||||
pub packages: Vec<Package>,
|
pub packages: Vec<Package>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue