mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
stm32/rcc: add ClockEnableBit struct.
This commit is contained in:
parent
8e7361f4ca
commit
eeb6ffce4c
@ -7,6 +7,7 @@ use std::{env, fs};
|
||||
|
||||
use proc_macro2::{Ident, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
use stm32_metapac::metadata::ir::BitOffset;
|
||||
use stm32_metapac::metadata::{
|
||||
MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, METADATA,
|
||||
};
|
||||
@ -359,12 +360,17 @@ fn main() {
|
||||
|
||||
// ========
|
||||
// Extract the rcc registers
|
||||
|
||||
let rcc_registers = METADATA
|
||||
.peripherals
|
||||
.iter()
|
||||
.filter_map(|p| p.registers.as_ref())
|
||||
.find(|r| r.kind == "rcc")
|
||||
.unwrap();
|
||||
for b in rcc_registers.ir.blocks {
|
||||
eprintln!("{}", b.name);
|
||||
}
|
||||
let rcc_block = rcc_registers.ir.blocks.iter().find(|b| b.name == "Rcc").unwrap();
|
||||
|
||||
// ========
|
||||
// Generate RccPeripheral impls
|
||||
@ -540,6 +546,29 @@ fn main() {
|
||||
let pname = format_ident!("{}", p.name);
|
||||
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
|
||||
let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
|
||||
let en_reg_offs = rcc_block
|
||||
.items
|
||||
.iter()
|
||||
.find(|i| i.name.eq_ignore_ascii_case(en.register))
|
||||
.unwrap()
|
||||
.byte_offset;
|
||||
let en_reg_offs: u8 = (en_reg_offs / 4).try_into().unwrap();
|
||||
|
||||
let en_bit_offs = &rcc_registers
|
||||
.ir
|
||||
.fieldsets
|
||||
.iter()
|
||||
.find(|i| i.name.eq_ignore_ascii_case(en.register))
|
||||
.unwrap()
|
||||
.fields
|
||||
.iter()
|
||||
.find(|i| i.name.eq_ignore_ascii_case(en.field))
|
||||
.unwrap()
|
||||
.bit_offset;
|
||||
let BitOffset::Regular(en_bit_offs) = en_bit_offs else {
|
||||
panic!("cursed bit offset")
|
||||
};
|
||||
let en_bit_offs: u8 = en_bit_offs.offset.try_into().unwrap();
|
||||
|
||||
let refcount =
|
||||
clock_gen.force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1;
|
||||
@ -624,6 +653,9 @@ fn main() {
|
||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
||||
#decr_stop_refcount
|
||||
}
|
||||
fn enable_bit() -> crate::rcc::ClockEnableBit {
|
||||
unsafe { crate::rcc::ClockEnableBit::new(#en_reg_offs, #en_bit_offs) }
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::rcc::RccPeripheral for peripherals::#pname {}
|
||||
|
@ -31,6 +31,7 @@ pub use hsi48::*;
|
||||
mod _version;
|
||||
|
||||
pub use _version::*;
|
||||
use stm32_metapac::RCC;
|
||||
|
||||
pub use crate::_generated::{mux, Clocks};
|
||||
use crate::time::Hertz;
|
||||
@ -66,9 +67,10 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks {
|
||||
}
|
||||
|
||||
pub(crate) trait SealedRccPeripheral {
|
||||
fn frequency() -> crate::time::Hertz;
|
||||
fn frequency() -> Hertz;
|
||||
fn enable_and_reset_with_cs(cs: CriticalSection);
|
||||
fn disable_with_cs(cs: CriticalSection);
|
||||
fn enable_bit() -> ClockEnableBit;
|
||||
|
||||
fn enable_and_reset() {
|
||||
critical_section::with(|cs| Self::enable_and_reset_with_cs(cs))
|
||||
@ -137,3 +139,49 @@ pub unsafe fn enable_and_reset<T: RccPeripheral>() {
|
||||
pub unsafe fn disable<T: RccPeripheral>() {
|
||||
T::disable();
|
||||
}
|
||||
|
||||
/// Struct representing some clock enable bit (xxxENR.xxEN), only known at runtime.
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct ClockEnableBit {
|
||||
/// offset in 32bit words of the xxxENR register into the RCC register block.
|
||||
offset: u8,
|
||||
/// bit within the register (0..=31)
|
||||
bit: u8,
|
||||
}
|
||||
|
||||
impl ClockEnableBit {
|
||||
/// Safety: offset+bit must correspond to a valid xxxEN bit.
|
||||
pub(crate) unsafe fn new(offset: u8, bit: u8) -> Self {
|
||||
Self { offset, bit }
|
||||
}
|
||||
|
||||
fn ptr(self) -> *mut u32 {
|
||||
unsafe { (RCC.as_ptr() as *mut u32).add(self.offset as _) }
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn enable_with_cs(self, _cs: CriticalSection) {
|
||||
let p = self.ptr();
|
||||
unsafe {
|
||||
let val = p.read_volatile();
|
||||
p.write_volatile(val | 1u32 << self.bit);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn disable_with_cs(self, _cs: CriticalSection) {
|
||||
let p = self.ptr();
|
||||
unsafe {
|
||||
let val = p.read_volatile();
|
||||
p.write_volatile(val & !(1u32 << self.bit));
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(crate) fn enable(self) {
|
||||
critical_section::with(|cs| self.enable_with_cs(cs))
|
||||
}
|
||||
|
||||
pub(crate) fn disable(self) {
|
||||
critical_section::with(|cs| self.disable_with_cs(cs))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user