1use crate::stm32::{rcc, FLASH, PWR, RCC};
2use crate::time::Hertz;
3use fugit::RateExtU32;
4
5mod clockout;
6mod config;
7mod enable;
8
9pub use clockout::*;
10pub use config::*;
11
12pub const HSI_FREQ: u32 = 16_000_000;
14
15#[derive(Clone, Copy)]
17pub struct Clocks {
18 pub sys_clk: Hertz,
20 pub core_clk: Hertz,
22 pub ahb_clk: Hertz,
24 pub apb_clk: Hertz,
26 pub apb_tim_clk: Hertz,
28 pub pll_clk: PLLClocks,
30}
31
32#[derive(Clone, Copy)]
34pub struct PLLClocks {
35 pub r: Hertz,
37 pub q: Option<Hertz>,
39 pub p: Option<Hertz>,
41}
42
43impl Default for Clocks {
44 fn default() -> Clocks {
45 Clocks {
46 sys_clk: 16.MHz(),
47 ahb_clk: 16.MHz(),
48 core_clk: 2.MHz(),
49 apb_clk: 16.MHz(),
50 apb_tim_clk: 16.MHz(),
51 pll_clk: PLLClocks {
52 r: 64.MHz(),
53 q: None,
54 p: None,
55 },
56 }
57 }
58}
59
60pub enum ResetMode {
62 ResetInput = 0b01,
64 GPIO = 0b10,
66 Bidirectional = 0b11,
68}
69
70pub struct Rcc {
72 pub clocks: Clocks,
74 pub(crate) rb: RCC,
75}
76
77impl core::ops::Deref for Rcc {
78 type Target = RCC;
79
80 #[inline(always)]
81 fn deref(&self) -> &Self::Target {
82 &self.rb
83 }
84}
85
86impl Rcc {
87 pub fn freeze(self, rcc_cfg: Config) -> Self {
89 let pll_clk = self.config_pll(rcc_cfg.pll_cfg);
90
91 let (sys_clk, sw_bits) = match rcc_cfg.sys_mux {
92 SysClockSrc::HSE(freq) => {
93 self.enable_hse(false);
94 (freq, 0b001)
95 }
96 SysClockSrc::HSE_BYPASS(freq) => {
97 self.enable_hse(true);
98 (freq, 0b001)
99 }
100 SysClockSrc::PLL => (pll_clk.r, 0b010),
101 SysClockSrc::LSE(freq) => {
102 self.enable_lse(false);
103 (freq, 0b100)
104 }
105 SysClockSrc::LSE_BYPASS(freq) => {
106 self.enable_lse(true);
107 (freq, 0b100)
108 }
109 SysClockSrc::LSI => {
110 self.enable_lsi();
111 (32_768.Hz(), 0b011)
112 }
113 SysClockSrc::HSI(prs) => {
114 self.enable_hsi();
115 let (freq, div_bits) = match prs {
116 Prescaler::Div2 => (HSI_FREQ / 2, 0b001),
117 Prescaler::Div4 => (HSI_FREQ / 4, 0b010),
118 Prescaler::Div8 => (HSI_FREQ / 8, 0b011),
119 Prescaler::Div16 => (HSI_FREQ / 16, 0b100),
120 Prescaler::Div32 => (HSI_FREQ / 32, 0b101),
121 Prescaler::Div64 => (HSI_FREQ / 64, 0b110),
122 Prescaler::Div128 => (HSI_FREQ / 128, 0b111),
123 _ => (HSI_FREQ, 0b000),
124 };
125 self.cr.write(|w| unsafe { w.hsidiv().bits(div_bits) });
126 (freq.Hz(), 0b000)
127 }
128 };
129
130 let sys_freq = sys_clk.raw();
131 let (ahb_freq, ahb_psc_bits) = match rcc_cfg.ahb_psc {
132 Prescaler::Div2 => (sys_freq / 2, 0b1000),
133 Prescaler::Div4 => (sys_freq / 4, 0b1001),
134 Prescaler::Div8 => (sys_freq / 8, 0b1010),
135 Prescaler::Div16 => (sys_freq / 16, 0b1011),
136 Prescaler::Div64 => (sys_freq / 64, 0b1100),
137 Prescaler::Div128 => (sys_freq / 128, 0b1101),
138 Prescaler::Div256 => (sys_freq / 256, 0b1110),
139 Prescaler::Div512 => (sys_freq / 512, 0b1111),
140 _ => (sys_clk.raw(), 0b0000),
141 };
142 let (apb_freq, apb_tim_freq, apb_psc_bits) = match rcc_cfg.apb_psc {
143 Prescaler::Div2 => (ahb_freq / 2, ahb_freq, 0b100),
144 Prescaler::Div4 => (ahb_freq / 4, ahb_freq / 2, 0b101),
145 Prescaler::Div8 => (ahb_freq / 8, ahb_freq / 4, 0b110),
146 Prescaler::Div16 => (ahb_freq / 16, ahb_freq / 8, 0b111),
147 _ => (ahb_freq, ahb_freq, 0b000),
148 };
149
150 unsafe {
151 let flash = &(*FLASH::ptr());
153 flash.acr.modify(|_, w| {
154 w.latency().bits(if sys_clk.raw() <= 24_000_000 {
155 0b000
156 } else if sys_clk.raw() <= 48_000_000 {
157 0b001
158 } else {
159 0b010
160 })
161 })
162 }
163
164 self.cfgr.modify(|_, w| unsafe {
165 w.hpre()
166 .bits(ahb_psc_bits)
167 .ppre()
168 .bits(apb_psc_bits)
169 .sw()
170 .bits(sw_bits)
171 });
172
173 while self.cfgr.read().sws().bits() != sw_bits {}
174
175 Rcc {
176 rb: self.rb,
177 clocks: Clocks {
178 pll_clk,
179 sys_clk,
180 core_clk: (ahb_freq / 8).Hz(),
181 ahb_clk: ahb_freq.Hz(),
182 apb_clk: apb_freq.Hz(),
183 apb_tim_clk: apb_tim_freq.Hz(),
184 },
185 }
186 }
187
188 pub fn trim_hsi_clocks(&mut self, value: u8) {
189 self.icscr.modify(|_, w| unsafe { w.hsitrim().bits(value) });
190 }
191
192 pub fn set_reset_mode(&mut self, mode: ResetMode) {
193 unsafe {
194 let flash = &(*FLASH::ptr());
195
196 flash.keyr.write(|w| w.keyr().bits(0x4567_0123));
198 flash.keyr.write(|w| w.keyr().bits(0xcdef_89ab));
199
200 flash.optkeyr.write(|w| w.optkeyr().bits(0x0819_2a3b));
202 flash.optkeyr.write(|w| w.optkeyr().bits(0x4c5d_6e7f));
203 flash.cr.modify(|_, w| w.optlock().clear_bit());
204
205 flash.optr.modify(|_, w| w.nrst_mode().bits(mode as u8));
206 flash.cr.modify(|_, w| w.optstrt().set_bit());
207 }
208 }
209
210 fn config_pll(&self, pll_cfg: PllConfig) -> PLLClocks {
211 assert!(pll_cfg.m > 0 && pll_cfg.m <= 8);
212 assert!(pll_cfg.r > 1 && pll_cfg.r <= 8);
213
214 self.cfgr.modify(|r, w| {
218 if r.sw().bits() == 0b010 {
219 unsafe { w.sw().bits(0b000) };
220 }
221 w
222 });
223
224 self.cr.modify(|_, w| w.pllon().clear_bit());
226 while self.cr.read().pllrdy().bit_is_set() {}
227
228 let (freq, pll_sw_bits) = match pll_cfg.mux {
229 PLLSrc::HSI => {
230 self.enable_hsi();
231 (HSI_FREQ, 0b10)
232 }
233 PLLSrc::HSE(freq) => {
234 self.enable_hse(false);
235 (freq.raw(), 0b11)
236 }
237 PLLSrc::HSE_BYPASS(freq) => {
238 self.enable_hse(true);
239 (freq.raw(), 0b11)
240 }
241 };
242
243 let pll_freq = freq / (pll_cfg.m as u32) * (pll_cfg.n as u32);
244 let r = (pll_freq / (pll_cfg.r as u32)).Hz();
245 let mut q = None;
246 let mut p = None;
247
248 self.pllsyscfgr.write(|w| unsafe {
249 w.pllsrc().bits(pll_sw_bits);
250 w.pllm().bits(pll_cfg.m - 1);
251 w.plln().bits(pll_cfg.n);
252 w.pllr().bits(pll_cfg.r - 1);
253 w.pllren().set_bit();
254 if let Some(div) = pll_cfg.q {
255 assert!(div > 1 && div <= 8);
256 w.pllq().bits(div - 1);
257 w.pllqen().set_bit();
258 let req = pll_freq / div as u32;
259 q = Some(req.Hz());
260 }
261 if let Some(div) = pll_cfg.p {
262 assert!(div > 1 && div <= 8);
263 w.pllp().bits(div - 1);
264 w.pllpen().set_bit();
265 let req = pll_freq / div as u32;
266 p = Some(req.Hz());
267 }
268 w
269 });
270
271 self.cr.modify(|_, w| w.pllon().set_bit());
273 while self.cr.read().pllrdy().bit_is_clear() {}
274
275 PLLClocks { r, q, p }
276 }
277
278 pub(crate) fn enable_hsi(&self) {
279 self.cr.modify(|_, w| w.hsion().set_bit());
280 while self.cr.read().hsirdy().bit_is_clear() {}
281 }
282
283 pub(crate) fn enable_hse(&self, bypass: bool) {
284 self.cr
285 .modify(|_, w| w.hseon().set_bit().hsebyp().bit(bypass));
286 while self.cr.read().hserdy().bit_is_clear() {}
287 }
288
289 pub(crate) fn enable_lse(&self, bypass: bool) {
290 self.bdcr
291 .modify(|_, w| w.lseon().bit(!bypass).lsebyp().bit(bypass));
292 while !bypass && self.bdcr.read().lserdy().bit_is_clear() {}
293 }
294
295 pub(crate) fn enable_lsi(&self) {
296 self.csr.modify(|_, w| w.lsion().set_bit());
297 while self.csr.read().lsirdy().bit_is_clear() {}
298 }
299
300 pub(crate) fn unlock_rtc(&self) {
301 self.apbenr1.modify(|_, w| w.pwren().set_bit());
302 let pwr = unsafe { &(*PWR::ptr()) };
303 pwr.cr1.modify(|_, w| w.dbp().set_bit());
304 while pwr.cr1.read().dbp().bit_is_clear() {}
305 }
306
307 pub(crate) fn enable_rtc(&self, src: RTCSrc) {
308 self.unlock_rtc();
309 self.apbenr1
310 .modify(|_, w| w.rtcapben().set_bit().pwren().set_bit());
311 self.apbsmenr1.modify(|_, w| w.rtcapbsmen().set_bit());
312 self.bdcr.modify(|_, w| w.bdrst().set_bit());
313
314 let rtc_sel = match src {
315 RTCSrc::LSE | RTCSrc::LSE_BYPASS => 0b01,
316 RTCSrc::LSI => 0b10,
317 RTCSrc::HSE | RTCSrc::HSE_BYPASS => 0b11,
318 };
319
320 self.bdcr.modify(|_, w| unsafe {
321 w.rtcsel()
322 .bits(rtc_sel)
323 .rtcen()
324 .set_bit()
325 .bdrst()
326 .clear_bit()
327 });
328
329 self.unlock_rtc();
330 match src {
331 RTCSrc::LSE => self.enable_lse(false),
332 RTCSrc::LSE_BYPASS => self.enable_lse(true),
333 RTCSrc::LSI => self.enable_lsi(),
334 RTCSrc::HSE => self.enable_hse(false),
335 RTCSrc::HSE_BYPASS => self.enable_hse(true),
336 };
337 }
338}
339
340pub trait RccExt {
342 fn constrain(self) -> Rcc;
344 fn freeze(self, rcc_cfg: Config) -> Rcc;
346}
347
348impl RccExt for RCC {
349 fn constrain(self) -> Rcc {
350 Rcc {
351 rb: self,
352 clocks: Clocks::default(),
353 }
354 }
355
356 fn freeze(self, rcc_cfg: Config) -> Rcc {
357 self.constrain().freeze(rcc_cfg)
358 }
359}
360
361pub trait RccBus: crate::Sealed {
363 type Bus;
365}
366
367pub trait Enable: RccBus {
369 fn enable(rcc: &mut Rcc);
371
372 fn disable(rcc: &mut Rcc);
374
375 fn is_enabled() -> bool;
377
378 fn is_disabled() -> bool;
380
381 unsafe fn enable_unchecked();
385
386 unsafe fn disable_unchecked();
390}
391
392pub trait SMEnable: RccBus {
394 fn sleep_mode_enable(rcc: &mut Rcc);
396
397 fn sleep_mode_disable(rcc: &mut Rcc);
399
400 fn is_sleep_mode_enabled() -> bool;
402
403 fn is_sleep_mode_disabled() -> bool;
405
406 unsafe fn sleep_mode_enable_unchecked();
410
411 unsafe fn sleep_mode_disable_unchecked();
415}
416
417pub trait Reset: RccBus {
419 fn reset(rcc: &mut Rcc);
421
422 unsafe fn reset_unchecked();
426}
427
428use crate::stm32::rcc::RegisterBlock as RccRB;
429
430macro_rules! bus_struct {
431 ($($busX:ident => ($EN:ident, $en:ident, $SMEN:ident, $smen:ident, $RST:ident, $rst:ident, $doc:literal),)+) => {
432 $(
433 #[doc = $doc]
434 pub struct $busX {
435 _0: (),
436 }
437
438 impl $busX {
439 #[inline(always)]
440 fn enr(rcc: &RccRB) -> &rcc::$EN {
441 &rcc.$en
442 }
443 #[inline(always)]
444 fn smenr(rcc: &RccRB) -> &rcc::$SMEN {
445 &rcc.$smen
446 }
447 #[inline(always)]
448 fn rstr(rcc: &RccRB) -> &rcc::$RST {
449 &rcc.$rst
450 }
451 }
452 )+
453 };
454}
455
456bus_struct! {
457 AHB => (AHBENR, ahbenr, AHBSMENR, ahbsmenr, AHBRSTR, ahbrstr, "AMBA High-performance Bus (AHB) registers"),
458 APB1 => (APBENR1, apbenr1, APBSMENR1, apbsmenr1, APBRSTR1, apbrstr1, "Advanced Peripheral Bus 1 (APB1) registers"),
459 APB2 => (APBENR2, apbenr2, APBSMENR2, apbsmenr2, APBRSTR2, apbrstr2, "Advanced Peripheral Bus 2 (APB2) registers"),
460 IOP => (IOPENR, iopenr, IOPSMENR, iopsmenr, IOPRSTR, ioprstr, "Input-Output Peripheral Bus (IOP) registers"),
461}