Provide a way for a peripheral to query its clock frequency
Currently this looks up the frequency in the global singleton that must be initialized by the per-chip RCC implementation. At present, this is only done for the L0 family of chips.
This commit is contained in:
parent
85f172dd93
commit
952f525af5
@ -17,9 +17,7 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream
|
|||||||
);
|
);
|
||||||
let clock = unsafe { make_static(&mut c) };
|
let clock = unsafe { make_static(&mut c) };
|
||||||
|
|
||||||
// TODO: Is TIM2 always APB1?
|
clock.start();
|
||||||
let timer_freq = unsafe { #embassy_stm32_path::rcc::get_freqs().apb1_clk };
|
|
||||||
clock.start(timer_freq);
|
|
||||||
|
|
||||||
let mut alarm = clock.alarm1();
|
let mut alarm = clock.alarm1();
|
||||||
unsafe { #embassy_path::time::set_clock(clock) };
|
unsafe { #embassy_path::time::set_clock(clock) };
|
||||||
|
@ -77,12 +77,14 @@ impl<T: Instance> Clock<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start(&'static self, timer_freq: Hertz) {
|
pub fn start(&'static self) {
|
||||||
let inner = T::inner();
|
let inner = T::inner();
|
||||||
|
|
||||||
T::enable();
|
T::enable();
|
||||||
T::reset();
|
T::reset();
|
||||||
|
|
||||||
|
let timer_freq = T::frequency();
|
||||||
|
|
||||||
// NOTE(unsafe) Critical section to use the unsafe methods
|
// NOTE(unsafe) Critical section to use the unsafe methods
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -469,35 +469,31 @@ impl RccExt for RCC {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (apb1_freq, apb1_tim_freq, apb1_pre) = match cfgr.apb1_pre {
|
let apb1_freq = match cfgr.apb1_pre {
|
||||||
APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1),
|
APBPrescaler::NotDivided => ahb_freq,
|
||||||
pre => {
|
pre => {
|
||||||
let pre: Ppre = pre.into();
|
let pre: Ppre = pre.into();
|
||||||
let pre: u8 = 1 << (pre.0 - 3);
|
let pre: u8 = 1 << (pre.0 - 3);
|
||||||
let freq = ahb_freq / pre as u32;
|
let freq = ahb_freq / pre as u32;
|
||||||
(freq, freq * 2, pre as u8)
|
freq
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let (apb2_freq, apb2_tim_freq, apb2_pre) = match cfgr.apb2_pre {
|
let apb2_freq = match cfgr.apb2_pre {
|
||||||
APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1),
|
APBPrescaler::NotDivided => ahb_freq,
|
||||||
pre => {
|
pre => {
|
||||||
let pre: Ppre = pre.into();
|
let pre: Ppre = pre.into();
|
||||||
let pre: u8 = 1 << (pre.0 - 3);
|
let pre: u8 = 1 << (pre.0 - 3);
|
||||||
let freq = ahb_freq / (1 << (pre as u8 - 3));
|
let freq = ahb_freq / (1 << (pre as u8 - 3));
|
||||||
(freq, freq * 2, pre as u8)
|
freq
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Clocks {
|
Clocks {
|
||||||
sys_clk: sys_clk.hz(),
|
sys: sys_clk.hz(),
|
||||||
ahb_clk: ahb_freq.hz(),
|
ahb: ahb_freq.hz(),
|
||||||
apb1_clk: apb1_freq.hz(),
|
apb1: apb1_freq.hz(),
|
||||||
apb2_clk: apb2_freq.hz(),
|
apb2: apb2_freq.hz(),
|
||||||
apb1_tim_clk: apb1_tim_freq.hz(),
|
|
||||||
apb2_tim_clk: apb2_tim_freq.hz(),
|
|
||||||
apb1_pre,
|
|
||||||
apb2_pre,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,10 @@ use core::mem::MaybeUninit;
|
|||||||
/// The existence of this value indicates that the clock configuration can no longer be changed
|
/// The existence of this value indicates that the clock configuration can no longer be changed
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Clocks {
|
pub struct Clocks {
|
||||||
pub sys_clk: Hertz,
|
pub sys: Hertz,
|
||||||
pub ahb_clk: Hertz,
|
pub ahb: Hertz,
|
||||||
pub apb1_clk: Hertz,
|
pub apb1: Hertz,
|
||||||
pub apb1_tim_clk: Hertz,
|
pub apb2: Hertz,
|
||||||
pub apb2_clk: Hertz,
|
|
||||||
pub apb2_tim_clk: Hertz,
|
|
||||||
pub apb1_pre: u8,
|
|
||||||
pub apb2_pre: u8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
|
static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
|
||||||
@ -50,6 +46,7 @@ cfg_if::cfg_if! {
|
|||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
pub trait RccPeripheral {
|
pub trait RccPeripheral {
|
||||||
|
fn frequency() -> crate::time::Hertz;
|
||||||
fn reset();
|
fn reset();
|
||||||
fn enable();
|
fn enable();
|
||||||
fn disable();
|
fn disable();
|
||||||
@ -59,8 +56,16 @@ pub(crate) mod sealed {
|
|||||||
pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
|
pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
|
||||||
|
|
||||||
crate::pac::peripheral_rcc!(
|
crate::pac::peripheral_rcc!(
|
||||||
($inst:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => {
|
($inst:ident, $clk:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => {
|
||||||
impl sealed::RccPeripheral for peripherals::$inst {
|
impl sealed::RccPeripheral for peripherals::$inst {
|
||||||
|
fn frequency() -> crate::time::Hertz {
|
||||||
|
critical_section::with(|_| {
|
||||||
|
unsafe {
|
||||||
|
let freqs = get_freqs();
|
||||||
|
freqs.$clk
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
fn enable() {
|
fn enable() {
|
||||||
critical_section::with(|_| {
|
critical_section::with(|_| {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -37,7 +37,6 @@ pub struct Spi<'d, T: Instance> {
|
|||||||
|
|
||||||
impl<'d, T: Instance> Spi<'d, T> {
|
impl<'d, T: Instance> Spi<'d, T> {
|
||||||
pub fn new<F>(
|
pub fn new<F>(
|
||||||
pclk: Hertz,
|
|
||||||
_peri: impl Unborrow<Target = T> + 'd,
|
_peri: impl Unborrow<Target = T> + 'd,
|
||||||
sck: impl Unborrow<Target = impl SckPin<T>>,
|
sck: impl Unborrow<Target = impl SckPin<T>>,
|
||||||
mosi: impl Unborrow<Target = impl MosiPin<T>>,
|
mosi: impl Unborrow<Target = impl MosiPin<T>>,
|
||||||
@ -60,6 +59,7 @@ impl<'d, T: Instance> Spi<'d, T> {
|
|||||||
let mosi = mosi.degrade();
|
let mosi = mosi.degrade();
|
||||||
let miso = miso.degrade();
|
let miso = miso.degrade();
|
||||||
|
|
||||||
|
let pclk = T::frequency();
|
||||||
let br = Self::compute_baud_rate(pclk, freq.into());
|
let br = Self::compute_baud_rate(pclk, freq.into());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -287,8 +287,23 @@ pub fn gen(options: Options) {
|
|||||||
|
|
||||||
match (en, rst) {
|
match (en, rst) {
|
||||||
(Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => {
|
(Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => {
|
||||||
|
let clock = if clock_prefix == "" {
|
||||||
|
let re = Regex::new("([A-Z]+\\d*).*").unwrap();
|
||||||
|
if !re.is_match(enable_reg) {
|
||||||
|
panic!(
|
||||||
|
"unable to derive clock name from register name {}",
|
||||||
|
enable_reg
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let caps = re.captures(enable_reg).unwrap();
|
||||||
|
caps.get(1).unwrap().as_str()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clock_prefix
|
||||||
|
};
|
||||||
peripheral_rcc_table.push(vec![
|
peripheral_rcc_table.push(vec![
|
||||||
name.clone(),
|
name.clone(),
|
||||||
|
clock.to_ascii_lowercase(),
|
||||||
enable_reg.to_ascii_lowercase(),
|
enable_reg.to_ascii_lowercase(),
|
||||||
reset_reg.to_ascii_lowercase(),
|
reset_reg.to_ascii_lowercase(),
|
||||||
format!("set_{}", enable_field.to_ascii_lowercase()),
|
format!("set_{}", enable_field.to_ascii_lowercase()),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user