stm32f429_hal/
rcc.rs

1//! Reset and Clock Control
2
3use core::cmp;
4
5use cast::u32;
6use stm32f429::{rcc, RCC};
7
8use flash::ACR;
9use time::Hertz;
10
11/// Extension trait that constrains the `RCC` peripheral
12pub trait RccExt {
13    /// Constrains the `RCC` peripheral so it plays nicely with the other abstractions
14    fn constrain(self) -> Rcc;
15}
16
17impl RccExt for RCC {
18    fn constrain(self) -> Rcc {
19        Rcc {
20            ahb1: AHB1 { _0: () },
21            ahb2: AHB2 { _0: () },
22            ahb3: AHB3 { _0: () },
23            apb1: APB1 { _0: () },
24            apb2: APB2 { _0: () },
25            cfgr: CFGR {
26                hclk: None,
27                pclk1: None,
28                pclk2: None,
29                sysclk: None,
30            },
31        }
32    }
33}
34
35/// Constrained RCC peripheral
36pub struct Rcc {
37    /// AMBA High-performance Bus 1 (AHB1) registers
38    pub ahb1: AHB1,
39    /// AMBA High-performance Bus 2 (AHB2) registers
40    pub ahb2: AHB2,
41    /// AMBA High-performance Bus 3 (AHB3) registers
42    pub ahb3: AHB3,
43    /// Advanced Peripheral Bus 1 (APB1) registers
44    pub apb1: APB1,
45    /// Advanced Peripheral Bus 2 (APB2) registers
46    pub apb2: APB2,
47    /// Clock configuration
48    pub cfgr: CFGR,
49}
50
51/// AMBA High-performance Bus 1 (AHB1) registers
52pub struct AHB1 {
53    _0: (),
54}
55
56#[allow(unused)]
57impl AHB1 {
58    pub(crate) fn enr(&mut self) -> &rcc::AHB1ENR {
59        // NOTE(unsafe) this proxy grants exclusive access to this register
60        unsafe { &(*RCC::ptr()).ahb1enr }
61    }
62
63    pub(crate) fn rstr(&mut self) -> &rcc::AHB1RSTR {
64        // NOTE(unsafe) this proxy grants exclusive access to this register
65        unsafe { &(*RCC::ptr()).ahb1rstr }
66    }
67}
68
69/// AMBA High-performance Bus 2 (AHB2) registers
70pub struct AHB2 {
71    _0: (),
72}
73
74#[allow(unused)]
75impl AHB2 {
76    pub(crate) fn enr(&mut self) -> &rcc::AHB2ENR {
77        // NOTE(unsafe) this proxy grants exclusive access to this register
78        unsafe { &(*RCC::ptr()).ahb2enr }
79    }
80
81    pub(crate) fn rstr(&mut self) -> &rcc::AHB2RSTR {
82        // NOTE(unsafe) this proxy grants exclusive access to this register
83        unsafe { &(*RCC::ptr()).ahb2rstr }
84    }
85}
86
87/// AMBA High-performance Bus 3 (AHB3) registers
88pub struct AHB3 {
89    _0: (),
90}
91
92#[allow(unused)]
93impl AHB3 {
94    pub(crate) fn enr(&mut self) -> &rcc::AHB3ENR {
95        // NOTE(unsafe) this proxy grants exclusive access to this register
96        unsafe { &(*RCC::ptr()).ahb3enr }
97    }
98
99    pub(crate) fn rstr(&mut self) -> &rcc::AHB3RSTR {
100        // NOTE(unsafe) this proxy grants exclusive access to this register
101        unsafe { &(*RCC::ptr()).ahb3rstr }
102    }
103}
104
105/// Advanced Peripheral Bus 1 (APB1) registers
106pub struct APB1 {
107    _0: (),
108}
109
110impl APB1 {
111    pub(crate) fn enr(&mut self) -> &rcc::APB1ENR {
112        // NOTE(unsafe) this proxy grants exclusive access to this register
113        unsafe { &(*RCC::ptr()).apb1enr }
114    }
115
116    pub(crate) fn rstr(&mut self) -> &rcc::APB1RSTR {
117        // NOTE(unsafe) this proxy grants exclusive access to this register
118        unsafe { &(*RCC::ptr()).apb1rstr }
119    }
120}
121
122/// Advanced Peripheral Bus 2 (APB2) registers
123pub struct APB2 {
124    _0: (),
125}
126
127#[allow(unused)]
128impl APB2 {
129    pub(crate) fn enr(&mut self) -> &rcc::APB2ENR {
130        // NOTE(unsafe) this proxy grants exclusive access to this register
131        unsafe { &(*RCC::ptr()).apb2enr }
132    }
133
134    pub(crate) fn rstr(&mut self) -> &rcc::APB2RSTR {
135        // NOTE(unsafe) this proxy grants exclusive access to this register
136        unsafe { &(*RCC::ptr()).apb2rstr }
137    }
138}
139
140const HSI: u32 = 16_000_000; // 16 MHz
141
142/// Clock configuration
143#[derive(Debug)]
144pub struct CFGR {
145    hclk: Option<u32>,
146    pclk1: Option<u32>,
147    pclk2: Option<u32>,
148    sysclk: Option<u32>,
149}
150
151impl CFGR {
152    /// Sets a frequency for the AHB bus
153    pub fn hclk<F>(mut self, freq: F) -> Self
154    where
155        F: Into<Hertz>,
156    {
157        self.hclk = Some(freq.into().0);
158        self
159    }
160
161    /// Sets a frequency for the APB1 bus
162    pub fn pclk1<F>(mut self, freq: F) -> Self
163    where
164        F: Into<Hertz>,
165    {
166        self.pclk1 = Some(freq.into().0);
167        self
168    }
169
170    /// Sets a frequency for the APB2 bus
171    pub fn pclk2<F>(mut self, freq: F) -> Self
172    where
173        F: Into<Hertz>,
174    {
175        self.pclk2 = Some(freq.into().0);
176        self
177    }
178
179    /// Sets the system (core) frequency
180    pub fn sysclk<F>(mut self, freq: F) -> Self
181    where
182        F: Into<Hertz>,
183    {
184        self.sysclk = Some(freq.into().0);
185        self
186    }
187
188    /// Freezes the clock configuration, making it effective
189    pub fn freeze(self, acr: &mut ACR) -> Clocks {
190        let pllmul = (2 * self.sysclk.unwrap_or(HSI)) / HSI;
191        let pllmul = cmp::min(cmp::max(pllmul, 2), 16);
192        let pllmul_bits = if pllmul == 2 {
193            None
194        } else {
195            Some(pllmul as u8 - 2)
196        };
197
198        let sysclk = pllmul * HSI / 2;
199
200        assert!(sysclk <= 72_000_000);
201
202        // Prescaler factor
203        let hpre_bits = self.hclk
204            .map(|hclk| match sysclk / hclk {
205                0 => unreachable!(),
206                1 => 0b0111,  // sysclk not divided
207                2 => 0b1000,
208                3...5 => 0b1001,
209                6...11 => 0b1010,
210                12...39 => 0b1011,
211                40...95 => 0b1100,
212                96...191 => 0b1101,
213                192...383 => 0b1110,
214                _ => 0b1111,
215            })
216            .unwrap_or(0b0111);  // sysclk not divided
217
218        let hclk = sysclk / (1 << (hpre_bits - 0b0111));
219
220        assert!(hclk <= 72_000_000);
221
222        let ppre1_bits = self.pclk1
223            .map(|pclk1| match hclk / pclk1 {
224                0 => unreachable!(),
225                1 => 0b011,
226                2 => 0b100,
227                3...5 => 0b101,
228                6...11 => 0b110,
229                _ => 0b111,
230            })
231            .unwrap_or(0b011);
232
233        let ppre1 = 1 << (ppre1_bits - 0b011);
234        let pclk1 = hclk / u32(ppre1);
235
236        // Must not exceed 45 MHz!
237        assert!(pclk1 <= 45_000_000);
238
239        let ppre2_bits = self.pclk2
240            .map(|pclk2| match hclk / pclk2 {
241                0 => unreachable!(),
242                1 => 0b011,
243                2 => 0b100,
244                3...5 => 0b101,
245                6...11 => 0b110,
246                _ => 0b111,
247            })
248            .unwrap_or(0b011);
249
250        let ppre2 = 1 << (ppre2_bits - 0b011);
251        let pclk2 = hclk / u32(ppre2);
252
253        // Must not exceed 90 MHz!
254        assert!(pclk2 <= 90_000_000);
255
256        // adjust flash wait states
257        acr.acr().write(|w| {
258            w.latency().bits(if sysclk <= 24_000_000 {
259                0b000
260            } else if sysclk <= 48_000_000 {
261                0b001
262            } else {
263                0b010
264            })
265        });
266
267        let rcc = unsafe { &*RCC::ptr() };
268        if let Some(pllmul_bits) = pllmul_bits {
269            // use PLL as source
270            rcc.cfgr.modify(|_, w| w.hpre().bits(pllmul_bits));
271
272            // Enable PLL
273            rcc.cr.write(|w| w.pllon().set_bit());
274            // Wait for PLL ready
275            while rcc.cr.read().pllrdy().bit_is_clear() {}
276
277            // SW: PLL selected as system clock
278            rcc.cfgr.modify(|_, w| unsafe {
279                w
280                    // APB high-speed prescaler (APB2)
281                    .ppre2()
282                    .bits(ppre2_bits)
283                    // APB Low speed prescaler (APB1)
284                    .ppre1()
285                    .bits(ppre1_bits)
286                    // AHB prescaler
287                    .hpre()
288                    .bits(hpre_bits)
289                    // System clock switch
290                    .sw()
291                    // PLL selected as system clock
292                    .bits(0b10)
293            });
294        } else {
295            // use HSI as source
296
297            // SW: HSI selected as system clock
298            rcc.cfgr.write(|w| unsafe {
299                w.ppre2()
300                    .bits(ppre2_bits)
301                    .ppre1()
302                    .bits(ppre1_bits)
303                    .hpre()
304                    .bits(hpre_bits)
305                    .sw()
306                    .bits(0b00)
307            });
308        }
309
310        Clocks {
311            hclk: Hertz(hclk),
312            pclk1: Hertz(pclk1),
313            pclk2: Hertz(pclk2),
314            ppre1,
315            ppre2,
316            sysclk: Hertz(sysclk),
317        }
318    }
319}
320
321/// Frozen clock frequencies
322///
323/// The existence of this value indicates that the clock configuration can no longer be changed
324#[derive(Clone, Copy, Debug)]
325pub struct Clocks {
326    hclk: Hertz,
327    pclk1: Hertz,
328    pclk2: Hertz,
329    ppre1: u8,
330    // TODO remove `allow`
331    #[allow(dead_code)] ppre2: u8,
332    sysclk: Hertz,
333}
334
335impl Clocks {
336    /// Returns the frequency of the AHB
337    pub fn hclk(&self) -> Hertz {
338        self.hclk
339    }
340
341    /// Returns the frequency of the APB1
342    pub fn pclk1(&self) -> Hertz {
343        self.pclk1
344    }
345
346    /// Returns the frequency of the APB2
347    pub fn pclk2(&self) -> Hertz {
348        self.pclk2
349    }
350
351    pub(crate) fn ppre1(&self) -> u8 {
352        self.ppre1
353    }
354
355    // TODO remove `allow`
356    #[allow(dead_code)]
357    pub(crate) fn ppre2(&self) -> u8 {
358        self.ppre2
359    }
360
361    /// Returns the system (core) frequency
362    pub fn sysclk(&self) -> Hertz {
363        self.sysclk
364    }
365}