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}