diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-02-23 13:05:01 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2024-02-23 13:05:01 +0000 |
| commit | f77d59500e9bbc0282f1ba4b6b27507f83f9d974 (patch) | |
| tree | 3b3e54b5416f441cc401e82812fb0528c2f74eea | |
| parent | 840a9a9ce7eaba61f4c3aceee1deb87271ea3421 (diff) | |
| parent | b091ffcb55840a1349c62f1e4218746d9d51b6c3 (diff) | |
Merge pull request #2618 from barnabywalters/g4rcc
[embassy-stm32] G4 RCC refactor amendments and additions
| -rw-r--r-- | embassy-stm32/src/rcc/g4.rs | 52 |
1 files changed, 35 insertions, 17 deletions
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 382ffbead..6ed266284 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs | |||
| @@ -176,7 +176,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 176 | _ => unreachable!(), | 176 | _ => unreachable!(), |
| 177 | }; | 177 | }; |
| 178 | 178 | ||
| 179 | // TODO: check PLL input, internal and output frequencies for validity | 179 | assert!(max::PLL_IN.contains(&src_freq)); |
| 180 | 180 | ||
| 181 | // Disable PLL before configuration | 181 | // Disable PLL before configuration |
| 182 | RCC.cr().modify(|w| w.set_pllon(false)); | 182 | RCC.cr().modify(|w| w.set_pllon(false)); |
| @@ -184,6 +184,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 184 | 184 | ||
| 185 | let internal_freq = src_freq / pll_config.prediv * pll_config.mul; | 185 | let internal_freq = src_freq / pll_config.prediv * pll_config.mul; |
| 186 | 186 | ||
| 187 | assert!(max::PLL_VCO.contains(&internal_freq)); | ||
| 188 | |||
| 187 | RCC.pllcfgr().write(|w| { | 189 | RCC.pllcfgr().write(|w| { |
| 188 | w.set_plln(pll_config.mul); | 190 | w.set_plln(pll_config.mul); |
| 189 | w.set_pllm(pll_config.prediv); | 191 | w.set_pllm(pll_config.prediv); |
| @@ -195,7 +197,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 195 | w.set_pllp(div_p); | 197 | w.set_pllp(div_p); |
| 196 | w.set_pllpen(true); | 198 | w.set_pllpen(true); |
| 197 | }); | 199 | }); |
| 198 | internal_freq / div_p | 200 | let freq = internal_freq / div_p; |
| 201 | assert!(max::PCLK.contains(&freq)); | ||
| 202 | freq | ||
| 199 | }); | 203 | }); |
| 200 | 204 | ||
| 201 | let pll_q_freq = pll_config.divq.map(|div_q| { | 205 | let pll_q_freq = pll_config.divq.map(|div_q| { |
| @@ -203,7 +207,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 203 | w.set_pllq(div_q); | 207 | w.set_pllq(div_q); |
| 204 | w.set_pllqen(true); | 208 | w.set_pllqen(true); |
| 205 | }); | 209 | }); |
| 206 | internal_freq / div_q | 210 | let freq = internal_freq / div_q; |
| 211 | assert!(max::PCLK.contains(&freq)); | ||
| 212 | freq | ||
| 207 | }); | 213 | }); |
| 208 | 214 | ||
| 209 | let pll_r_freq = pll_config.divr.map(|div_r| { | 215 | let pll_r_freq = pll_config.divr.map(|div_r| { |
| @@ -211,7 +217,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 211 | w.set_pllr(div_r); | 217 | w.set_pllr(div_r); |
| 212 | w.set_pllren(true); | 218 | w.set_pllren(true); |
| 213 | }); | 219 | }); |
| 214 | internal_freq / div_r | 220 | let freq = internal_freq / div_r; |
| 221 | assert!(max::PCLK.contains(&freq)); | ||
| 222 | freq | ||
| 215 | }); | 223 | }); |
| 216 | 224 | ||
| 217 | // Enable the PLL | 225 | // Enable the PLL |
| @@ -234,7 +242,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 234 | 242 | ||
| 235 | let freq = pll_freq.as_ref().unwrap().pll_r.unwrap().0; | 243 | let freq = pll_freq.as_ref().unwrap().pll_r.unwrap().0; |
| 236 | 244 | ||
| 237 | assert!(freq <= 170_000_000); | 245 | assert!(max::SYSCLK.contains(&Hertz(freq))); |
| 238 | 246 | ||
| 239 | (Hertz(freq), Sw::PLL1_R) | 247 | (Hertz(freq), Sw::PLL1_R) |
| 240 | } | 248 | } |
| @@ -244,6 +252,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 244 | // Calculate the AHB frequency (HCLK), among other things so we can calculate the correct flash read latency. | 252 | // Calculate the AHB frequency (HCLK), among other things so we can calculate the correct flash read latency. |
| 245 | let hclk = sys_clk / config.ahb_pre; | 253 | let hclk = sys_clk / config.ahb_pre; |
| 246 | 254 | ||
| 255 | assert!(max::HCLK.contains(&hclk)); | ||
| 256 | |||
| 247 | // Configure Core Boost mode ([RM0440] p234 – inverted because setting r1mode to 0 enables boost mode!) | 257 | // Configure Core Boost mode ([RM0440] p234 – inverted because setting r1mode to 0 enables boost mode!) |
| 248 | if config.boost { | 258 | if config.boost { |
| 249 | // RM0440 p235 | 259 | // RM0440 p235 |
| @@ -346,32 +356,40 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 346 | adc: adc12_ck, | 356 | adc: adc12_ck, |
| 347 | adc34: adc345_ck, | 357 | adc34: adc345_ck, |
| 348 | pll1_p: pll_freq.as_ref().and_then(|pll| pll.pll_p), | 358 | pll1_p: pll_freq.as_ref().and_then(|pll| pll.pll_p), |
| 349 | pll1_q: pll_freq.as_ref().and_then(|pll| pll.pll_p), | 359 | pll1_q: pll_freq.as_ref().and_then(|pll| pll.pll_q), |
| 360 | pll1_r: pll_freq.as_ref().and_then(|pll| pll.pll_r), | ||
| 350 | hse: hse, | 361 | hse: hse, |
| 351 | rtc: rtc, | 362 | rtc: rtc, |
| 352 | ); | 363 | ); |
| 353 | } | 364 | } |
| 354 | 365 | ||
| 355 | // TODO: if necessary, make more of these, gated behind cfg attrs | 366 | /// Acceptable Frequency Ranges |
| 367 | /// Currently assuming voltage scaling range 1 boost mode. | ||
| 368 | /// Where not specified in the generic G4 reference manual (RM0440), values taken from the STM32G474 datasheet. | ||
| 369 | /// If acceptable ranges for other G4-family chips differ, make additional max modules gated behind cfg attrs. | ||
| 356 | mod max { | 370 | mod max { |
| 357 | use core::ops::RangeInclusive; | 371 | use core::ops::RangeInclusive; |
| 358 | 372 | ||
| 359 | use crate::time::Hertz; | 373 | use crate::time::Hertz; |
| 360 | 374 | ||
| 361 | /// HSE 4-48MHz (RM0440 p280) | 375 | /// HSE Frequency Range (RM0440 p280) |
| 362 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(48_000_000); | 376 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(48_000_000); |
| 363 | 377 | ||
| 364 | /// External Clock ?-48MHz (RM0440 p280) | 378 | /// External Clock Frequency Range (RM0440 p280) |
| 365 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000); | 379 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000); |
| 366 | 380 | ||
| 367 | // SYSCLK ?-170MHz (RM0440 p282) | 381 | /// SYSCLK Frequency Range (RM0440 p282) |
| 368 | //pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(170_000_000); | 382 | pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(170_000_000); |
| 383 | |||
| 384 | /// PLL Output Frequency Range (RM0440 p281, STM32G474 Datasheet p123, Table 46) | ||
| 385 | pub(crate) const PCLK: RangeInclusive<Hertz> = Hertz(8)..=Hertz(170_000_000); | ||
| 386 | |||
| 387 | /// HCLK (AHB) Clock Frequency Range (STM32G474 Datasheet) | ||
| 388 | pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(170_000_000); | ||
| 369 | 389 | ||
| 370 | // PLL Output frequency ?-170MHz (RM0440 p281) | 390 | /// PLL Source Frequency Range (STM32G474 Datasheet p123, Table 46) |
| 371 | //pub(crate) const PCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(170_000_000); | 391 | pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(2_660_000)..=Hertz(16_000_000); |
| 372 | 392 | ||
| 373 | // Left over from f.rs, remove if not necessary | 393 | /// PLL VCO (internal) Frequency Range (STM32G474 Datasheet p123, Table 46) |
| 374 | //pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(12_500_000)..=Hertz(216_000_000); | 394 | pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(96_000_000)..=Hertz(344_000_000); |
| 375 | //pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(2_100_000); | ||
| 376 | //pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(100_000_000)..=Hertz(432_000_000); | ||
| 377 | } | 395 | } |
