aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-06-14 16:22:14 +0200
committerGitHub <[email protected]>2021-06-14 16:22:14 +0200
commit0dafd8f763a65558b88b2c7d55c933863c481d39 (patch)
tree833f4531578d64e276765bcd23e3f8c6663c2602
parent85f172dd93227e637724d37e76bbcd7d886678f9 (diff)
parent531093f28189573818d5ebcfd4ccf56389d3972f (diff)
Merge pull request #241 from lulf/get-clock-frequencies
Provide a way for a peripheral to query its clock frequency
-rw-r--r--embassy-macros/src/chip/stm32.rs4
-rw-r--r--embassy-stm32/src/clock.rs4
-rw-r--r--embassy-stm32/src/rcc/f4/mod.rs205
-rw-r--r--embassy-stm32/src/rcc/h7/mod.rs17
-rw-r--r--embassy-stm32/src/rcc/l0/mod.rs160
-rw-r--r--embassy-stm32/src/rcc/l4/mod.rs204
-rw-r--r--embassy-stm32/src/rcc/mod.rs53
-rw-r--r--embassy-stm32/src/rcc/types.rs94
-rw-r--r--embassy-stm32/src/rcc/wb55/mod.rs204
-rw-r--r--embassy-stm32/src/spi/v1.rs2
-rw-r--r--embassy-stm32/src/spi/v2.rs2
-rw-r--r--embassy-stm32/src/spi/v3.rs2
-rw-r--r--examples/stm32f4/src/bin/spi.rs1
-rw-r--r--examples/stm32l0/src/bin/spi.rs1
-rw-r--r--examples/stm32l4/src/bin/spi.rs1
-rw-r--r--stm32-metapac/gen/src/lib.rs21
16 files changed, 804 insertions, 171 deletions
diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs
index 0a3a5abb9..9cd0111c9 100644
--- a/embassy-macros/src/chip/stm32.rs
+++ b/embassy-macros/src/chip/stm32.rs
@@ -17,9 +17,7 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream
17 ); 17 );
18 let clock = unsafe { make_static(&mut c) }; 18 let clock = unsafe { make_static(&mut c) };
19 19
20 // TODO: Is TIM2 always APB1? 20 clock.start();
21 let timer_freq = unsafe { #embassy_stm32_path::rcc::get_freqs().apb1_clk };
22 clock.start(timer_freq);
23 21
24 let mut alarm = clock.alarm1(); 22 let mut alarm = clock.alarm1();
25 unsafe { #embassy_path::time::set_clock(clock) }; 23 unsafe { #embassy_path::time::set_clock(clock) };
diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs
index 39a96402a..6c3175789 100644
--- a/embassy-stm32/src/clock.rs
+++ b/embassy-stm32/src/clock.rs
@@ -77,12 +77,14 @@ impl<T: Instance> Clock<T> {
77 } 77 }
78 } 78 }
79 79
80 pub fn start(&'static self, timer_freq: Hertz) { 80 pub fn start(&'static self) {
81 let inner = T::inner(); 81 let inner = T::inner();
82 82
83 T::enable(); 83 T::enable();
84 T::reset(); 84 T::reset();
85 85
86 let timer_freq = T::frequency();
87
86 // NOTE(unsafe) Critical section to use the unsafe methods 88 // NOTE(unsafe) Critical section to use the unsafe methods
87 critical_section::with(|_| { 89 critical_section::with(|_| {
88 unsafe { 90 unsafe {
diff --git a/embassy-stm32/src/rcc/f4/mod.rs b/embassy-stm32/src/rcc/f4/mod.rs
new file mode 100644
index 000000000..e8709b5fc
--- /dev/null
+++ b/embassy-stm32/src/rcc/f4/mod.rs
@@ -0,0 +1,205 @@
1pub use super::types::*;
2use crate::pac;
3use crate::peripherals::{self, RCC};
4use crate::rcc::{get_freqs, set_freqs, Clocks};
5use crate::time::Hertz;
6use crate::time::U32Ext;
7use core::marker::PhantomData;
8use embassy::util::Unborrow;
9use embassy_extras::unborrow;
10use pac::rcc::vals::{Hpre, Ppre, Sw};
11
12/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
13/// and with the addition of the init function to configure a system clock.
14
15/// Only the basic setup using the HSE and HSI clocks are supported as of now.
16
17/// HSI speed
18pub const HSI_FREQ: u32 = 16_000_000;
19
20/// System clock mux source
21#[derive(Clone, Copy)]
22pub enum ClockSrc {
23 HSE(Hertz),
24 HSI16,
25}
26
27impl Into<Ppre> for APBPrescaler {
28 fn into(self) -> Ppre {
29 match self {
30 APBPrescaler::NotDivided => Ppre::DIV1,
31 APBPrescaler::Div2 => Ppre::DIV2,
32 APBPrescaler::Div4 => Ppre::DIV4,
33 APBPrescaler::Div8 => Ppre::DIV8,
34 APBPrescaler::Div16 => Ppre::DIV16,
35 }
36 }
37}
38
39impl Into<Hpre> for AHBPrescaler {
40 fn into(self) -> Hpre {
41 match self {
42 AHBPrescaler::NotDivided => Hpre::DIV1,
43 AHBPrescaler::Div2 => Hpre::DIV2,
44 AHBPrescaler::Div4 => Hpre::DIV4,
45 AHBPrescaler::Div8 => Hpre::DIV8,
46 AHBPrescaler::Div16 => Hpre::DIV16,
47 AHBPrescaler::Div64 => Hpre::DIV64,
48 AHBPrescaler::Div128 => Hpre::DIV128,
49 AHBPrescaler::Div256 => Hpre::DIV256,
50 AHBPrescaler::Div512 => Hpre::DIV512,
51 }
52 }
53}
54
55/// Clocks configutation
56pub struct Config {
57 mux: ClockSrc,
58 ahb_pre: AHBPrescaler,
59 apb1_pre: APBPrescaler,
60 apb2_pre: APBPrescaler,
61}
62
63impl Default for Config {
64 #[inline]
65 fn default() -> Config {
66 Config {
67 mux: ClockSrc::HSI16,
68 ahb_pre: AHBPrescaler::NotDivided,
69 apb1_pre: APBPrescaler::NotDivided,
70 apb2_pre: APBPrescaler::NotDivided,
71 }
72 }
73}
74
75impl Config {
76 #[inline]
77 pub fn clock_src(mut self, mux: ClockSrc) -> Self {
78 self.mux = mux;
79 self
80 }
81
82 #[inline]
83 pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self {
84 self.ahb_pre = pre;
85 self
86 }
87
88 #[inline]
89 pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self {
90 self.apb1_pre = pre;
91 self
92 }
93
94 #[inline]
95 pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self {
96 self.apb2_pre = pre;
97 self
98 }
99}
100
101/// RCC peripheral
102pub struct Rcc<'d> {
103 _rb: peripherals::RCC,
104 phantom: PhantomData<&'d mut peripherals::RCC>,
105}
106
107impl<'d> Rcc<'d> {
108 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
109 unborrow!(rcc);
110 Self {
111 _rb: rcc,
112 phantom: PhantomData,
113 }
114 }
115
116 // Safety: RCC init must have been called
117 pub fn clocks(&self) -> &'static Clocks {
118 unsafe { get_freqs() }
119 }
120}
121
122/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
123pub trait RccExt {
124 fn freeze(self, config: Config) -> Clocks;
125}
126
127impl RccExt for RCC {
128 #[inline]
129 fn freeze(self, cfgr: Config) -> Clocks {
130 let rcc = pac::RCC;
131 let (sys_clk, sw) = match cfgr.mux {
132 ClockSrc::HSI16 => {
133 // Enable HSI16
134 unsafe {
135 rcc.cr().write(|w| w.set_hsion(true));
136 while !rcc.cr().read().hsirdy() {}
137 }
138
139 (HSI_FREQ, Sw::HSI)
140 }
141 ClockSrc::HSE(freq) => {
142 // Enable HSE
143 unsafe {
144 rcc.cr().write(|w| w.set_hseon(true));
145 while !rcc.cr().read().hserdy() {}
146 }
147
148 (freq.0, Sw::HSE)
149 }
150 };
151
152 unsafe {
153 rcc.cfgr().modify(|w| {
154 w.set_sw(sw.into());
155 w.set_hpre(cfgr.ahb_pre.into());
156 w.set_ppre1(cfgr.apb1_pre.into());
157 w.set_ppre2(cfgr.apb2_pre.into());
158 });
159 }
160
161 let ahb_freq: u32 = match cfgr.ahb_pre {
162 AHBPrescaler::NotDivided => sys_clk,
163 pre => {
164 let pre: Hpre = pre.into();
165 let pre = 1 << (pre.0 as u32 - 7);
166 sys_clk / pre
167 }
168 };
169
170 let apb1_freq = match cfgr.apb1_pre {
171 APBPrescaler::NotDivided => ahb_freq,
172 pre => {
173 let pre: Ppre = pre.into();
174 let pre: u8 = 1 << (pre.0 - 3);
175 let freq = ahb_freq / pre as u32;
176 freq
177 }
178 };
179
180 let apb2_freq = match cfgr.apb2_pre {
181 APBPrescaler::NotDivided => ahb_freq,
182 pre => {
183 let pre: Ppre = pre.into();
184 let pre: u8 = 1 << (pre.0 - 3);
185 let freq = ahb_freq / (1 << (pre as u8 - 3));
186 freq
187 }
188 };
189
190 Clocks {
191 sys: sys_clk.hz(),
192 ahb1: ahb_freq.hz(),
193 ahb2: ahb_freq.hz(),
194 ahb3: ahb_freq.hz(),
195 apb1: apb1_freq.hz(),
196 apb2: apb2_freq.hz(),
197 }
198 }
199}
200
201pub unsafe fn init(config: Config) {
202 let r = <peripherals::RCC as embassy::util::Steal>::steal();
203 let clocks = r.freeze(config);
204 set_freqs(clocks);
205}
diff --git a/embassy-stm32/src/rcc/h7/mod.rs b/embassy-stm32/src/rcc/h7/mod.rs
index f15dbe075..4bb50be3e 100644
--- a/embassy-stm32/src/rcc/h7/mod.rs
+++ b/embassy-stm32/src/rcc/h7/mod.rs
@@ -6,6 +6,7 @@ use crate::pac::rcc::vals::Timpre;
6use crate::pac::{DBGMCU, RCC, SYSCFG}; 6use crate::pac::{DBGMCU, RCC, SYSCFG};
7use crate::peripherals; 7use crate::peripherals;
8use crate::pwr::{Power, VoltageScale}; 8use crate::pwr::{Power, VoltageScale};
9use crate::rcc::{set_freqs, Clocks};
9use crate::time::Hertz; 10use crate::time::Hertz;
10 11
11mod pll; 12mod pll;
@@ -522,5 +523,17 @@ impl<'d> Rcc<'d> {
522 } 523 }
523} 524}
524 525
525// TODO 526pub unsafe fn init(config: Config) {
526pub unsafe fn init(_config: Config) {} 527 let mut power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal(), false);
528 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config);
529 let core_clocks = rcc.freeze(&mut power);
530 set_freqs(Clocks {
531 sys: core_clocks.c_ck,
532 ahb1: core_clocks.hclk,
533 ahb2: core_clocks.hclk,
534 ahb3: core_clocks.hclk,
535 apb1: core_clocks.pclk1,
536 apb2: core_clocks.pclk2,
537 apb4: core_clocks.pclk4,
538 });
539}
diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs
index d08c32b17..2d51c690f 100644
--- a/embassy-stm32/src/rcc/l0/mod.rs
+++ b/embassy-stm32/src/rcc/l0/mod.rs
@@ -1,3 +1,4 @@
1pub use super::types::*;
1use crate::pac; 2use crate::pac;
2use crate::peripherals::{self, CRS, RCC, SYSCFG}; 3use crate::peripherals::{self, CRS, RCC, SYSCFG};
3use crate::rcc::{get_freqs, set_freqs, Clocks}; 4use crate::rcc::{get_freqs, set_freqs, Clocks};
@@ -12,6 +13,9 @@ use pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
12/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 13/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
13/// and with the addition of the init function to configure a system clock. 14/// and with the addition of the init function to configure a system clock.
14 15
16/// HSI speed
17pub const HSI_FREQ: u32 = 16_000_000;
18
15/// System clock mux source 19/// System clock mux source
16#[derive(Clone, Copy)] 20#[derive(Clone, Copy)]
17pub enum ClockSrc { 21pub enum ClockSrc {
@@ -21,90 +25,6 @@ pub enum ClockSrc {
21 HSI16, 25 HSI16,
22} 26}
23 27
24/// MSI Clock Range
25///
26/// These ranges control the frequency of the MSI. Internally, these ranges map
27/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
28#[derive(Clone, Copy)]
29pub enum MSIRange {
30 /// Around 65.536 kHz
31 Range0,
32 /// Around 131.072 kHz
33 Range1,
34 /// Around 262.144 kHz
35 Range2,
36 /// Around 524.288 kHz
37 Range3,
38 /// Around 1.048 MHz
39 Range4,
40 /// Around 2.097 MHz (reset value)
41 Range5,
42 /// Around 4.194 MHz
43 Range6,
44}
45
46impl Default for MSIRange {
47 fn default() -> MSIRange {
48 MSIRange::Range5
49 }
50}
51
52/// PLL divider
53#[derive(Clone, Copy)]
54pub enum PLLDiv {
55 Div2,
56 Div3,
57 Div4,
58}
59
60/// PLL multiplier
61#[derive(Clone, Copy)]
62pub enum PLLMul {
63 Mul3,
64 Mul4,
65 Mul6,
66 Mul8,
67 Mul12,
68 Mul16,
69 Mul24,
70 Mul32,
71 Mul48,
72}
73
74/// AHB prescaler
75#[derive(Clone, Copy)]
76pub enum AHBPrescaler {
77 NotDivided,
78 Div2,
79 Div4,
80 Div8,
81 Div16,
82 Div64,
83 Div128,
84 Div256,
85 Div512,
86}
87
88/// APB prescaler
89#[derive(Clone, Copy)]
90pub enum APBPrescaler {
91 NotDivided,
92 Div2,
93 Div4,
94 Div8,
95 Div16,
96}
97
98/// PLL clock input source
99#[derive(Clone, Copy)]
100pub enum PLLSource {
101 HSI16,
102 HSE(Hertz),
103}
104
105/// HSI speed
106pub const HSI_FREQ: u32 = 16_000_000;
107
108impl Into<Pllmul> for PLLMul { 28impl Into<Pllmul> for PLLMul {
109 fn into(self) -> Pllmul { 29 fn into(self) -> Pllmul {
110 match self { 30 match self {
@@ -248,18 +168,6 @@ impl<'d> Rcc<'d> {
248 unsafe { get_freqs() } 168 unsafe { get_freqs() }
249 } 169 }
250 170
251 /*
252 pub fn enable_lse(&mut self, _: &PWR) -> LSE {
253 self.rb.csr.modify(|_, w| {
254 // Enable LSE clock
255 w.lseon().set_bit()
256 });
257 while self.rb.csr.read().lserdy().bit_is_clear() {}
258 LSE(())
259 }
260 }
261 */
262
263 pub fn enable_debug_wfe(&mut self, _dbg: &mut peripherals::DBGMCU, enable_dma: bool) { 171 pub fn enable_debug_wfe(&mut self, _dbg: &mut peripherals::DBGMCU, enable_dma: bool) {
264 // NOTE(unsafe) We have exclusive access to the RCC and DBGMCU 172 // NOTE(unsafe) We have exclusive access to the RCC and DBGMCU
265 unsafe { 173 unsafe {
@@ -319,30 +227,6 @@ impl<'d> Rcc<'d> {
319 HSI48(()) 227 HSI48(())
320 } 228 }
321} 229}
322/*
323
324impl Rcc {
325 /// Configure MCO (Microcontroller Clock Output).
326 pub fn configure_mco<P>(
327 &mut self,
328 source: MCOSEL_A,
329 prescaler: MCOPRE_A,
330 output_pin: P,
331 ) -> MCOEnabled
332 where
333 P: mco::Pin,
334 {
335 output_pin.into_mco();
336
337 self.rb.cfgr.modify(|_, w| {
338 w.mcosel().variant(source);
339 w.mcopre().variant(prescaler)
340 });
341
342 MCOEnabled(())
343 }
344}
345*/
346 230
347/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration 231/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
348pub trait RccExt { 232pub trait RccExt {
@@ -469,35 +353,31 @@ impl RccExt for RCC {
469 } 353 }
470 }; 354 };
471 355
472 let (apb1_freq, apb1_tim_freq, apb1_pre) = match cfgr.apb1_pre { 356 let apb1_freq = match cfgr.apb1_pre {
473 APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), 357 APBPrescaler::NotDivided => ahb_freq,
474 pre => { 358 pre => {
475 let pre: Ppre = pre.into(); 359 let pre: Ppre = pre.into();
476 let pre: u8 = 1 << (pre.0 - 3); 360 let pre: u8 = 1 << (pre.0 - 3);
477 let freq = ahb_freq / pre as u32; 361 let freq = ahb_freq / pre as u32;
478 (freq, freq * 2, pre as u8) 362 freq
479 } 363 }
480 }; 364 };
481 365
482 let (apb2_freq, apb2_tim_freq, apb2_pre) = match cfgr.apb2_pre { 366 let apb2_freq = match cfgr.apb2_pre {
483 APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1), 367 APBPrescaler::NotDivided => ahb_freq,
484 pre => { 368 pre => {
485 let pre: Ppre = pre.into(); 369 let pre: Ppre = pre.into();
486 let pre: u8 = 1 << (pre.0 - 3); 370 let pre: u8 = 1 << (pre.0 - 3);
487 let freq = ahb_freq / (1 << (pre as u8 - 3)); 371 let freq = ahb_freq / (1 << (pre as u8 - 3));
488 (freq, freq * 2, pre as u8) 372 freq
489 } 373 }
490 }; 374 };
491 375
492 Clocks { 376 Clocks {
493 sys_clk: sys_clk.hz(), 377 sys: sys_clk.hz(),
494 ahb_clk: ahb_freq.hz(), 378 ahb: ahb_freq.hz(),
495 apb1_clk: apb1_freq.hz(), 379 apb1: apb1_freq.hz(),
496 apb2_clk: apb2_freq.hz(), 380 apb2: apb2_freq.hz(),
497 apb1_tim_clk: apb1_tim_freq.hz(),
498 apb2_tim_clk: apb2_tim_freq.hz(),
499 apb1_pre,
500 apb2_pre,
501 } 381 }
502 } 382 }
503} 383}
@@ -508,18 +388,6 @@ impl RccExt for RCC {
508#[derive(Clone, Copy)] 388#[derive(Clone, Copy)]
509pub struct HSI48(()); 389pub struct HSI48(());
510 390
511/// Token that exists only if MCO (Microcontroller Clock Out) has been enabled.
512///
513/// You can get an instance of this struct by calling [`Rcc::configure_mco`].
514#[derive(Clone, Copy)]
515pub struct MCOEnabled(());
516
517/// Token that exists only, if the LSE clock has been enabled
518///
519/// You can get an instance of this struct by calling [`Rcc::enable_lse`].
520#[derive(Clone, Copy)]
521pub struct LSE(());
522
523pub unsafe fn init(config: Config) { 391pub unsafe fn init(config: Config) {
524 let rcc = pac::RCC; 392 let rcc = pac::RCC;
525 rcc.iopenr().write(|w| { 393 rcc.iopenr().write(|w| {
diff --git a/embassy-stm32/src/rcc/l4/mod.rs b/embassy-stm32/src/rcc/l4/mod.rs
new file mode 100644
index 000000000..9ae6d62b9
--- /dev/null
+++ b/embassy-stm32/src/rcc/l4/mod.rs
@@ -0,0 +1,204 @@
1pub use super::types::*;
2use crate::pac;
3use crate::peripherals::{self, RCC};
4use crate::rcc::{get_freqs, set_freqs, Clocks};
5use crate::time::Hertz;
6use crate::time::U32Ext;
7use core::marker::PhantomData;
8use embassy::util::Unborrow;
9use embassy_extras::unborrow;
10
11/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
12/// and with the addition of the init function to configure a system clock.
13
14/// Only the basic setup using the HSE and HSI clocks are supported as of now.
15
16/// HSI speed
17pub const HSI_FREQ: u32 = 16_000_000;
18
19/// System clock mux source
20#[derive(Clone, Copy)]
21pub enum ClockSrc {
22 HSE(Hertz),
23 HSI16,
24}
25
26impl Into<u8> for APBPrescaler {
27 fn into(self) -> u8 {
28 match self {
29 APBPrescaler::NotDivided => 1,
30 APBPrescaler::Div2 => 0x04,
31 APBPrescaler::Div4 => 0x05,
32 APBPrescaler::Div8 => 0x06,
33 APBPrescaler::Div16 => 0x07,
34 }
35 }
36}
37
38impl Into<u8> for AHBPrescaler {
39 fn into(self) -> u8 {
40 match self {
41 AHBPrescaler::NotDivided => 1,
42 AHBPrescaler::Div2 => 0x08,
43 AHBPrescaler::Div4 => 0x09,
44 AHBPrescaler::Div8 => 0x0a,
45 AHBPrescaler::Div16 => 0x0b,
46 AHBPrescaler::Div64 => 0x0c,
47 AHBPrescaler::Div128 => 0x0d,
48 AHBPrescaler::Div256 => 0x0e,
49 AHBPrescaler::Div512 => 0x0f,
50 }
51 }
52}
53
54/// Clocks configutation
55pub struct Config {
56 mux: ClockSrc,
57 ahb_pre: AHBPrescaler,
58 apb1_pre: APBPrescaler,
59 apb2_pre: APBPrescaler,
60}
61
62impl Default for Config {
63 #[inline]
64 fn default() -> Config {
65 Config {
66 mux: ClockSrc::HSI16,
67 ahb_pre: AHBPrescaler::NotDivided,
68 apb1_pre: APBPrescaler::NotDivided,
69 apb2_pre: APBPrescaler::NotDivided,
70 }
71 }
72}
73
74impl Config {
75 #[inline]
76 pub fn clock_src(mut self, mux: ClockSrc) -> Self {
77 self.mux = mux;
78 self
79 }
80
81 #[inline]
82 pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self {
83 self.ahb_pre = pre;
84 self
85 }
86
87 #[inline]
88 pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self {
89 self.apb1_pre = pre;
90 self
91 }
92
93 #[inline]
94 pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self {
95 self.apb2_pre = pre;
96 self
97 }
98}
99
100/// RCC peripheral
101pub struct Rcc<'d> {
102 _rb: peripherals::RCC,
103 phantom: PhantomData<&'d mut peripherals::RCC>,
104}
105
106impl<'d> Rcc<'d> {
107 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
108 unborrow!(rcc);
109 Self {
110 _rb: rcc,
111 phantom: PhantomData,
112 }
113 }
114
115 // Safety: RCC init must have been called
116 pub fn clocks(&self) -> &'static Clocks {
117 unsafe { get_freqs() }
118 }
119}
120
121/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
122pub trait RccExt {
123 fn freeze(self, config: Config) -> Clocks;
124}
125
126impl RccExt for RCC {
127 #[inline]
128 fn freeze(self, cfgr: Config) -> Clocks {
129 let rcc = pac::RCC;
130 let (sys_clk, sw) = match cfgr.mux {
131 ClockSrc::HSI16 => {
132 // Enable HSI16
133 unsafe {
134 rcc.cr().write(|w| w.set_hsion(true));
135 while !rcc.cr().read().hsirdy() {}
136 }
137
138 (HSI_FREQ, 0x01)
139 }
140 ClockSrc::HSE(freq) => {
141 // Enable HSE
142 unsafe {
143 rcc.cr().write(|w| w.set_hseon(true));
144 while !rcc.cr().read().hserdy() {}
145 }
146
147 (freq.0, 0x02)
148 }
149 };
150
151 unsafe {
152 rcc.cfgr().modify(|w| {
153 w.set_sw(sw.into());
154 w.set_hpre(cfgr.ahb_pre.into());
155 w.set_ppre1(cfgr.apb1_pre.into());
156 w.set_ppre2(cfgr.apb2_pre.into());
157 });
158 }
159
160 let ahb_freq: u32 = match cfgr.ahb_pre {
161 AHBPrescaler::NotDivided => sys_clk,
162 pre => {
163 let pre: u8 = pre.into();
164 let pre = 1 << (pre as u32 - 7);
165 sys_clk / pre
166 }
167 };
168
169 let apb1_freq = match cfgr.apb1_pre {
170 APBPrescaler::NotDivided => ahb_freq,
171 pre => {
172 let pre: u8 = pre.into();
173 let pre: u8 = 1 << (pre - 3);
174 let freq = ahb_freq / pre as u32;
175 freq
176 }
177 };
178
179 let apb2_freq = match cfgr.apb2_pre {
180 APBPrescaler::NotDivided => ahb_freq,
181 pre => {
182 let pre: u8 = pre.into();
183 let pre: u8 = 1 << (pre - 3);
184 let freq = ahb_freq / (1 << (pre as u8 - 3));
185 freq
186 }
187 };
188
189 Clocks {
190 sys: sys_clk.hz(),
191 ahb1: ahb_freq.hz(),
192 ahb2: ahb_freq.hz(),
193 ahb3: ahb_freq.hz(),
194 apb1: apb1_freq.hz(),
195 apb2: apb2_freq.hz(),
196 }
197 }
198}
199
200pub unsafe fn init(config: Config) {
201 let r = <peripherals::RCC as embassy::util::Steal>::steal();
202 let clocks = r.freeze(config);
203 set_freqs(clocks);
204}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 3c5b53b05..48bdb3de6 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -3,22 +3,33 @@
3use crate::peripherals; 3use crate::peripherals;
4use crate::time::Hertz; 4use crate::time::Hertz;
5use core::mem::MaybeUninit; 5use core::mem::MaybeUninit;
6mod types;
6 7
7/// Frozen clock frequencies
8///
9/// The existence of this value indicates that the clock configuration can no longer be changed
10#[derive(Clone, Copy)] 8#[derive(Clone, Copy)]
11pub struct Clocks { 9pub struct Clocks {
12 pub sys_clk: Hertz, 10 pub sys: Hertz,
13 pub ahb_clk: Hertz, 11 pub apb1: Hertz,
14 pub apb1_clk: Hertz, 12 pub apb2: Hertz,
15 pub apb1_tim_clk: Hertz, 13
16 pub apb2_clk: Hertz, 14 #[cfg(any(rcc_l0))]
17 pub apb2_tim_clk: Hertz, 15 pub ahb: Hertz,
18 pub apb1_pre: u8, 16
19 pub apb2_pre: u8, 17 #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55))]
18 pub ahb1: Hertz,
19
20 #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55))]
21 pub ahb2: Hertz,
22
23 #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb55))]
24 pub ahb3: Hertz,
25
26 #[cfg(any(rcc_h7))]
27 pub apb4: Hertz,
20} 28}
21 29
30/// Frozen clock frequencies
31///
32/// The existence of this value indicates that the clock configuration can no longer be changed
22static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); 33static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
23 34
24/// Sets the clock frequencies 35/// Sets the clock frequencies
@@ -40,6 +51,15 @@ cfg_if::cfg_if! {
40 } else if #[cfg(rcc_l0)] { 51 } else if #[cfg(rcc_l0)] {
41 mod l0; 52 mod l0;
42 pub use l0::*; 53 pub use l0::*;
54 } else if #[cfg(rcc_l4)] {
55 mod l4;
56 pub use l4::*;
57 } else if #[cfg(rcc_f4)] {
58 mod f4;
59 pub use f4::*;
60 } else if #[cfg(rcc_wb55)] {
61 mod wb55;
62 pub use wb55::*;
43 } else { 63 } else {
44 #[derive(Default)] 64 #[derive(Default)]
45 pub struct Config {} 65 pub struct Config {}
@@ -50,6 +70,7 @@ cfg_if::cfg_if! {
50 70
51pub(crate) mod sealed { 71pub(crate) mod sealed {
52 pub trait RccPeripheral { 72 pub trait RccPeripheral {
73 fn frequency() -> crate::time::Hertz;
53 fn reset(); 74 fn reset();
54 fn enable(); 75 fn enable();
55 fn disable(); 76 fn disable();
@@ -59,8 +80,16 @@ pub(crate) mod sealed {
59pub trait RccPeripheral: sealed::RccPeripheral + 'static {} 80pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
60 81
61crate::pac::peripheral_rcc!( 82crate::pac::peripheral_rcc!(
62 ($inst:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { 83 ($inst:ident, $clk:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => {
63 impl sealed::RccPeripheral for peripherals::$inst { 84 impl sealed::RccPeripheral for peripherals::$inst {
85 fn frequency() -> crate::time::Hertz {
86 critical_section::with(|_| {
87 unsafe {
88 let freqs = get_freqs();
89 freqs.$clk
90 }
91 })
92 }
64 fn enable() { 93 fn enable() {
65 critical_section::with(|_| { 94 critical_section::with(|_| {
66 unsafe { 95 unsafe {
diff --git a/embassy-stm32/src/rcc/types.rs b/embassy-stm32/src/rcc/types.rs
new file mode 100644
index 000000000..df7917ab3
--- /dev/null
+++ b/embassy-stm32/src/rcc/types.rs
@@ -0,0 +1,94 @@
1#![allow(dead_code)]
2/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
3/// and with the addition of the init function to configure a system clock.
4use crate::time::Hertz;
5
6/// System clock mux source
7#[derive(Clone, Copy)]
8pub enum ClockSrc {
9 MSI(MSIRange),
10 PLL(PLLSource, PLLMul, PLLDiv),
11 HSE(Hertz),
12 HSI16,
13}
14
15/// MSI Clock Range
16///
17/// These ranges control the frequency of the MSI. Internally, these ranges map
18/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
19#[derive(Clone, Copy)]
20pub enum MSIRange {
21 /// Around 65.536 kHz
22 Range0,
23 /// Around 131.072 kHz
24 Range1,
25 /// Around 262.144 kHz
26 Range2,
27 /// Around 524.288 kHz
28 Range3,
29 /// Around 1.048 MHz
30 Range4,
31 /// Around 2.097 MHz (reset value)
32 Range5,
33 /// Around 4.194 MHz
34 Range6,
35}
36
37impl Default for MSIRange {
38 fn default() -> MSIRange {
39 MSIRange::Range5
40 }
41}
42
43/// PLL divider
44#[derive(Clone, Copy)]
45pub enum PLLDiv {
46 Div2,
47 Div3,
48 Div4,
49}
50
51/// PLL multiplier
52#[derive(Clone, Copy)]
53pub enum PLLMul {
54 Mul3,
55 Mul4,
56 Mul6,
57 Mul8,
58 Mul12,
59 Mul16,
60 Mul24,
61 Mul32,
62 Mul48,
63}
64
65/// AHB prescaler
66#[derive(Clone, Copy)]
67pub enum AHBPrescaler {
68 NotDivided,
69 Div2,
70 Div4,
71 Div8,
72 Div16,
73 Div64,
74 Div128,
75 Div256,
76 Div512,
77}
78
79/// APB prescaler
80#[derive(Clone, Copy)]
81pub enum APBPrescaler {
82 NotDivided,
83 Div2,
84 Div4,
85 Div8,
86 Div16,
87}
88
89/// PLL clock input source
90#[derive(Clone, Copy)]
91pub enum PLLSource {
92 HSI16,
93 HSE(Hertz),
94}
diff --git a/embassy-stm32/src/rcc/wb55/mod.rs b/embassy-stm32/src/rcc/wb55/mod.rs
new file mode 100644
index 000000000..9ae6d62b9
--- /dev/null
+++ b/embassy-stm32/src/rcc/wb55/mod.rs
@@ -0,0 +1,204 @@
1pub use super::types::*;
2use crate::pac;
3use crate::peripherals::{self, RCC};
4use crate::rcc::{get_freqs, set_freqs, Clocks};
5use crate::time::Hertz;
6use crate::time::U32Ext;
7use core::marker::PhantomData;
8use embassy::util::Unborrow;
9use embassy_extras::unborrow;
10
11/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
12/// and with the addition of the init function to configure a system clock.
13
14/// Only the basic setup using the HSE and HSI clocks are supported as of now.
15
16/// HSI speed
17pub const HSI_FREQ: u32 = 16_000_000;
18
19/// System clock mux source
20#[derive(Clone, Copy)]
21pub enum ClockSrc {
22 HSE(Hertz),
23 HSI16,
24}
25
26impl Into<u8> for APBPrescaler {
27 fn into(self) -> u8 {
28 match self {
29 APBPrescaler::NotDivided => 1,
30 APBPrescaler::Div2 => 0x04,
31 APBPrescaler::Div4 => 0x05,
32 APBPrescaler::Div8 => 0x06,
33 APBPrescaler::Div16 => 0x07,
34 }
35 }
36}
37
38impl Into<u8> for AHBPrescaler {
39 fn into(self) -> u8 {
40 match self {
41 AHBPrescaler::NotDivided => 1,
42 AHBPrescaler::Div2 => 0x08,
43 AHBPrescaler::Div4 => 0x09,
44 AHBPrescaler::Div8 => 0x0a,
45 AHBPrescaler::Div16 => 0x0b,
46 AHBPrescaler::Div64 => 0x0c,
47 AHBPrescaler::Div128 => 0x0d,
48 AHBPrescaler::Div256 => 0x0e,
49 AHBPrescaler::Div512 => 0x0f,
50 }
51 }
52}
53
54/// Clocks configutation
55pub struct Config {
56 mux: ClockSrc,
57 ahb_pre: AHBPrescaler,
58 apb1_pre: APBPrescaler,
59 apb2_pre: APBPrescaler,
60}
61
62impl Default for Config {
63 #[inline]
64 fn default() -> Config {
65 Config {
66 mux: ClockSrc::HSI16,
67 ahb_pre: AHBPrescaler::NotDivided,
68 apb1_pre: APBPrescaler::NotDivided,
69 apb2_pre: APBPrescaler::NotDivided,
70 }
71 }
72}
73
74impl Config {
75 #[inline]
76 pub fn clock_src(mut self, mux: ClockSrc) -> Self {
77 self.mux = mux;
78 self
79 }
80
81 #[inline]
82 pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self {
83 self.ahb_pre = pre;
84 self
85 }
86
87 #[inline]
88 pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self {
89 self.apb1_pre = pre;
90 self
91 }
92
93 #[inline]
94 pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self {
95 self.apb2_pre = pre;
96 self
97 }
98}
99
100/// RCC peripheral
101pub struct Rcc<'d> {
102 _rb: peripherals::RCC,
103 phantom: PhantomData<&'d mut peripherals::RCC>,
104}
105
106impl<'d> Rcc<'d> {
107 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
108 unborrow!(rcc);
109 Self {
110 _rb: rcc,
111 phantom: PhantomData,
112 }
113 }
114
115 // Safety: RCC init must have been called
116 pub fn clocks(&self) -> &'static Clocks {
117 unsafe { get_freqs() }
118 }
119}
120
121/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
122pub trait RccExt {
123 fn freeze(self, config: Config) -> Clocks;
124}
125
126impl RccExt for RCC {
127 #[inline]
128 fn freeze(self, cfgr: Config) -> Clocks {
129 let rcc = pac::RCC;
130 let (sys_clk, sw) = match cfgr.mux {
131 ClockSrc::HSI16 => {
132 // Enable HSI16
133 unsafe {
134 rcc.cr().write(|w| w.set_hsion(true));
135 while !rcc.cr().read().hsirdy() {}
136 }
137
138 (HSI_FREQ, 0x01)
139 }
140 ClockSrc::HSE(freq) => {
141 // Enable HSE
142 unsafe {
143 rcc.cr().write(|w| w.set_hseon(true));
144 while !rcc.cr().read().hserdy() {}
145 }
146
147 (freq.0, 0x02)
148 }
149 };
150
151 unsafe {
152 rcc.cfgr().modify(|w| {
153 w.set_sw(sw.into());
154 w.set_hpre(cfgr.ahb_pre.into());
155 w.set_ppre1(cfgr.apb1_pre.into());
156 w.set_ppre2(cfgr.apb2_pre.into());
157 });
158 }
159
160 let ahb_freq: u32 = match cfgr.ahb_pre {
161 AHBPrescaler::NotDivided => sys_clk,
162 pre => {
163 let pre: u8 = pre.into();
164 let pre = 1 << (pre as u32 - 7);
165 sys_clk / pre
166 }
167 };
168
169 let apb1_freq = match cfgr.apb1_pre {
170 APBPrescaler::NotDivided => ahb_freq,
171 pre => {
172 let pre: u8 = pre.into();
173 let pre: u8 = 1 << (pre - 3);
174 let freq = ahb_freq / pre as u32;
175 freq
176 }
177 };
178
179 let apb2_freq = match cfgr.apb2_pre {
180 APBPrescaler::NotDivided => ahb_freq,
181 pre => {
182 let pre: u8 = pre.into();
183 let pre: u8 = 1 << (pre - 3);
184 let freq = ahb_freq / (1 << (pre as u8 - 3));
185 freq
186 }
187 };
188
189 Clocks {
190 sys: sys_clk.hz(),
191 ahb1: ahb_freq.hz(),
192 ahb2: ahb_freq.hz(),
193 ahb3: ahb_freq.hz(),
194 apb1: apb1_freq.hz(),
195 apb2: apb2_freq.hz(),
196 }
197 }
198}
199
200pub unsafe fn init(config: Config) {
201 let r = <peripherals::RCC as embassy::util::Steal>::steal();
202 let clocks = r.freeze(config);
203 set_freqs(clocks);
204}
diff --git a/embassy-stm32/src/spi/v1.rs b/embassy-stm32/src/spi/v1.rs
index 227a36a89..01cbf86b6 100644
--- a/embassy-stm32/src/spi/v1.rs
+++ b/embassy-stm32/src/spi/v1.rs
@@ -29,7 +29,6 @@ pub struct Spi<'d, T: Instance> {
29 29
30impl<'d, T: Instance> Spi<'d, T> { 30impl<'d, T: Instance> Spi<'d, T> {
31 pub fn new<F>( 31 pub fn new<F>(
32 pclk: Hertz,
33 _peri: impl Unborrow<Target = T> + 'd, 32 _peri: impl Unborrow<Target = T> + 'd,
34 sck: impl Unborrow<Target = impl SckPin<T>>, 33 sck: impl Unborrow<Target = impl SckPin<T>>,
35 mosi: impl Unborrow<Target = impl MosiPin<T>>, 34 mosi: impl Unborrow<Target = impl MosiPin<T>>,
@@ -58,6 +57,7 @@ impl<'d, T: Instance> Spi<'d, T> {
58 }); 57 });
59 } 58 }
60 59
60 let pclk = T::frequency();
61 let br = Self::compute_baud_rate(pclk, freq.into()); 61 let br = Self::compute_baud_rate(pclk, freq.into());
62 62
63 unsafe { 63 unsafe {
diff --git a/embassy-stm32/src/spi/v2.rs b/embassy-stm32/src/spi/v2.rs
index a7ac54cdd..4e135e9df 100644
--- a/embassy-stm32/src/spi/v2.rs
+++ b/embassy-stm32/src/spi/v2.rs
@@ -37,7 +37,6 @@ pub struct Spi<'d, T: Instance> {
37 37
38impl<'d, T: Instance> Spi<'d, T> { 38impl<'d, T: Instance> Spi<'d, T> {
39 pub fn new<F>( 39 pub fn new<F>(
40 pclk: Hertz,
41 _peri: impl Unborrow<Target = T> + 'd, 40 _peri: impl Unborrow<Target = T> + 'd,
42 sck: impl Unborrow<Target = impl SckPin<T>>, 41 sck: impl Unborrow<Target = impl SckPin<T>>,
43 mosi: impl Unborrow<Target = impl MosiPin<T>>, 42 mosi: impl Unborrow<Target = impl MosiPin<T>>,
@@ -60,6 +59,7 @@ impl<'d, T: Instance> Spi<'d, T> {
60 let mosi = mosi.degrade(); 59 let mosi = mosi.degrade();
61 let miso = miso.degrade(); 60 let miso = miso.degrade();
62 61
62 let pclk = T::frequency();
63 let br = Self::compute_baud_rate(pclk, freq.into()); 63 let br = Self::compute_baud_rate(pclk, freq.into());
64 64
65 unsafe { 65 unsafe {
diff --git a/embassy-stm32/src/spi/v3.rs b/embassy-stm32/src/spi/v3.rs
index 6073616bd..0b4a71457 100644
--- a/embassy-stm32/src/spi/v3.rs
+++ b/embassy-stm32/src/spi/v3.rs
@@ -37,7 +37,6 @@ pub struct Spi<'d, T: Instance> {
37 37
38impl<'d, T: Instance> Spi<'d, T> { 38impl<'d, T: Instance> Spi<'d, T> {
39 pub fn new<F>( 39 pub fn new<F>(
40 pclk: Hertz,
41 _peri: impl Unborrow<Target = T> + 'd, 40 _peri: impl Unborrow<Target = T> + 'd,
42 sck: impl Unborrow<Target = impl SckPin<T>>, 41 sck: impl Unborrow<Target = impl SckPin<T>>,
43 mosi: impl Unborrow<Target = impl MosiPin<T>>, 42 mosi: impl Unborrow<Target = impl MosiPin<T>>,
@@ -62,6 +61,7 @@ impl<'d, T: Instance> Spi<'d, T> {
62 let mosi = mosi.degrade(); 61 let mosi = mosi.degrade();
63 let miso = miso.degrade(); 62 let miso = miso.degrade();
64 63
64 let pclk = T::frequency();
65 let br = Self::compute_baud_rate(pclk, freq.into()); 65 let br = Self::compute_baud_rate(pclk, freq.into());
66 unsafe { 66 unsafe {
67 T::enable(); 67 T::enable();
diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs
index af0d57412..610bb64e9 100644
--- a/examples/stm32f4/src/bin/spi.rs
+++ b/examples/stm32f4/src/bin/spi.rs
@@ -50,7 +50,6 @@ fn main() -> ! {
50 let p = embassy_stm32::init(Default::default()); 50 let p = embassy_stm32::init(Default::default());
51 51
52 let mut spi = Spi::new( 52 let mut spi = Spi::new(
53 Hertz(16_000_000),
54 p.SPI3, 53 p.SPI3,
55 p.PC10, 54 p.PC10,
56 p.PC12, 55 p.PC12,
diff --git a/examples/stm32l0/src/bin/spi.rs b/examples/stm32l0/src/bin/spi.rs
index 4eb9bfdd2..0e828c436 100644
--- a/examples/stm32l0/src/bin/spi.rs
+++ b/examples/stm32l0/src/bin/spi.rs
@@ -28,7 +28,6 @@ fn main() -> ! {
28 rcc.enable_debug_wfe(&mut p.DBGMCU, true); 28 rcc.enable_debug_wfe(&mut p.DBGMCU, true);
29 29
30 let mut spi = Spi::new( 30 let mut spi = Spi::new(
31 Hertz(16_000_000),
32 p.SPI1, 31 p.SPI1,
33 p.PB3, 32 p.PB3,
34 p.PA7, 33 p.PA7,
diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs
index 9db854dc3..7c672b70d 100644
--- a/examples/stm32l4/src/bin/spi.rs
+++ b/examples/stm32l4/src/bin/spi.rs
@@ -44,7 +44,6 @@ fn main() -> ! {
44 let p = embassy_stm32::init(Default::default()); 44 let p = embassy_stm32::init(Default::default());
45 45
46 let mut spi = Spi::new( 46 let mut spi = Spi::new(
47 Hertz(16_000_000),
48 p.SPI3, 47 p.SPI3,
49 p.PC10, 48 p.PC10,
50 p.PC12, 49 p.PC12,
diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs
index 399840c5b..5133aef9a 100644
--- a/stm32-metapac/gen/src/lib.rs
+++ b/stm32-metapac/gen/src/lib.rs
@@ -84,7 +84,11 @@ fn find_reg_for_field<'c>(
84 field_name: &str, 84 field_name: &str,
85) -> Option<(&'c str, &'c str)> { 85) -> Option<(&'c str, &'c str)> {
86 rcc.fieldsets.iter().find_map(|(name, fieldset)| { 86 rcc.fieldsets.iter().find_map(|(name, fieldset)| {
87 if name.starts_with(reg_prefix) { 87 // Workaround for some families that prefix register aliases with C1_, which does
88 // not help matching for clock name.
89 if name.starts_with("C1") || name.starts_with("C2") {
90 None
91 } else if name.starts_with(reg_prefix) {
88 fieldset 92 fieldset
89 .fields 93 .fields
90 .iter() 94 .iter()
@@ -287,8 +291,23 @@ pub fn gen(options: Options) {
287 291
288 match (en, rst) { 292 match (en, rst) {
289 (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => { 293 (Some((enable_reg, enable_field)), Some((reset_reg, reset_field))) => {
294 let clock = if clock_prefix == "" {
295 let re = Regex::new("([A-Z]+\\d*).*").unwrap();
296 if !re.is_match(enable_reg) {
297 panic!(
298 "unable to derive clock name from register name {}",
299 enable_reg
300 );
301 } else {
302 let caps = re.captures(enable_reg).unwrap();
303 caps.get(1).unwrap().as_str()
304 }
305 } else {
306 clock_prefix
307 };
290 peripheral_rcc_table.push(vec![ 308 peripheral_rcc_table.push(vec![
291 name.clone(), 309 name.clone(),
310 clock.to_ascii_lowercase(),
292 enable_reg.to_ascii_lowercase(), 311 enable_reg.to_ascii_lowercase(),
293 reset_reg.to_ascii_lowercase(), 312 reset_reg.to_ascii_lowercase(),
294 format!("set_{}", enable_field.to_ascii_lowercase()), 313 format!("set_{}", enable_field.to_ascii_lowercase()),