aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarnaby Walters <[email protected]>2024-02-16 21:34:12 +0100
committerBarnaby Walters <[email protected]>2024-02-16 21:34:12 +0100
commite465dacf739e499f64b7943f4674edfe060f83b7 (patch)
tree8d627ecdda402ae33df2b6c1346cc2bc38f30a90
parent25a95503f661f064e57854df8f831ad681868a4c (diff)
Added documentation, fixed and refined boost and flash read latency config
-rw-r--r--embassy-stm32/src/rcc/g4.rs69
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
14pub const HSI_FREQ: Hertz = Hertz(16_000_000); 14pub 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)]
17pub enum HseMode { 18pub 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)]
25pub struct Hse { 27pub 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]
59pub struct Config { 61pub 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 => {