diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-05-20 23:36:21 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-05-20 23:37:20 +0200 |
| commit | eeb6ffce4cfa0e0055da8d6738f6d28c3fa43f15 (patch) | |
| tree | b6cb52689168a50e2d7e93c70830c3da75eb21b5 | |
| parent | 8e7361f4ca1fe0917eeefaeaced571e6395c265b (diff) | |
stm32/rcc: add ClockEnableBit struct.
| -rw-r--r-- | embassy-stm32/build.rs | 32 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 50 |
2 files changed, 81 insertions, 1 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index dbc8f9153..f17c6bef6 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -7,6 +7,7 @@ use std::{env, fs}; | |||
| 7 | 7 | ||
| 8 | use proc_macro2::{Ident, TokenStream}; | 8 | use proc_macro2::{Ident, TokenStream}; |
| 9 | use quote::{format_ident, quote}; | 9 | use quote::{format_ident, quote}; |
| 10 | use stm32_metapac::metadata::ir::BitOffset; | ||
| 10 | use stm32_metapac::metadata::{ | 11 | use stm32_metapac::metadata::{ |
| 11 | MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, METADATA, | 12 | MemoryRegionKind, PeripheralRccKernelClock, PeripheralRccRegister, PeripheralRegisters, StopMode, METADATA, |
| 12 | }; | 13 | }; |
| @@ -359,12 +360,17 @@ fn main() { | |||
| 359 | 360 | ||
| 360 | // ======== | 361 | // ======== |
| 361 | // Extract the rcc registers | 362 | // Extract the rcc registers |
| 363 | |||
| 362 | let rcc_registers = METADATA | 364 | let rcc_registers = METADATA |
| 363 | .peripherals | 365 | .peripherals |
| 364 | .iter() | 366 | .iter() |
| 365 | .filter_map(|p| p.registers.as_ref()) | 367 | .filter_map(|p| p.registers.as_ref()) |
| 366 | .find(|r| r.kind == "rcc") | 368 | .find(|r| r.kind == "rcc") |
| 367 | .unwrap(); | 369 | .unwrap(); |
| 370 | for b in rcc_registers.ir.blocks { | ||
| 371 | eprintln!("{}", b.name); | ||
| 372 | } | ||
| 373 | let rcc_block = rcc_registers.ir.blocks.iter().find(|b| b.name == "Rcc").unwrap(); | ||
| 368 | 374 | ||
| 369 | // ======== | 375 | // ======== |
| 370 | // Generate RccPeripheral impls | 376 | // Generate RccPeripheral impls |
| @@ -540,6 +546,29 @@ fn main() { | |||
| 540 | let pname = format_ident!("{}", p.name); | 546 | let pname = format_ident!("{}", p.name); |
| 541 | let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); | 547 | let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); |
| 542 | let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); | 548 | let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); |
| 549 | let en_reg_offs = rcc_block | ||
| 550 | .items | ||
| 551 | .iter() | ||
| 552 | .find(|i| i.name.eq_ignore_ascii_case(en.register)) | ||
| 553 | .unwrap() | ||
| 554 | .byte_offset; | ||
| 555 | let en_reg_offs: u8 = (en_reg_offs / 4).try_into().unwrap(); | ||
| 556 | |||
| 557 | let en_bit_offs = &rcc_registers | ||
| 558 | .ir | ||
| 559 | .fieldsets | ||
| 560 | .iter() | ||
| 561 | .find(|i| i.name.eq_ignore_ascii_case(en.register)) | ||
| 562 | .unwrap() | ||
| 563 | .fields | ||
| 564 | .iter() | ||
| 565 | .find(|i| i.name.eq_ignore_ascii_case(en.field)) | ||
| 566 | .unwrap() | ||
| 567 | .bit_offset; | ||
| 568 | let BitOffset::Regular(en_bit_offs) = en_bit_offs else { | ||
| 569 | panic!("cursed bit offset") | ||
| 570 | }; | ||
| 571 | let en_bit_offs: u8 = en_bit_offs.offset.try_into().unwrap(); | ||
| 543 | 572 | ||
| 544 | let refcount = | 573 | let refcount = |
| 545 | clock_gen.force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1; | 574 | clock_gen.force_refcount.contains(ptype) || *rcc_field_count.get(&(en.register, en.field)).unwrap() > 1; |
| @@ -624,6 +653,9 @@ fn main() { | |||
| 624 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); | 653 | crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); |
| 625 | #decr_stop_refcount | 654 | #decr_stop_refcount |
| 626 | } | 655 | } |
| 656 | fn enable_bit() -> crate::rcc::ClockEnableBit { | ||
| 657 | unsafe { crate::rcc::ClockEnableBit::new(#en_reg_offs, #en_bit_offs) } | ||
| 658 | } | ||
| 627 | } | 659 | } |
| 628 | 660 | ||
| 629 | impl crate::rcc::RccPeripheral for peripherals::#pname {} | 661 | impl crate::rcc::RccPeripheral for peripherals::#pname {} |
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index a585940bc..c413b62ef 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -31,6 +31,7 @@ pub use hsi48::*; | |||
| 31 | mod _version; | 31 | mod _version; |
| 32 | 32 | ||
| 33 | pub use _version::*; | 33 | pub use _version::*; |
| 34 | use stm32_metapac::RCC; | ||
| 34 | 35 | ||
| 35 | pub use crate::_generated::{mux, Clocks}; | 36 | pub use crate::_generated::{mux, Clocks}; |
| 36 | use crate::time::Hertz; | 37 | use crate::time::Hertz; |
| @@ -66,9 +67,10 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks { | |||
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | pub(crate) trait SealedRccPeripheral { | 69 | pub(crate) trait SealedRccPeripheral { |
| 69 | fn frequency() -> crate::time::Hertz; | 70 | fn frequency() -> Hertz; |
| 70 | fn enable_and_reset_with_cs(cs: CriticalSection); | 71 | fn enable_and_reset_with_cs(cs: CriticalSection); |
| 71 | fn disable_with_cs(cs: CriticalSection); | 72 | fn disable_with_cs(cs: CriticalSection); |
| 73 | fn enable_bit() -> ClockEnableBit; | ||
| 72 | 74 | ||
| 73 | fn enable_and_reset() { | 75 | fn enable_and_reset() { |
| 74 | critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) | 76 | critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) |
| @@ -137,3 +139,49 @@ pub unsafe fn enable_and_reset<T: RccPeripheral>() { | |||
| 137 | pub unsafe fn disable<T: RccPeripheral>() { | 139 | pub unsafe fn disable<T: RccPeripheral>() { |
| 138 | T::disable(); | 140 | T::disable(); |
| 139 | } | 141 | } |
| 142 | |||
| 143 | /// Struct representing some clock enable bit (xxxENR.xxEN), only known at runtime. | ||
| 144 | #[derive(Clone, Copy)] | ||
| 145 | pub(crate) struct ClockEnableBit { | ||
| 146 | /// offset in 32bit words of the xxxENR register into the RCC register block. | ||
| 147 | offset: u8, | ||
| 148 | /// bit within the register (0..=31) | ||
| 149 | bit: u8, | ||
| 150 | } | ||
| 151 | |||
| 152 | impl ClockEnableBit { | ||
| 153 | /// Safety: offset+bit must correspond to a valid xxxEN bit. | ||
| 154 | pub(crate) unsafe fn new(offset: u8, bit: u8) -> Self { | ||
| 155 | Self { offset, bit } | ||
| 156 | } | ||
| 157 | |||
| 158 | fn ptr(self) -> *mut u32 { | ||
| 159 | unsafe { (RCC.as_ptr() as *mut u32).add(self.offset as _) } | ||
| 160 | } | ||
| 161 | |||
| 162 | #[allow(unused)] | ||
| 163 | pub(crate) fn enable_with_cs(self, _cs: CriticalSection) { | ||
| 164 | let p = self.ptr(); | ||
| 165 | unsafe { | ||
| 166 | let val = p.read_volatile(); | ||
| 167 | p.write_volatile(val | 1u32 << self.bit); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | pub(crate) fn disable_with_cs(self, _cs: CriticalSection) { | ||
| 172 | let p = self.ptr(); | ||
| 173 | unsafe { | ||
| 174 | let val = p.read_volatile(); | ||
| 175 | p.write_volatile(val & !(1u32 << self.bit)); | ||
| 176 | } | ||
| 177 | } | ||
| 178 | |||
| 179 | #[allow(unused)] | ||
| 180 | pub(crate) fn enable(self) { | ||
| 181 | critical_section::with(|cs| self.enable_with_cs(cs)) | ||
| 182 | } | ||
| 183 | |||
| 184 | pub(crate) fn disable(self) { | ||
| 185 | critical_section::with(|cs| self.disable_with_cs(cs)) | ||
| 186 | } | ||
| 187 | } | ||
