stm32f7x7_hal/
rcc.rs

1//! Reset & Control Clock
2
3use crate::stm32::{RCC, FLASH};
4
5use crate::time::Hertz;
6
7/// LSI clock frequency is approximately 32 KHz.
8///
9/// Note - this is not very accurate.
10/// It is recommended to use TIM5 to measure the LSI frequency
11/// for accurate
12pub const LSI: u32 = 32_000_000;
13
14/// HSI default clock speed is 16 MHz
15pub const HSI: u32 = 16_000_000;
16
17/// Extension trait that constrains the `RCC` peripheral
18pub trait RccExt {
19    /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
20    fn constrain(self) -> Rcc;
21}
22
23impl RccExt for RCC {
24    fn constrain(self) -> Rcc {
25        Rcc {
26            cfgr: CFGR {
27                hclk: None,
28                pclk1: None,
29                pclk2: None,
30                sysclk: None,
31            },
32        }
33    }
34}
35
36/// Constrained RCC peripheral
37pub struct Rcc {
38    /// Clock configuration
39    pub cfgr: CFGR,
40}
41
42
43/// Clock configuration
44pub struct CFGR {
45    hclk: Option<u32>,
46    pclk1: Option<u32>,
47    pclk2: Option<u32>,
48    sysclk: Option<u32>,
49}
50
51impl CFGR {
52    /// Sets a frequency for the AHB bus
53    pub fn hclk<F>(mut self, freq: F) -> Self
54    where
55        F: Into<Hertz>,
56    {
57        self.hclk = Some(freq.into().0);
58        self
59    }
60
61    /// Sets a frequency for the APB1 bus
62    pub fn pclk1<F>(mut self, freq: F) -> Self
63    where
64        F: Into<Hertz>,
65    {
66        self.pclk1 = Some(freq.into().0);
67        self
68    }
69
70    /// Sets a frequency for the APB2 bus
71    pub fn pclk2<F>(mut self, freq: F) -> Self
72    where
73        F: Into<Hertz>,
74    {
75        self.pclk2 = Some(freq.into().0);
76        self
77    }
78
79    /// Sets the system (core) frequency
80    pub fn sysclk<F>(mut self, freq: F) -> Self
81    where
82        F: Into<Hertz>,
83    {
84        self.sysclk = Some(freq.into().0);
85        self
86    }
87
88    // @brief  System Clock Configuration
89    //         The system Clock is configured as follow :
90    //            System Clock source            = PLL (HSE)
91    //            SYSCLK(Hz)                     = 216000000
92    //            HCLK(Hz)                       = 216000000
93    //            AHB Prescaler                  = 1
94    //            APB1 Prescaler                 = 4
95    //            APB2 Prescaler                 = 2
96    //            HSE Frequency(Hz)              = 25000000
97    //            PLL_M                          = 8
98    //            PLL_N                          = 432
99    //            PLL_P                          = 2
100    //            PLL_Q                          = 9
101    //            PLL_R                          = 7
102    //            VDD(V)                         = 3.3
103    //            Main regulator output voltage  = Scale1 mode
104    //            Flash Latency(WS)              = 7
105    //
106    // TODO - configs/timeout/result?
107    /*
108    pub fn freeze_max(self, acr: &mut ACR) -> Clocks {
109        let rcc = unsafe { &*RCC::ptr() };
110        let pll_m = 8;
111        let pll_n = 432;
112        let pll_q = 9;
113        let pll_r = 7;
114
115        // enable power control clock
116        rcc.apb1enr.modify(|_, w| w.pwren().set_bit());
117
118        // TODO - needed?
119        // enable voltage scaling
120
121        // enable HSE oscillator and activate PLL with HSE as source
122        rcc.cr.modify(|_, w| w.hseon().set_bit());
123
124        // wait until HSE is ready
125        while rcc.cr.read().hserdy().bit() == false {}
126
127        // if the PLL is not used as system clock
128        if rcc.cfgr.read().sws().bits() != 0b10 {
129            // disable main PLL
130            rcc.cr.modify(|_, w| w.pllon().clear_bit());
131
132            // configure main PLL clock source
133            rcc.pllcfgr.modify(|_, w| unsafe {
134                w
135                    // HSE PLL source
136                    .pllsrc()
137                    .set_bit()
138                    .pllm()
139                    .bits(pll_m)
140                    .plln()
141                    .bits(pll_n)
142                    // PLLP_DIV2
143                    .pllp()
144                    .bits(0b00)
145                    .pllq()
146                    .bits(pll_q)
147                    .pllr()
148                    .bits(pll_r)
149            });
150
151            // enable main PLL
152            rcc.cr.modify(|_, w| w.pllon().set_bit());
153
154            // wait until PLL is ready
155            while rcc.cr.read().pllrdy().bit() == false {}
156        }
157
158        // TODO - not neede for voltage scale 1?
159        // activate OverDrive
160        // HAL_PWREx_EnableOverDrive
161
162        // set flash latency wait states
163        acr.acr().modify(|_, w| w.latency().bits(7));
164
165        // TODO - should read back out and check?
166
167        // HCLK config
168        // no prescaler
169        rcc.cfgr.modify(|_, w| unsafe { w.hpre().bits(0b0000) });
170
171        // SYSCLK config
172        // wait for PLL ready
173        while rcc.cr.read().pllrdy().bit() == false {}
174        // set clock source, PLL
175        rcc.cfgr.modify(|_, w| unsafe { w.sw().bits(0b10) });
176
177        // wait for it
178        while rcc.cfgr.read().sws().bits() != 0b10 {}
179
180        rcc.cfgr.modify(|_, w| unsafe {
181            w
182                // PCLK1, DIV4
183                .ppre1()
184                .bits(0b101)
185                // PCLK2, DIV2
186                .ppre2()
187                .bits(0b100)
188        });
189
190        // TODO
191        let sysclk = 216_000_000;
192        let hclk = sysclk;
193        let ppre1: u32 = 4;
194        let ppre2: u32 = 2;
195
196        Clocks {
197            hclk: Hertz(hclk),
198            pclk1: Hertz(hclk / ppre1),
199            pclk2: Hertz(hclk / ppre2),
200            ppre1: ppre1 as _,
201            ppre2: ppre2 as _,
202            sysclk: Hertz(sysclk),
203        }
204    }*/
205
206    /// Freezes the clock configuration, making it effective
207    pub fn freeze(self) -> Clocks {
208        let rcc = unsafe { &*RCC::ptr() };
209        let flash = unsafe { &*FLASH::ptr() };
210
211        let sysclk = self.sysclk.unwrap_or(HSI);
212        let hclk = self.hclk.unwrap_or(HSI);
213
214        assert!(sysclk >= HSI);
215        assert!(hclk <= sysclk);
216
217        if sysclk == HSI && hclk == sysclk {
218            // use HSI as source and run everything at the same speed
219            rcc.cfgr.modify(|_, w| unsafe {
220                w.ppre2().bits(0).ppre1().bits(0).hpre().bits(0).sw().hsi()
221            });
222
223            Clocks {
224                hclk: Hertz(hclk),
225                pclk1: Hertz(hclk),
226                pclk2: Hertz(hclk),
227                ppre1: 1,
228                ppre2: 1,
229                sysclk: Hertz(sysclk),
230            }
231        } else if sysclk == HSI && hclk < sysclk {
232            let hpre_bits = match sysclk / hclk {
233                0 => unreachable!(),
234                1 => 0b0111,
235                2 => 0b1000,
236                3...5 => 0b1001,
237                6...11 => 0b1010,
238                12...39 => 0b1011,
239                40...95 => 0b1100,
240                96...191 => 0b1101,
241                192...383 => 0b1110,
242                _ => 0b1111,
243            };
244
245            // Use HSI as source and run everything at the same speed
246            rcc.cfgr.modify(|_, w| unsafe {
247                w.ppre2()
248                    .bits(0)
249                    .ppre1()
250                    .bits(0)
251                    .hpre()
252                    .bits(hpre_bits)
253                    .sw()
254                    .hsi()
255            });
256
257            Clocks {
258                hclk: Hertz(hclk),
259                pclk1: Hertz(hclk),
260                pclk2: Hertz(hclk),
261                ppre1: 1,
262                ppre2: 1,
263                sysclk: Hertz(sysclk),
264            }
265        } else {
266            assert!(sysclk <= 216_000_000 && sysclk >= 24_000_000);
267
268            // We're not diving down the hclk so it'll be the same as sysclk
269            let hclk = sysclk;
270
271            let (pllm, plln, pllp) = if sysclk >= 96_000_000 {
272                // Input divisor from HSI clock, must result in less than 2MHz
273                let pllm = 16;
274
275                // Main scaler, must result in >= 192MHz and <= 432MHz, min 50, max 432
276                let plln = (sysclk / 1_000_000) * 2;
277
278                // Sysclk output divisor, must result in >= 24MHz and <= 216MHz
279                // needs to be the equivalent of 2, 4, 6 or 8
280                let pllp = 0;
281
282                (pllm, plln, pllp)
283            } else if sysclk <= 54_000_000 {
284                // Input divisor from HSI clock, must result in less than 2MHz
285                let pllm = 16;
286
287                // Main scaler, must result in >= 192MHz and <= 432MHz, min 50, max 432
288                let plln = (sysclk / 1_000_000) * 8;
289
290                // Sysclk output divisor, must result in >= 24MHz and <= 216MHz
291                // needs to be the equivalent of 2, 4, 6 or 8
292                let pllp = 0b11;
293
294                (pllm, plln, pllp)
295            } else {
296                // Input divisor from HSI clock, must result in less than 2MHz
297                let pllm = 16;
298
299                // Main scaler, must result in >= 192MHz and <= 432MHz, min 50, max 432
300                let plln = (sysclk / 1_000_000) * 4;
301
302                // Sysclk output divisor, must result in >= 24MHz and <= 216MHz
303                // needs to be the equivalent of 2, 4, 6 or 8
304                let pllp = 0b1;
305
306                (pllm, plln, pllp)
307            };
308
309            let ppre2_bits = if sysclk > 108_000_000 { 0b100 } else { 0 };
310            let ppre1_bits = if sysclk > 108_000_000 {
311                0b101
312            } else if sysclk > 54_000_000 {
313                0b100
314            } else {
315                0
316            };
317
318            // Calculate real divisor
319            let ppre1 = 1 << (ppre1_bits - 0b011);
320            let ppre2 = 1 << (ppre2_bits - 0b011);
321
322            // Calculate new bus clocks
323            let pclk1 = hclk / u32::from(ppre1);
324            let pclk2 = hclk / u32::from(ppre2);
325
326            // Adjust flash wait states
327            flash.acr.write(|w| {
328                w.latency().bits(if sysclk <= 30_000_000 {
329                    0b0000
330                } else if sysclk <= 60_000_000 {
331                    0b0001
332                } else if sysclk <= 90_000_000 {
333                    0b0010
334                } else if sysclk <= 120_000_000 {
335                    0b0011
336                } else if sysclk <= 150_000_000 {
337                    0b0100
338                } else if sysclk <= 180_000_000 {
339                    0b0101
340                } else if sysclk <= 210_000_000 {
341                    0b0110
342                } else {
343                    0b0111
344                })
345            });
346
347            // use PLL as source
348            rcc.pllcfgr.write(|w| unsafe {
349                w.pllm()
350                    .bits(pllm)
351                    .plln()
352                    .bits(plln as u16)
353                    .pllp()
354                    .bits(pllp)
355            });
356
357            // Enable PLL
358            rcc.cr.write(|w| w.pllon().set_bit());
359
360            // Wait for PLL to stabilise
361            while rcc.cr.read().pllrdy().bit_is_clear() {}
362
363            // Set scaling factors and switch clock to PLL
364            rcc.cfgr.modify(|_, w| unsafe {
365                w.ppre2()
366                    .bits(ppre2_bits)
367                    .ppre1()
368                    .bits(ppre1_bits)
369                    .hpre()
370                    .bits(0)
371                    .sw()
372                    .pll()
373            });
374
375            Clocks {
376                hclk: Hertz(hclk),
377                pclk1: Hertz(pclk1),
378                pclk2: Hertz(pclk2),
379                ppre1,
380                ppre2,
381                sysclk: Hertz(sysclk),
382            }
383        }
384    }
385}
386
387/// Frozen clock frequencies
388///
389/// The existence of this value indicates that the clock configuration can no longer be changed
390#[derive(Clone, Copy)]
391pub struct Clocks {
392    hclk: Hertz,
393    pclk1: Hertz,
394    pclk2: Hertz,
395    ppre1: u8,
396    ppre2: u8,
397    sysclk: Hertz,
398}
399
400impl Clocks {
401    /// Returns the frequency of the AHB1
402    pub fn hclk(&self) -> Hertz {
403        self.hclk
404    }
405
406    /// Returns the frequency of the APB1
407    pub fn pclk1(&self) -> Hertz {
408        self.pclk1
409    }
410
411    /// Returns the frequency of the APB2
412    pub fn pclk2(&self) -> Hertz {
413        self.pclk2
414    }
415
416    /// Returns the prescaler of the APB1
417    pub fn ppre1(&self) -> u8 {
418        self.ppre1
419    }
420
421    /// Returns the prescaler of the APB2
422    pub fn ppre2(&self) -> u8 {
423        self.ppre2
424    }
425
426    /// Returns the system (core) frequency
427    pub fn sysclk(&self) -> Hertz {
428        self.sysclk
429    }
430} 
431
432/// TODO
433#[derive(Copy, Clone, Debug)]
434pub struct ResetConditions {
435    pub low_power: bool,
436    pub window_watchdog: bool,
437    pub independent_watchdog: bool,
438    pub software: bool,
439    pub por_pdr: bool,
440    pub pin: bool,
441    pub bor: bool,
442}
443
444impl ResetConditions {
445    pub fn read_and_clear() -> Self {
446        let csr = unsafe { &(*RCC::ptr()).csr };
447        let rc = ResetConditions {
448            low_power: csr.read().lpwrrstf().bit(),
449            window_watchdog: csr.read().wwdgrstf().bit(),
450            independent_watchdog: csr.read().wdgrstf().bit(),
451            software: csr.read().sftrstf().bit(),
452            por_pdr: csr.read().porrstf().bit(),
453            pin: csr.read().padrstf().bit(),
454            bor: csr.read().borrstf().bit(),
455        };
456
457        // clear the reset flags
458        csr.modify(|_, w| w.rmvf().set_bit());
459
460        rc
461    }
462}