diff options
| author | Barnaby Walters <[email protected]> | 2024-02-16 21:34:12 +0100 |
|---|---|---|
| committer | Barnaby Walters <[email protected]> | 2024-02-16 21:34:12 +0100 |
| commit | e465dacf739e499f64b7943f4674edfe060f83b7 (patch) | |
| tree | 8d627ecdda402ae33df2b6c1346cc2bc38f30a90 | |
| parent | 25a95503f661f064e57854df8f831ad681868a4c (diff) | |
Added documentation, fixed and refined boost and flash read latency config
| -rw-r--r-- | embassy-stm32/src/rcc/g4.rs | 69 |
1 files changed, 39 insertions, 30 deletions
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 22dfa25c6..e2afd5260 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs | |||
| @@ -13,6 +13,7 @@ use crate::time::Hertz; | |||
| 13 | /// HSI speed | 13 | /// HSI speed |
| 14 | pub const HSI_FREQ: Hertz = Hertz(16_000_000); | 14 | pub const HSI_FREQ: Hertz = Hertz(16_000_000); |
| 15 | 15 | ||
| 16 | /// HSE Mode | ||
| 16 | #[derive(Clone, Copy, Eq, PartialEq)] | 17 | #[derive(Clone, Copy, Eq, PartialEq)] |
| 17 | pub enum HseMode { | 18 | pub enum HseMode { |
| 18 | /// crystal/ceramic oscillator (HSEBYP=0) | 19 | /// crystal/ceramic oscillator (HSEBYP=0) |
| @@ -21,6 +22,7 @@ pub enum HseMode { | |||
| 21 | Bypass, | 22 | Bypass, |
| 22 | } | 23 | } |
| 23 | 24 | ||
| 25 | /// HSE Configuration | ||
| 24 | #[derive(Clone, Copy, Eq, PartialEq)] | 26 | #[derive(Clone, Copy, Eq, PartialEq)] |
| 25 | pub struct Hse { | 27 | pub struct Hse { |
| 26 | /// HSE frequency. | 28 | /// HSE frequency. |
| @@ -57,11 +59,19 @@ pub struct Pll { | |||
| 57 | /// Clocks configutation | 59 | /// Clocks configutation |
| 58 | #[non_exhaustive] | 60 | #[non_exhaustive] |
| 59 | pub struct Config { | 61 | pub struct Config { |
| 62 | /// HSI Enable | ||
| 60 | pub hsi: bool, | 63 | pub hsi: bool, |
| 64 | |||
| 65 | /// HSE Configuration | ||
| 61 | pub hse: Option<Hse>, | 66 | pub hse: Option<Hse>, |
| 67 | |||
| 68 | /// System Clock Configuration | ||
| 62 | pub sys: Sysclk, | 69 | pub sys: Sysclk, |
| 70 | |||
| 71 | /// HSI48 Configuration | ||
| 63 | pub hsi48: Option<super::Hsi48Config>, | 72 | pub hsi48: Option<super::Hsi48Config>, |
| 64 | 73 | ||
| 74 | /// PLL Configuration | ||
| 65 | pub pll: Option<Pll>, | 75 | pub pll: Option<Pll>, |
| 66 | 76 | ||
| 67 | /// Iff PLL is requested as the main clock source in the `mux` field then the PLL configuration | 77 | /// Iff PLL is requested as the main clock source in the `mux` field then the PLL configuration |
| @@ -69,17 +79,26 @@ pub struct Config { | |||
| 69 | pub ahb_pre: AHBPrescaler, | 79 | pub ahb_pre: AHBPrescaler, |
| 70 | pub apb1_pre: APBPrescaler, | 80 | pub apb1_pre: APBPrescaler, |
| 71 | pub apb2_pre: APBPrescaler, | 81 | pub apb2_pre: APBPrescaler, |
| 82 | |||
| 72 | pub low_power_run: bool, | 83 | pub low_power_run: bool, |
| 73 | 84 | ||
| 74 | /// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals. | 85 | /// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals. |
| 75 | pub clk48_src: Clk48Src, | 86 | pub clk48_src: Clk48Src, |
| 76 | 87 | ||
| 88 | /// Low-Speed Clock Configuration | ||
| 77 | pub ls: super::LsConfig, | 89 | pub ls: super::LsConfig, |
| 78 | 90 | ||
| 91 | /// Clock Source for ADCs 1 and 2 | ||
| 79 | pub adc12_clock_source: AdcClockSource, | 92 | pub adc12_clock_source: AdcClockSource, |
| 93 | |||
| 94 | /// Clock Source for ADCs 3, 4 and 5 | ||
| 80 | pub adc345_clock_source: AdcClockSource, | 95 | pub adc345_clock_source: AdcClockSource, |
| 96 | |||
| 97 | /// Clock Source for FDCAN | ||
| 81 | pub fdcan_clock_source: FdCanClockSource, | 98 | pub fdcan_clock_source: FdCanClockSource, |
| 82 | 99 | ||
| 100 | /// Enable range1 boost mode | ||
| 101 | /// Recommended when the SYSCLK frequency is greater than 150MHz. | ||
| 83 | pub boost: bool, | 102 | pub boost: bool, |
| 84 | } | 103 | } |
| 85 | 104 | ||
| @@ -217,36 +236,6 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 217 | 236 | ||
| 218 | assert!(freq <= 170_000_000); | 237 | assert!(freq <= 170_000_000); |
| 219 | 238 | ||
| 220 | if config.boost { | ||
| 221 | // Enable Core Boost mode ([RM0440] p234) | ||
| 222 | PWR.cr5().modify(|w| w.set_r1mode(false)); | ||
| 223 | if freq <= 36_000_000 { | ||
| 224 | FLASH.acr().modify(|w| w.set_latency(Latency::WS0)); | ||
| 225 | } else if freq <= 68_000_000 { | ||
| 226 | FLASH.acr().modify(|w| w.set_latency(Latency::WS1)); | ||
| 227 | } else if freq <= 102_000_000 { | ||
| 228 | FLASH.acr().modify(|w| w.set_latency(Latency::WS2)); | ||
| 229 | } else if freq <= 136_000_000 { | ||
| 230 | FLASH.acr().modify(|w| w.set_latency(Latency::WS3)); | ||
| 231 | } else { | ||
| 232 | FLASH.acr().modify(|w| w.set_latency(Latency::WS4)); | ||
| 233 | } | ||
| 234 | } else { | ||
| 235 | // Enable Core Boost mode ([RM0440] p234) | ||
| 236 | PWR.cr5().modify(|w| w.set_r1mode(true)); | ||
| 237 | if freq <= 30_000_000 { | ||
| 238 | FLASH.acr().modify(|w| w.set_latency(Latency::WS0)); | ||
| 239 | } else if freq <= 60_000_000 { | ||
| 240 | FLASH.acr().modify(|w| w.set_latency(Latency::WS1)); | ||
| 241 | } else if freq <= 80_000_000 { | ||
| 242 | FLASH.acr().modify(|w| w.set_latency(Latency::WS2)); | ||
| 243 | } else if freq <= 120_000_000 { | ||
| 244 | FLASH.acr().modify(|w| w.set_latency(Latency::WS3)); | ||
| 245 | } else { | ||
| 246 | FLASH.acr().modify(|w| w.set_latency(Latency::WS4)); | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | (Hertz(freq), Sw::PLL1_R) | 239 | (Hertz(freq), Sw::PLL1_R) |
| 251 | } | 240 | } |
| 252 | _ => unreachable!(), | 241 | _ => unreachable!(), |
| @@ -261,6 +250,26 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 261 | 250 | ||
| 262 | let ahb_freq = sys_clk / config.ahb_pre; | 251 | let ahb_freq = sys_clk / config.ahb_pre; |
| 263 | 252 | ||
| 253 | // Configure Core Boost mode ([RM0440] p234 – inverted because setting r1mode to 0 enables boost mode!) | ||
| 254 | PWR.cr5().modify(|w| w.set_r1mode(!config.boost)); | ||
| 255 | |||
| 256 | // Configure flash read access latency based on boost mode and frequency (RM0440 p98) | ||
| 257 | FLASH.acr().modify(|w| { | ||
| 258 | w.set_latency(match (config.boost, ahb_freq.0) { | ||
| 259 | (true, ..=34_000_000) => Latency::WS0, | ||
| 260 | (true, ..=68_000_000) => Latency::WS1, | ||
| 261 | (true, ..=102_000_000) => Latency::WS2, | ||
| 262 | (true, ..=136_000_000) => Latency::WS3, | ||
| 263 | (true, _) => Latency::WS4, | ||
| 264 | |||
| 265 | (false, ..=36_000_000) => Latency::WS0, | ||
| 266 | (false, ..=60_000_000) => Latency::WS1, | ||
| 267 | (false, ..=90_000_000) => Latency::WS2, | ||
| 268 | (false, ..=120_000_000) => Latency::WS3, | ||
| 269 | (false, _) => Latency::WS4, | ||
| 270 | }) | ||
| 271 | }); | ||
| 272 | |||
| 264 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { | 273 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { |
| 265 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 274 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 266 | pre => { | 275 | pre => { |
