stm32g0xx_hal/rcc/
mod.rs

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
12/// HSI speed
13pub const HSI_FREQ: u32 = 16_000_000;
14
15/// Clock frequencies
16#[derive(Clone, Copy)]
17pub struct Clocks {
18    /// System frequency
19    pub sys_clk: Hertz,
20    /// Core frequency
21    pub core_clk: Hertz,
22    /// AHB frequency
23    pub ahb_clk: Hertz,
24    /// APB frequency
25    pub apb_clk: Hertz,
26    /// APB timers frequency
27    pub apb_tim_clk: Hertz,
28    /// PLL frequency
29    pub pll_clk: PLLClocks,
30}
31
32/// PLL Clock frequencies
33#[derive(Clone, Copy)]
34pub struct PLLClocks {
35    /// R frequency
36    pub r: Hertz,
37    /// Q frequency
38    pub q: Option<Hertz>,
39    /// P frequency
40    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
60/// Reset pin mode and remap
61pub enum ResetMode {
62    /// Reset Input only: a low level on the NRST pin generates system reset, internal RESET not propagated to the NSRT pin
63    ResetInput = 0b01,
64    /// GPIO: standard GPIO pad functionality, only internal RESET possible
65    GPIO = 0b10,
66    /// Bidirectional reset: NRST pin configured in reset input/output mode (legacy mode)
67    Bidirectional = 0b11,
68}
69
70/// Constrained RCC peripheral
71pub struct Rcc {
72    /// Clock configuration
73    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    /// Apply clock configuration
88    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            // Adjust flash wait states
152            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            // Unlock flash
197            flash.keyr.write(|w| w.keyr().bits(0x4567_0123));
198            flash.keyr.write(|w| w.keyr().bits(0xcdef_89ab));
199
200            // Unlock flash OTP
201            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        // If the system is currently clocked from the PLL, then switch back to
215        // the HSI before we disable the PLL, otherwise the PLL will refuse to
216        // switch off.
217        self.cfgr.modify(|r, w| {
218            if r.sw().bits() == 0b010 {
219                unsafe { w.sw().bits(0b000) };
220            }
221            w
222        });
223
224        // Disable PLL
225        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        // Enable PLL
272        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
340/// Extension trait that constrains the `RCC` peripheral
341pub trait RccExt {
342    /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
343    fn constrain(self) -> Rcc;
344    /// Constrains the `RCC` peripheral and apply clock configuration
345    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
361/// Bus associated to peripheral
362pub trait RccBus: crate::Sealed {
363    /// Bus type;
364    type Bus;
365}
366
367/// Enable/disable peripheral
368pub trait Enable: RccBus {
369    /// Enables peripheral
370    fn enable(rcc: &mut Rcc);
371
372    /// Disables peripheral
373    fn disable(rcc: &mut Rcc);
374
375    /// Check if peripheral enabled
376    fn is_enabled() -> bool;
377
378    /// Check if peripheral disabled
379    fn is_disabled() -> bool;
380
381    /// # Safety
382    ///
383    /// Enables peripheral. Takes access to RCC internally
384    unsafe fn enable_unchecked();
385
386    /// # Safety
387    ///
388    /// Disables peripheral. Takes access to RCC internally
389    unsafe fn disable_unchecked();
390}
391
392/// Enable/disable peripheral in Sleep mode
393pub trait SMEnable: RccBus {
394    /// Enables peripheral
395    fn sleep_mode_enable(rcc: &mut Rcc);
396
397    /// Disables peripheral
398    fn sleep_mode_disable(rcc: &mut Rcc);
399
400    /// Check if peripheral enabled
401    fn is_sleep_mode_enabled() -> bool;
402
403    /// Check if peripheral disabled
404    fn is_sleep_mode_disabled() -> bool;
405
406    /// # Safety
407    ///
408    /// Enables peripheral. Takes access to RCC internally
409    unsafe fn sleep_mode_enable_unchecked();
410
411    /// # Safety
412    ///
413    /// Disables peripheral. Takes access to RCC internally
414    unsafe fn sleep_mode_disable_unchecked();
415}
416
417/// Reset peripheral
418pub trait Reset: RccBus {
419    /// Resets peripheral
420    fn reset(rcc: &mut Rcc);
421
422    /// # Safety
423    ///
424    /// Resets peripheral. Takes access to RCC internally
425    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}