stm32/rcc: add ClockEnableBit struct.

This commit is contained in:
Dario Nieuwenhuis 2024-05-20 23:36:21 +02:00
parent 8e7361f4ca
commit eeb6ffce4c
2 changed files with 81 additions and 1 deletions

View File

@ -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 {}

View File

@ -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))
}
}