stm32f1xx_hal/
rcc.rs

1//! # Reset & Control Clock
2
3use crate::pac::{rcc, PWR, RCC};
4
5use crate::flash::ACR;
6#[cfg(any(feature = "stm32f103", feature = "connectivity"))]
7use crate::time::MHz;
8use fugit::{HertzU32 as Hertz, RateExtU32};
9
10use crate::backup_domain::BackupDomain;
11
12mod enable;
13
14/// Extension trait that constrains the `RCC` peripheral
15pub trait RccExt {
16    /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
17    fn constrain(self) -> Rcc;
18}
19
20impl RccExt for RCC {
21    fn constrain(self) -> Rcc {
22        Rcc {
23            cfgr: CFGR {
24                hse: None,
25                hclk: None,
26                pclk1: None,
27                pclk2: None,
28                sysclk: None,
29                adcclk: None,
30            },
31            bkp: BKP { _0: () },
32        }
33    }
34}
35
36/// Constrained RCC peripheral
37///
38/// Aquired by calling the [constrain](../trait.RccExt.html#tymethod.constrain) method
39/// on the Rcc struct from the `PAC`
40///
41/// ```rust
42/// let dp = pac::Peripherals::take().unwrap();
43/// let mut rcc = dp.RCC.constrain();
44/// ```
45pub struct Rcc {
46    pub cfgr: CFGR,
47    pub bkp: BKP,
48}
49
50/// AMBA High-performance Bus (AHB) registers
51pub struct AHB {
52    _0: (),
53}
54
55impl AHB {
56    fn enr(rcc: &rcc::RegisterBlock) -> &rcc::AHBENR {
57        &rcc.ahbenr
58    }
59}
60
61/// Advanced Peripheral Bus 1 (APB1) registers
62pub struct APB1 {
63    _0: (),
64}
65
66impl APB1 {
67    fn enr(rcc: &rcc::RegisterBlock) -> &rcc::APB1ENR {
68        &rcc.apb1enr
69    }
70
71    fn rstr(rcc: &rcc::RegisterBlock) -> &rcc::APB1RSTR {
72        &rcc.apb1rstr
73    }
74}
75
76impl APB1 {
77    /// Set power interface clock (PWREN) bit in RCC_APB1ENR
78    pub fn set_pwren() {
79        let rcc = unsafe { &*RCC::ptr() };
80        PWR::enable(rcc);
81    }
82}
83
84/// Advanced Peripheral Bus 2 (APB2) registers
85pub struct APB2 {
86    _0: (),
87}
88
89impl APB2 {
90    fn enr(rcc: &rcc::RegisterBlock) -> &rcc::APB2ENR {
91        &rcc.apb2enr
92    }
93
94    fn rstr(rcc: &rcc::RegisterBlock) -> &rcc::APB2RSTR {
95        &rcc.apb2rstr
96    }
97}
98
99const HSI: u32 = 8_000_000; // Hz
100
101/// Clock configuration register (CFGR)
102///
103/// Used to configure the frequencies of the clocks present in the processor.
104///
105/// After setting all frequencies, call the [freeze](#method.freeze) function to
106/// apply the configuration.
107///
108/// **NOTE**: Currently, it is not guaranteed that the exact frequencies selected will be
109/// used, only frequencies close to it.
110#[derive(Debug, Default, PartialEq, Eq)]
111pub struct CFGR {
112    hse: Option<u32>,
113    hclk: Option<u32>,
114    pclk1: Option<u32>,
115    pclk2: Option<u32>,
116    sysclk: Option<u32>,
117    adcclk: Option<u32>,
118}
119
120impl CFGR {
121    /// Uses HSE (external oscillator) instead of HSI (internal RC oscillator) as the clock source.
122    /// Will result in a hang if an external oscillator is not connected or it fails to start.
123    /// The frequency specified must be the frequency of the external oscillator
124    #[inline(always)]
125    pub fn use_hse(mut self, freq: Hertz) -> Self {
126        self.hse = Some(freq.raw());
127        self
128    }
129
130    /// Sets the desired frequency for the HCLK clock
131    #[inline(always)]
132    pub fn hclk(mut self, freq: Hertz) -> Self {
133        self.hclk = Some(freq.raw());
134        self
135    }
136
137    /// Sets the desired frequency for the PCKL1 clock
138    #[inline(always)]
139    pub fn pclk1(mut self, freq: Hertz) -> Self {
140        self.pclk1 = Some(freq.raw());
141        self
142    }
143
144    /// Sets the desired frequency for the PCLK2 clock
145    #[inline(always)]
146    pub fn pclk2(mut self, freq: Hertz) -> Self {
147        self.pclk2 = Some(freq.raw());
148        self
149    }
150
151    /// Sets the desired frequency for the SYSCLK clock
152    #[inline(always)]
153    pub fn sysclk(mut self, freq: Hertz) -> Self {
154        self.sysclk = Some(freq.raw());
155        self
156    }
157
158    /// Sets the desired frequency for the ADCCLK clock
159    #[inline(always)]
160    pub fn adcclk(mut self, freq: Hertz) -> Self {
161        self.adcclk = Some(freq.raw());
162        self
163    }
164
165    /// Applies the clock configuration and returns a `Clocks` struct that signifies that the
166    /// clocks are frozen, and contains the frequencies used. After this function is called,
167    /// the clocks can not change
168    ///
169    /// Usage:
170    ///
171    /// ```rust
172    /// let dp = pac::Peripherals::take().unwrap();
173    /// let mut flash = dp.FLASH.constrain();
174    /// let mut rcc = dp.RCC.constrain();
175    /// let clocks = rcc.cfgr.freeze(&mut flash.acr);
176    /// ```
177
178    #[inline(always)]
179    pub fn freeze(self, acr: &mut ACR) -> Clocks {
180        let cfg = Config::from_cfgr(self);
181        Self::_freeze_with_config(cfg, acr)
182    }
183
184    #[inline(always)]
185    pub fn freeze_with_config(self, cfg: Config, acr: &mut ACR) -> Clocks {
186        Self::_freeze_with_config(cfg, acr)
187    }
188
189    #[allow(unused_variables)]
190    fn _freeze_with_config(cfg: Config, acr: &mut ACR) -> Clocks {
191        let clocks = cfg.get_clocks();
192        // adjust flash wait states
193        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
194        unsafe {
195            acr.acr().write(|w| {
196                w.latency().bits(if clocks.sysclk <= MHz(24) {
197                    0b000
198                } else if clocks.sysclk <= MHz(48) {
199                    0b001
200                } else {
201                    0b010
202                })
203            })
204        }
205
206        let rcc = unsafe { &*RCC::ptr() };
207
208        if cfg.hse.is_some() {
209            // enable HSE and wait for it to be ready
210
211            rcc.cr.modify(|_, w| w.hseon().set_bit());
212
213            while rcc.cr.read().hserdy().bit_is_clear() {}
214        }
215
216        if let Some(pllmul_bits) = cfg.pllmul {
217            // enable PLL and wait for it to be ready
218
219            #[allow(unused_unsafe)]
220            rcc.cfgr.modify(|_, w| unsafe {
221                w.pllmul().bits(pllmul_bits).pllsrc().bit(cfg.hse.is_some())
222            });
223
224            rcc.cr.modify(|_, w| w.pllon().set_bit());
225
226            while rcc.cr.read().pllrdy().bit_is_clear() {}
227        }
228
229        // set prescalers and clock source
230        #[cfg(feature = "connectivity")]
231        rcc.cfgr.modify(|_, w| unsafe {
232            w.adcpre().variant(cfg.adcpre);
233            w.ppre2()
234                .bits(cfg.ppre2 as u8)
235                .ppre1()
236                .bits(cfg.ppre1 as u8)
237                .hpre()
238                .bits(cfg.hpre as u8)
239                .otgfspre()
240                .variant(cfg.usbpre)
241                .sw()
242                .bits(if cfg.pllmul.is_some() {
243                    // PLL
244                    0b10
245                } else if cfg.hse.is_some() {
246                    // HSE
247                    0b1
248                } else {
249                    // HSI
250                    0b0
251                })
252        });
253
254        #[cfg(feature = "stm32f103")]
255        rcc.cfgr.modify(|_, w| unsafe {
256            w.adcpre().variant(cfg.adcpre);
257            w.ppre2()
258                .bits(cfg.ppre2 as u8)
259                .ppre1()
260                .bits(cfg.ppre1 as u8)
261                .hpre()
262                .bits(cfg.hpre as u8)
263                .usbpre()
264                .variant(cfg.usbpre)
265                .sw()
266                .bits(if cfg.pllmul.is_some() {
267                    // PLL
268                    0b10
269                } else {
270                    // HSE or HSI
271                    u8::from(cfg.hse.is_some())
272                })
273        });
274
275        #[cfg(any(feature = "stm32f100", feature = "stm32f101"))]
276        rcc.cfgr.modify(|_, w| unsafe {
277            w.adcpre().variant(cfg.adcpre);
278            w.ppre2()
279                .bits(cfg.ppre2 as u8)
280                .ppre1()
281                .bits(cfg.ppre1 as u8)
282                .hpre()
283                .bits(cfg.hpre as u8)
284                .sw()
285                .bits(if cfg.pllmul.is_some() {
286                    // PLL
287                    0b10
288                } else if cfg.hse.is_some() {
289                    // HSE
290                    0b1
291                } else {
292                    // HSI
293                    0b0
294                })
295        });
296
297        clocks
298    }
299}
300
301pub struct BKP {
302    _0: (),
303}
304
305impl BKP {
306    /// Enables write access to the registers in the backup domain
307    pub fn constrain(self, bkp: crate::pac::BKP, pwr: &mut PWR) -> BackupDomain {
308        // Enable the backup interface by setting PWREN and BKPEN
309        let rcc = unsafe { &(*RCC::ptr()) };
310        crate::pac::BKP::enable(rcc);
311        crate::pac::PWR::enable(rcc);
312
313        // Enable access to the backup registers
314        pwr.cr.modify(|_r, w| w.dbp().set_bit());
315
316        BackupDomain { _regs: bkp }
317    }
318}
319
320/// Frozen clock frequencies
321///
322/// The existence of this value indicates that the clock configuration can no longer be changed
323///
324/// To acquire it, use the freeze function on the `rcc.cfgr` register. If desired, you can adjust
325/// the frequencies using the methods on [cfgr](struct.CFGR.html) before calling freeze.
326///
327/// ```rust
328/// let dp = pac::Peripherals::take().unwrap();
329/// let mut rcc = dp.RCC.constrain();
330/// let mut flash = dp.FLASH.constrain();
331///
332/// let clocks = rcc.cfgr.freeze(&mut flash.acr);
333/// ```
334#[derive(Clone, Copy, Debug, PartialEq, Eq)]
335pub struct Clocks {
336    hclk: Hertz,
337    pclk1: Hertz,
338    pclk2: Hertz,
339    ppre1: u8,
340    ppre2: u8,
341    sysclk: Hertz,
342    adcclk: Hertz,
343    #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
344    usbclk_valid: bool,
345}
346
347impl Clocks {
348    /// Returns the frequency of the AHB
349    pub const fn hclk(&self) -> Hertz {
350        self.hclk
351    }
352
353    /// Returns the frequency of the APB1
354    pub const fn pclk1(&self) -> Hertz {
355        self.pclk1
356    }
357
358    /// Returns the frequency of the APB2
359    pub const fn pclk2(&self) -> Hertz {
360        self.pclk2
361    }
362
363    /// Returns the frequency of the APB1 Timers
364    pub const fn pclk1_tim(&self) -> Hertz {
365        Hertz::from_raw(self.pclk1.raw() * if self.ppre1() == 1 { 1 } else { 2 })
366    }
367
368    /// Returns the frequency of the APB2 Timers
369    pub const fn pclk2_tim(&self) -> Hertz {
370        Hertz::from_raw(self.pclk2.raw() * if self.ppre2() == 1 { 1 } else { 2 })
371    }
372
373    pub(crate) const fn ppre1(&self) -> u8 {
374        self.ppre1
375    }
376
377    // TODO remove `allow`
378    #[allow(dead_code)]
379    pub(crate) const fn ppre2(&self) -> u8 {
380        self.ppre2
381    }
382
383    /// Returns the system (core) frequency
384    pub const fn sysclk(&self) -> Hertz {
385        self.sysclk
386    }
387
388    /// Returns the adc clock frequency
389    pub const fn adcclk(&self) -> Hertz {
390        self.adcclk
391    }
392
393    /// Returns whether the USBCLK clock frequency is valid for the USB peripheral
394    #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
395    pub const fn usbclk_valid(&self) -> bool {
396        self.usbclk_valid
397    }
398}
399
400/// Frequency on bus that peripheral is connected in
401pub trait BusClock {
402    /// Calculates frequency depending on `Clock` state
403    fn clock(clocks: &Clocks) -> Hertz;
404}
405
406/// Frequency on bus that timer is connected in
407pub trait BusTimerClock {
408    /// Calculates base frequency of timer depending on `Clock` state
409    fn timer_clock(clocks: &Clocks) -> Hertz;
410}
411
412impl<T> BusClock for T
413where
414    T: RccBus,
415    T::Bus: BusClock,
416{
417    fn clock(clocks: &Clocks) -> Hertz {
418        T::Bus::clock(clocks)
419    }
420}
421
422impl<T> BusTimerClock for T
423where
424    T: RccBus,
425    T::Bus: BusTimerClock,
426{
427    fn timer_clock(clocks: &Clocks) -> Hertz {
428        T::Bus::timer_clock(clocks)
429    }
430}
431
432impl BusClock for AHB {
433    fn clock(clocks: &Clocks) -> Hertz {
434        clocks.hclk
435    }
436}
437
438impl BusClock for APB1 {
439    fn clock(clocks: &Clocks) -> Hertz {
440        clocks.pclk1
441    }
442}
443
444impl BusClock for APB2 {
445    fn clock(clocks: &Clocks) -> Hertz {
446        clocks.pclk2
447    }
448}
449
450impl BusTimerClock for APB1 {
451    fn timer_clock(clocks: &Clocks) -> Hertz {
452        clocks.pclk1_tim()
453    }
454}
455
456impl BusTimerClock for APB2 {
457    fn timer_clock(clocks: &Clocks) -> Hertz {
458        clocks.pclk2_tim()
459    }
460}
461
462/// Bus associated to peripheral
463pub trait RccBus: crate::Sealed {
464    /// Bus type;
465    type Bus;
466}
467
468/// Enable/disable peripheral
469pub trait Enable: RccBus {
470    fn enable(rcc: &rcc::RegisterBlock);
471    fn disable(rcc: &rcc::RegisterBlock);
472}
473/// Reset peripheral
474pub trait Reset: RccBus {
475    fn reset(rcc: &rcc::RegisterBlock);
476}
477
478#[derive(Clone, Copy, Debug, PartialEq)]
479pub struct Config {
480    pub hse: Option<u32>,
481    pub pllmul: Option<u8>,
482    pub hpre: HPre,
483    pub ppre1: PPre,
484    pub ppre2: PPre,
485    #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
486    pub usbpre: UsbPre,
487    pub adcpre: AdcPre,
488}
489
490impl Default for Config {
491    fn default() -> Self {
492        Self {
493            hse: None,
494            pllmul: None,
495            hpre: HPre::Div1,
496            ppre1: PPre::Div1,
497            ppre2: PPre::Div1,
498            #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
499            usbpre: UsbPre::Div15,
500            adcpre: AdcPre::Div2,
501        }
502    }
503}
504
505#[repr(u8)]
506#[derive(Clone, Copy, Debug, PartialEq, Eq)]
507pub enum HPre {
508    /// SYSCLK not divided
509    Div1 = 7,
510    /// SYSCLK divided by 2
511    Div2 = 8,
512    /// SYSCLK divided by 4
513    Div4 = 9,
514    /// SYSCLK divided by 8
515    Div8 = 10,
516    /// SYSCLK divided by 16
517    Div16 = 11,
518    /// SYSCLK divided by 64
519    Div64 = 12,
520    /// SYSCLK divided by 128
521    Div128 = 13,
522    /// SYSCLK divided by 256
523    Div256 = 14,
524    /// SYSCLK divided by 512
525    Div512 = 15,
526}
527
528#[derive(Clone, Copy, Debug, PartialEq, Eq)]
529#[repr(u8)]
530pub enum PPre {
531    /// HCLK not divided
532    Div1 = 3,
533    /// HCLK divided by 2
534    Div2 = 4,
535    /// HCLK divided by 4
536    Div4 = 5,
537    /// HCLK divided by 8
538    Div8 = 6,
539    /// HCLK divided by 16
540    Div16 = 7,
541}
542
543#[cfg(feature = "stm32f103")]
544pub type UsbPre = rcc::cfgr::USBPRE_A;
545#[cfg(feature = "connectivity")]
546pub type UsbPre = rcc::cfgr::OTGFSPRE_A;
547pub type AdcPre = rcc::cfgr::ADCPRE_A;
548
549impl Config {
550    pub const fn from_cfgr(cfgr: CFGR) -> Self {
551        let hse = cfgr.hse;
552        let pllsrcclk = if let Some(hse) = hse { hse } else { HSI / 2 };
553
554        let pllmul = if let Some(sysclk) = cfgr.sysclk {
555            sysclk / pllsrcclk
556        } else {
557            1
558        };
559
560        let (pllmul_bits, sysclk) = if pllmul == 1 {
561            (None, if let Some(hse) = hse { hse } else { HSI })
562        } else {
563            #[cfg(not(feature = "connectivity"))]
564            let pllmul = match pllmul {
565                1..=16 => pllmul,
566                0 => 1,
567                _ => 16,
568            };
569
570            #[cfg(feature = "connectivity")]
571            let pllmul = match pllmul {
572                4..=9 => pllmul,
573                0..=3 => 4,
574                _ => 9,
575            };
576
577            (Some(pllmul as u8 - 2), pllsrcclk * pllmul)
578        };
579
580        let hpre_bits = if let Some(hclk) = cfgr.hclk {
581            match sysclk / hclk {
582                0..=1 => HPre::Div1,
583                2 => HPre::Div2,
584                3..=5 => HPre::Div4,
585                6..=11 => HPre::Div8,
586                12..=39 => HPre::Div16,
587                40..=95 => HPre::Div64,
588                96..=191 => HPre::Div128,
589                192..=383 => HPre::Div256,
590                _ => HPre::Div512,
591            }
592        } else {
593            HPre::Div1
594        };
595
596        let hclk = if hpre_bits as u8 >= 0b1100 {
597            sysclk / (1 << (hpre_bits as u8 - 0b0110))
598        } else {
599            sysclk / (1 << (hpre_bits as u8 - 0b0111))
600        };
601
602        let pclk1 = if let Some(pclk1) = cfgr.pclk1 {
603            pclk1
604        } else if hclk < 36_000_000 {
605            hclk
606        } else {
607            36_000_000
608        };
609        let ppre1_bits = match (hclk + pclk1 - 1) / pclk1 {
610            0 | 1 => PPre::Div1,
611            2 => PPre::Div2,
612            3..=5 => PPre::Div4,
613            6..=11 => PPre::Div8,
614            _ => PPre::Div16,
615        };
616
617        let ppre2_bits = if let Some(pclk2) = cfgr.pclk2 {
618            match hclk / pclk2 {
619                0..=1 => PPre::Div1,
620                2 => PPre::Div2,
621                3..=5 => PPre::Div4,
622                6..=11 => PPre::Div8,
623                _ => PPre::Div16,
624            }
625        } else {
626            PPre::Div1
627        };
628
629        let ppre2 = 1 << (ppre2_bits as u8 - 0b011);
630        let pclk2 = hclk / (ppre2 as u32);
631
632        // usbpre == false: divide clock by 1.5, otherwise no division
633        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
634        let usbpre = match (hse, pllmul_bits, sysclk) {
635            (Some(_), Some(_), 72_000_000) => UsbPre::Div15,
636            _ => UsbPre::Div1,
637        };
638
639        let apre_bits = if let Some(adcclk) = cfgr.adcclk {
640            match pclk2 / adcclk {
641                0..=2 => AdcPre::Div2,
642                3..=4 => AdcPre::Div4,
643                5..=7 => AdcPre::Div6,
644                _ => AdcPre::Div8,
645            }
646        } else {
647            AdcPre::Div8
648        };
649
650        Self {
651            hse,
652            pllmul: pllmul_bits,
653            hpre: hpre_bits,
654            ppre1: ppre1_bits,
655            ppre2: ppre2_bits,
656            #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
657            usbpre,
658            adcpre: apre_bits,
659        }
660    }
661
662    // NOTE: to maintain the invariant that the existence of a Clocks
663    // value implies frozen clocks, this function must not be pub.
664    fn get_clocks(&self) -> Clocks {
665        let sysclk = if let Some(pllmul_bits) = self.pllmul {
666            let pllsrcclk = if let Some(hse) = self.hse {
667                hse
668            } else {
669                HSI / 2
670            };
671            pllsrcclk * (pllmul_bits as u32 + 2)
672        } else if let Some(hse) = self.hse {
673            hse
674        } else {
675            HSI
676        };
677
678        let hclk = if self.hpre as u8 >= 0b1100 {
679            sysclk / (1 << (self.hpre as u8 - 0b0110))
680        } else {
681            sysclk / (1 << (self.hpre as u8 - 0b0111))
682        };
683
684        let ppre1 = 1 << (self.ppre1 as u8 - 0b011);
685        let pclk1 = hclk / (ppre1 as u32);
686
687        let ppre2 = 1 << (self.ppre2 as u8 - 0b011);
688        let pclk2 = hclk / (ppre2 as u32);
689
690        let apre = (self.adcpre as u8 + 1) << 1;
691        let adcclk = pclk2 / (apre as u32);
692
693        // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
694        // PLL output frequency is a supported one.
695        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
696        let usbclk_valid = matches!(
697            (self.hse, self.pllmul, sysclk),
698            (Some(_), Some(_), 72_000_000) | (Some(_), Some(_), 48_000_000)
699        );
700
701        assert!(
702            sysclk <= 72_000_000
703                && hclk <= 72_000_000
704                && pclk1 <= 36_000_000
705                && pclk2 <= 72_000_000
706                && adcclk <= 14_000_000
707        );
708
709        Clocks {
710            hclk: hclk.Hz(),
711            pclk1: pclk1.Hz(),
712            pclk2: pclk2.Hz(),
713            ppre1,
714            ppre2,
715            sysclk: sysclk.Hz(),
716            adcclk: adcclk.Hz(),
717            #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
718            usbclk_valid,
719        }
720    }
721}
722
723#[test]
724fn rcc_config_usb() {
725    let cfgr = CFGR::default()
726        .use_hse(8.MHz())
727        .sysclk(48.MHz())
728        .pclk1(24.MHz());
729
730    let config = Config::from_cfgr(cfgr);
731    let config_expected = Config {
732        hse: Some(8_000_000),
733        pllmul: Some(4),
734        hpre: HPre::Div1,
735        ppre1: PPre::Div2,
736        ppre2: PPre::Div1,
737        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
738        usbpre: UsbPre::Div1,
739        adcpre: AdcPre::Div8,
740    };
741    assert_eq!(config, config_expected);
742
743    let clocks = config.get_clocks();
744    let clocks_expected = Clocks {
745        hclk: 48.MHz(),
746        pclk1: 24.MHz(),
747        pclk2: 48.MHz(),
748        ppre1: 2,
749        ppre2: 1,
750        sysclk: 48.MHz(),
751        adcclk: 6.MHz(),
752        #[cfg(any(feature = "stm32f103", feature = "connectivity"))]
753        usbclk_valid: true,
754    };
755    assert_eq!(clocks, clocks_expected);
756}