aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-05-20 23:36:21 +0200
committerDario Nieuwenhuis <[email protected]>2024-05-20 23:37:20 +0200
commiteeb6ffce4cfa0e0055da8d6738f6d28c3fa43f15 (patch)
treeb6cb52689168a50e2d7e93c70830c3da75eb21b5 /embassy-stm32
parent8e7361f4ca1fe0917eeefaeaced571e6395c265b (diff)
stm32/rcc: add ClockEnableBit struct.
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/build.rs32
-rw-r--r--embassy-stm32/src/rcc/mod.rs50
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
8use proc_macro2::{Ident, TokenStream}; 8use proc_macro2::{Ident, TokenStream};
9use quote::{format_ident, quote}; 9use quote::{format_ident, quote};
10use stm32_metapac::metadata::ir::BitOffset;
10use stm32_metapac::metadata::{ 11use 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::*;
31mod _version; 31mod _version;
32 32
33pub use _version::*; 33pub use _version::*;
34use stm32_metapac::RCC;
34 35
35pub use crate::_generated::{mux, Clocks}; 36pub use crate::_generated::{mux, Clocks};
36use crate::time::Hertz; 37use crate::time::Hertz;
@@ -66,9 +67,10 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks {
66} 67}
67 68
68pub(crate) trait SealedRccPeripheral { 69pub(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>() {
137pub unsafe fn disable<T: RccPeripheral>() { 139pub 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)]
145pub(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
152impl 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}