stm32/rcc: add ClockEnableBit struct.
This commit is contained in:
parent
8e7361f4ca
commit
eeb6ffce4c
2 changed files with 81 additions and 1 deletions
|
@ -7,6 +7,7 @@ use std::{env, fs};
|
||||||
|
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
use stm32_metapac::metadata::ir::BitOffset;
|
||||||
use stm32_metapac::metadata::{
|
use stm32_metapac::metadata::{
|
||||||
MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, METADATA,
|
MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, METADATA,
|
||||||
};
|
};
|
||||||
|
@ -359,12 +360,17 @@ fn main() {
|
||||||
|
|
||||||
// ========
|
// ========
|
||||||
// Extract the rcc registers
|
// Extract the rcc registers
|
||||||
|
|
||||||
let rcc_registers = METADATA
|
let rcc_registers = METADATA
|
||||||
.peripherals
|
.peripherals
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|p| p.registers.as_ref())
|
.filter_map(|p| p.registers.as_ref())
|
||||||
.find(|r| r.kind == "rcc")
|
.find(|r| r.kind == "rcc")
|
||||||
.unwrap();
|
.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
|
// Generate RccPeripheral impls
|
||||||
|
@ -540,6 +546,29 @@ fn main() {
|
||||||
let pname = format_ident!("{}", p.name);
|
let pname = format_ident!("{}", p.name);
|
||||||
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
|
let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
|
||||||
let set_en_field = format_ident!("set_{}", en.field.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 =
|
let refcount =
|
||||||
clock_gen.force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1;
|
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));
|
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
||||||
#decr_stop_refcount
|
#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 {}
|
impl crate::rcc::RccPeripheral for peripherals::#pname {}
|
||||||
|
|
|
@ -31,6 +31,7 @@ pub use hsi48::*;
|
||||||
mod _version;
|
mod _version;
|
||||||
|
|
||||||
pub use _version::*;
|
pub use _version::*;
|
||||||
|
use stm32_metapac::RCC;
|
||||||
|
|
||||||
pub use crate::_generated::{mux, Clocks};
|
pub use crate::_generated::{mux, Clocks};
|
||||||
use crate::time::Hertz;
|
use crate::time::Hertz;
|
||||||
|
@ -66,9 +67,10 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait SealedRccPeripheral {
|
pub(crate) trait SealedRccPeripheral {
|
||||||
fn frequency() -> crate::time::Hertz;
|
fn frequency() -> Hertz;
|
||||||
fn enable_and_reset_with_cs(cs: CriticalSection);
|
fn enable_and_reset_with_cs(cs: CriticalSection);
|
||||||
fn disable_with_cs(cs: CriticalSection);
|
fn disable_with_cs(cs: CriticalSection);
|
||||||
|
fn enable_bit() -> ClockEnableBit;
|
||||||
|
|
||||||
fn enable_and_reset() {
|
fn enable_and_reset() {
|
||||||
critical_section::with(|cs| Self::enable_and_reset_with_cs(cs))
|
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>() {
|
pub unsafe fn disable<T: RccPeripheral>() {
|
||||||
T::disable();
|
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…
Add table
Reference in a new issue