aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-03-03 23:19:54 +0100
committerDario Nieuwenhuis <[email protected]>2024-03-04 00:04:06 +0100
commitc8c4b0b701ecfbb146c6f651bebd43f053f55ac2 (patch)
treef4af9be094f3a2b5d16af8097e589a53ed76c7be
parentb4567bb8c56dced1c64177d727ebb32ee4680ea3 (diff)
stm32/rcc: port g0 to new api.
-rw-r--r--embassy-stm32/src/rcc/g0.rs482
-rw-r--r--examples/stm32g0/src/bin/hf_timer.rs15
-rw-r--r--tests/stm32/src/common.rs13
3 files changed, 249 insertions, 261 deletions
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index 5cfe9953b..ea4422ccc 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -1,7 +1,8 @@
1use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
2use crate::pac::rcc::vals::{self, Sw}; 2pub use crate::pac::pwr::vals::Vos as VoltageRange;
3pub use crate::pac::rcc::vals::{ 3pub use crate::pac::rcc::vals::{
4 Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler, 4 Hpre as AHBPrescaler, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv,
5 Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk,
5}; 6};
6use crate::pac::{FLASH, PWR, RCC}; 7use crate::pac::{FLASH, PWR, RCC};
7use crate::time::Hertz; 8use crate::time::Hertz;
@@ -9,6 +10,7 @@ use crate::time::Hertz;
9/// HSI speed 10/// HSI speed
10pub const HSI_FREQ: Hertz = Hertz(16_000_000); 11pub const HSI_FREQ: Hertz = Hertz(16_000_000);
11 12
13/// HSE Mode
12#[derive(Clone, Copy, Eq, PartialEq)] 14#[derive(Clone, Copy, Eq, PartialEq)]
13pub enum HseMode { 15pub enum HseMode {
14 /// crystal/ceramic oscillator (HSEBYP=0) 16 /// crystal/ceramic oscillator (HSEBYP=0)
@@ -17,69 +19,71 @@ pub enum HseMode {
17 Bypass, 19 Bypass,
18} 20}
19 21
20/// System clock mux source 22/// HSE Configuration
21#[derive(Clone, Copy)] 23#[derive(Clone, Copy, Eq, PartialEq)]
22pub enum Sysclk { 24pub struct Hse {
23 HSE(Hertz, HseMode), 25 /// HSE frequency.
24 HSI(HSIPrescaler), 26 pub freq: Hertz,
25 PLL(PllConfig), 27 /// HSE mode.
26 LSI, 28 pub mode: HseMode,
27} 29}
28 30
29/// The PLL configuration. 31/// PLL Configuration
30/// 32///
31/// * `VCOCLK = source / m * n` 33/// Use this struct to configure the PLL source, input frequency, multiplication factor, and output
32/// * `PLLRCLK = VCOCLK / r` 34/// dividers. Be sure to keep check the datasheet for your specific part for the appropriate
33/// * `PLLQCLK = VCOCLK / q` 35/// frequency ranges for each of these settings.
34/// * `PLLPCLK = VCOCLK / p` 36pub struct Pll {
35#[derive(Clone, Copy)] 37 /// PLL Source clock selection.
36pub struct PllConfig {
37 /// The source from which the PLL receives a clock signal
38 pub source: PllSource, 38 pub source: PllSource,
39 /// The initial divisor of that clock signal
40 pub m: Pllm,
41 /// The PLL VCO multiplier, which must be in the range `8..=86`.
42 pub n: Plln,
43 /// The final divisor for `PLLRCLK` output which drives the system clock
44 pub r: Pllr,
45
46 /// The divisor for the `PLLQCLK` output, if desired
47 pub q: Option<Pllq>,
48
49 /// The divisor for the `PLLPCLK` output, if desired
50 pub p: Option<Pllp>,
51}
52 39
53impl Default for PllConfig { 40 /// PLL pre-divider
54 #[inline] 41 pub prediv: PllPreDiv,
55 fn default() -> PllConfig {
56 // HSI / 1 * 8 / 2 = 64 MHz
57 PllConfig {
58 source: PllSource::HSI,
59 m: Pllm::DIV1,
60 n: Plln::MUL8,
61 r: Pllr::DIV2,
62 q: None,
63 p: None,
64 }
65 }
66}
67 42
68#[derive(Clone, Copy, Eq, PartialEq)] 43 /// PLL multiplication factor for VCO
69pub enum PllSource { 44 pub mul: PllMul,
70 HSI, 45
71 HSE(Hertz, HseMode), 46 /// PLL division factor for P clock (ADC Clock)
47 pub divp: Option<PllPDiv>,
48
49 /// PLL division factor for Q clock (USB, I2S23, SAI1, FDCAN, QSPI)
50 pub divq: Option<PllQDiv>,
51
52 /// PLL division factor for R clock (SYSCLK)
53 pub divr: Option<PllRDiv>,
72} 54}
73 55
74/// Clocks configutation 56/// Clocks configutation
57#[non_exhaustive]
75pub struct Config { 58pub struct Config {
59 /// HSI Enable
60 pub hsi: bool,
61
62 /// HSE Configuration
63 pub hse: Option<Hse>,
64
65 /// System Clock Configuration
76 pub sys: Sysclk, 66 pub sys: Sysclk,
77 pub ahb_pre: AHBPrescaler, 67
78 pub apb_pre: APBPrescaler, 68 /// HSI48 Configuration
79 pub low_power_run: bool,
80 pub ls: super::LsConfig,
81 #[cfg(crs)] 69 #[cfg(crs)]
82 pub hsi48: Option<super::Hsi48Config>, 70 pub hsi48: Option<super::Hsi48Config>,
71
72 /// PLL Configuration
73 pub pll: Option<Pll>,
74
75 /// If PLL is requested as the main clock source in the `sys` field then the PLL configuration
76 /// MUST turn on the PLLR output.
77 pub ahb_pre: AHBPrescaler,
78 pub apb1_pre: APBPrescaler,
79
80 /// Low-Speed Clock Configuration
81 pub ls: super::LsConfig,
82
83 pub low_power_run: bool,
84
85 pub voltage_range: VoltageRange,
86
83 /// Per-peripheral kernel clock selection muxes 87 /// Per-peripheral kernel clock selection muxes
84 pub mux: super::mux::ClockMux, 88 pub mux: super::mux::ClockMux,
85} 89}
@@ -88,248 +92,218 @@ impl Default for Config {
88 #[inline] 92 #[inline]
89 fn default() -> Config { 93 fn default() -> Config {
90 Config { 94 Config {
91 sys: Sysclk::HSI(HSIPrescaler::DIV1), 95 hsi: true,
96 hse: None,
97 sys: Sysclk::HSI,
98 #[cfg(crs)]
99 hsi48: Some(Default::default()),
100 pll: None,
92 ahb_pre: AHBPrescaler::DIV1, 101 ahb_pre: AHBPrescaler::DIV1,
93 apb_pre: APBPrescaler::DIV1, 102 apb1_pre: APBPrescaler::DIV1,
94 low_power_run: false, 103 low_power_run: false,
95 ls: Default::default(), 104 ls: Default::default(),
96 #[cfg(crs)] 105 voltage_range: VoltageRange::RANGE1,
97 hsi48: Some(Default::default()),
98 mux: Default::default(), 106 mux: Default::default(),
99 } 107 }
100 } 108 }
101} 109}
102 110
103impl PllConfig { 111#[derive(Default)]
104 pub(crate) fn init(self) -> (Hertz, Option<Hertz>, Option<Hertz>) { 112pub struct PllFreq {
105 let (src, input_freq) = match self.source { 113 pub pll_p: Option<Hertz>,
106 PllSource::HSI => (vals::Pllsrc::HSI, HSI_FREQ), 114 pub pll_q: Option<Hertz>,
107 PllSource::HSE(freq, _) => (vals::Pllsrc::HSE, freq), 115 pub pll_r: Option<Hertz>,
108 };
109
110 let m_freq = input_freq / self.m;
111 // RM0454 § 5.4.4:
112 // > Caution: The software must set these bits so that the PLL input frequency after the
113 // > /M divider is between 2.66 and 16 MHz.
114 debug_assert!(m_freq.0 >= 2_660_000 && m_freq.0 <= 16_000_000);
115
116 let n_freq = m_freq * self.n as u32;
117 // RM0454 § 5.4.4:
118 // > Caution: The software must set these bits so that the VCO output frequency is between
119 // > 64 and 344 MHz.
120 debug_assert!(n_freq.0 >= 64_000_000 && n_freq.0 <= 344_000_000);
121
122 let r_freq = n_freq / self.r;
123 // RM0454 § 5.4.4:
124 // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock.
125 debug_assert!(r_freq.0 <= 64_000_000);
126
127 let q_freq = self.q.map(|q| n_freq / q);
128 let p_freq = self.p.map(|p| n_freq / p);
129
130 // RM0454 § 5.2.3:
131 // > To modify the PLL configuration, proceed as follows:
132 // > 1. Disable the PLL by setting PLLON to 0 in Clock control register (RCC_CR).
133 RCC.cr().modify(|w| w.set_pllon(false));
134
135 // > 2. Wait until PLLRDY is cleared. The PLL is now fully stopped.
136 while RCC.cr().read().pllrdy() {}
137
138 // > 3. Change the desired parameter.
139 // Enable whichever clock source we're using, and wait for it to become ready
140 match self.source {
141 PllSource::HSI => {
142 RCC.cr().write(|w| w.set_hsion(true));
143 while !RCC.cr().read().hsirdy() {}
144 }
145 PllSource::HSE(_, mode) => {
146 RCC.cr().write(|w| {
147 w.set_hsebyp(mode != HseMode::Oscillator);
148 w.set_hseon(true);
149 });
150 while !RCC.cr().read().hserdy() {}
151 }
152 }
153
154 // Configure PLLCFGR
155 RCC.pllcfgr().modify(|w| {
156 w.set_pllr(self.r);
157 w.set_pllren(false);
158 w.set_pllq(self.q.unwrap_or(Pllq::DIV2));
159 w.set_pllqen(false);
160 w.set_pllp(self.p.unwrap_or(Pllp::DIV2));
161 w.set_pllpen(false);
162 w.set_plln(self.n);
163 w.set_pllm(self.m);
164 w.set_pllsrc(src)
165 });
166
167 // > 4. Enable the PLL again by setting PLLON to 1.
168 RCC.cr().modify(|w| w.set_pllon(true));
169
170 // Wait for the PLL to become ready
171 while !RCC.cr().read().pllrdy() {}
172
173 // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL
174 // > configuration register (RCC_PLLCFGR).
175 RCC.pllcfgr().modify(|w| {
176 // We'll use R for system clock, so enable that unconditionally
177 w.set_pllren(true);
178
179 // We may also use Q or P
180 w.set_pllqen(self.q.is_some());
181 w.set_pllpen(self.p.is_some());
182 });
183
184 (r_freq, q_freq, p_freq)
185 }
186} 116}
187 117
188pub(crate) unsafe fn init(config: Config) { 118pub(crate) unsafe fn init(config: Config) {
189 let mut pll1_q_freq = None; 119 // Configure HSI
190 let mut pll1_p_freq = None; 120 let hsi = match config.hsi {
191 121 false => {
192 let (sys_clk, sw) = match config.sys { 122 RCC.cr().modify(|w| w.set_hsion(false));
193 Sysclk::HSI(div) => { 123 None
194 // Enable HSI 124 }
195 RCC.cr().write(|w| { 125 true => {
196 w.set_hsidiv(div); 126 RCC.cr().modify(|w| w.set_hsion(true));
197 w.set_hsion(true)
198 });
199 while !RCC.cr().read().hsirdy() {} 127 while !RCC.cr().read().hsirdy() {}
200 128 Some(HSI_FREQ)
201 (HSI_FREQ / div, Sw::HSI)
202 } 129 }
203 Sysclk::HSE(freq, mode) => { 130 };
204 // Enable HSE
205 RCC.cr().write(|w| {
206 w.set_hseon(true);
207 w.set_hsebyp(mode != HseMode::Oscillator);
208 });
209 while !RCC.cr().read().hserdy() {}
210 131
211 (freq, Sw::HSE) 132 // Configure HSE
133 let hse = match config.hse {
134 None => {
135 RCC.cr().modify(|w| w.set_hseon(false));
136 None
212 } 137 }
213 Sysclk::PLL(pll) => { 138 Some(hse) => {
214 let (r_freq, q_freq, p_freq) = pll.init(); 139 match hse.mode {
215 140 HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)),
216 pll1_q_freq = q_freq; 141 HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)),
217 pll1_p_freq = p_freq; 142 }
218 143
219 (r_freq, Sw::PLL1_R) 144 RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator));
220 } 145 RCC.cr().modify(|w| w.set_hseon(true));
221 Sysclk::LSI => { 146 while !RCC.cr().read().hserdy() {}
222 // Enable LSI 147 Some(hse.freq)
223 RCC.csr().write(|w| w.set_lsion(true));
224 while !RCC.csr().read().lsirdy() {}
225 (super::LSI_FREQ, Sw::LSI)
226 } 148 }
227 }; 149 };
228 150
229 // Determine the flash latency implied by the target clock speed 151 // Configure HSI48 if required
230 // RM0454 § 3.3.4: 152 #[cfg(crs)]
231 let target_flash_latency = if sys_clk.0 <= 24_000_000 { 153 let hsi48 = config.hsi48.map(super::init_hsi48);
232 Latency::WS0
233 } else if sys_clk.0 <= 48_000_000 {
234 Latency::WS1
235 } else {
236 Latency::WS2
237 };
238 154
239 // Increase the number of cycles we wait for flash if the new value is higher 155 let pll = config
240 // There's no harm in waiting a little too much before the clock change, but we'll 156 .pll
241 // crash immediately if we don't wait enough after the clock change 157 .map(|pll_config| {
242 let mut set_flash_latency_after = false; 158 let src_freq = match pll_config.source {
243 FLASH.acr().modify(|w| { 159 PllSource::HSI => unwrap!(hsi),
244 // Is the current flash latency less than what we need at the new SYSCLK? 160 PllSource::HSE => unwrap!(hse),
245 if w.latency().to_bits() <= target_flash_latency.to_bits() { 161 _ => unreachable!(),
246 // We must increase the number of wait states now 162 };
247 w.set_latency(target_flash_latency) 163
248 } else { 164 // Disable PLL before configuration
249 // We may decrease the number of wait states later 165 RCC.cr().modify(|w| w.set_pllon(false));
250 set_flash_latency_after = true; 166 while RCC.cr().read().pllrdy() {}
251 } 167
168 let in_freq = src_freq / pll_config.prediv;
169 assert!(max::PLL_IN.contains(&in_freq));
170 let internal_freq = in_freq * pll_config.mul;
171
172 assert!(max::PLL_VCO.contains(&internal_freq));
173
174 RCC.pllcfgr().write(|w| {
175 w.set_plln(pll_config.mul);
176 w.set_pllm(pll_config.prediv);
177 w.set_pllsrc(pll_config.source.into());
178 });
252 179
253 // RM0454 § 3.3.5: 180 let pll_p_freq = pll_config.divp.map(|div_p| {
254 // > Prefetch is enabled by setting the PRFTEN bit of the FLASH access control register 181 RCC.pllcfgr().modify(|w| {
255 // > (FLASH_ACR). This feature is useful if at least one wait state is needed to access the 182 w.set_pllp(div_p);
256 // > Flash memory. 183 w.set_pllpen(true);
257 // 184 });
258 // Enable flash prefetching if we have at least one wait state, and disable it otherwise. 185 let freq = internal_freq / div_p;
259 w.set_prften(target_flash_latency.to_bits() > 0); 186 assert!(max::PLL_P.contains(&freq));
260 }); 187 freq
188 });
261 189
262 if !set_flash_latency_after { 190 let pll_q_freq = pll_config.divq.map(|div_q| {
263 // Spin until the effective flash latency is compatible with the clock change 191 RCC.pllcfgr().modify(|w| {
264 while FLASH.acr().read().latency().to_bits() < target_flash_latency.to_bits() {} 192 w.set_pllq(div_q);
265 } 193 w.set_pllqen(true);
194 });
195 let freq = internal_freq / div_q;
196 assert!(max::PLL_Q.contains(&freq));
197 freq
198 });
266 199
267 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once 200 let pll_r_freq = pll_config.divr.map(|div_r| {
268 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre); 201 RCC.pllcfgr().modify(|w| {
269 RCC.cfgr().modify(|w| { 202 w.set_pllr(div_r);
270 w.set_sw(sw); 203 w.set_pllren(true);
271 w.set_hpre(hpre); 204 });
272 w.set_ppre(ppre); 205 let freq = internal_freq / div_r;
273 }); 206 assert!(max::PLL_R.contains(&freq));
207 freq
208 });
274 209
275 if set_flash_latency_after { 210 // Enable the PLL
276 // We can make the flash require fewer wait states 211 RCC.cr().modify(|w| w.set_pllon(true));
277 // Spin until the SYSCLK changes have taken effect 212 while !RCC.cr().read().pllrdy() {}
278 loop { 213
279 let cfgr = RCC.cfgr().read(); 214 PllFreq {
280 if cfgr.sw() == sw && cfgr.hpre() == hpre && cfgr.ppre() == ppre { 215 pll_p: pll_p_freq,
281 break; 216 pll_q: pll_q_freq,
217 pll_r: pll_r_freq,
282 } 218 }
283 } 219 })
220 .unwrap_or_default();
221
222 let sys = match config.sys {
223 Sysclk::HSI => unwrap!(hsi),
224 Sysclk::HSE => unwrap!(hse),
225 Sysclk::PLL1_R => unwrap!(pll.pll_r),
226 _ => unreachable!(),
227 };
284 228
285 // Set the flash latency to require fewer wait states 229 assert!(max::SYSCLK.contains(&sys));
286 FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
287 }
288 230
289 let ahb_freq = sys_clk / config.ahb_pre; 231 // Calculate the AHB frequency (HCLK), among other things so we can calculate the correct flash read latency.
232 let hclk = sys / config.ahb_pre;
233 assert!(max::HCLK.contains(&hclk));
290 234
291 let (apb_freq, apb_tim_freq) = match config.apb_pre { 235 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
292 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 236 assert!(max::PCLK.contains(&pclk1));
293 pre => { 237
294 let freq = ahb_freq / pre; 238 let latency = match (config.voltage_range, hclk.0) {
295 (freq, freq * 2u32) 239 (VoltageRange::RANGE1, ..=24_000_000) => Latency::WS0,
296 } 240 (VoltageRange::RANGE1, ..=48_000_000) => Latency::WS1,
241 (VoltageRange::RANGE1, _) => Latency::WS2,
242 (VoltageRange::RANGE2, ..=8_000_000) => Latency::WS0,
243 (VoltageRange::RANGE2, ..=16_000_000) => Latency::WS1,
244 (VoltageRange::RANGE2, _) => Latency::WS2,
245 _ => unreachable!(),
297 }; 246 };
298 247
248 // Configure flash read access latency based on voltage scale and frequency (RM0444 3.3.4)
249 FLASH.acr().modify(|w| {
250 w.set_latency(latency);
251 });
252
253 // Spin until the effective flash latency is set.
254 while FLASH.acr().read().latency() != latency {}
255
256 // Now that boost mode and flash read access latency are configured, set up SYSCLK
257 RCC.cfgr().modify(|w| {
258 w.set_sw(config.sys);
259 w.set_hpre(config.ahb_pre);
260 w.set_ppre(config.apb1_pre);
261 });
262
299 if config.low_power_run { 263 if config.low_power_run {
300 assert!(sys_clk.0 <= 2_000_000); 264 assert!(sys <= Hertz(2_000_000));
301 PWR.cr1().modify(|w| w.set_lpr(true)); 265 PWR.cr1().modify(|w| w.set_lpr(true));
302 } 266 }
303 267
304 let rtc = config.ls.init(); 268 let rtc = config.ls.init();
305 let lse_freq = config.ls.lse.map(|lse| lse.frequency);
306
307 let hsi_freq = (sw == Sw::HSI).then_some(HSI_FREQ);
308 let hsi_div_8_freq = hsi_freq.map(|f| f / 8u32);
309 let lsi_freq = (sw == Sw::LSI).then_some(super::LSI_FREQ);
310 let hse_freq = (sw == Sw::HSE).then_some(sys_clk);
311
312 #[cfg(crs)]
313 let hsi48 = config.hsi48.map(super::init_hsi48);
314 #[cfg(not(crs))]
315 let hsi48: Option<Hertz> = None;
316 269
317 config.mux.init(); 270 config.mux.init();
318 271
319 set_clocks!( 272 set_clocks!(
320 sys: Some(sys_clk), 273 sys: Some(sys),
321 hclk1: Some(ahb_freq), 274 hclk1: Some(hclk),
322 pclk1: Some(apb_freq), 275 pclk1: Some(pclk1),
323 pclk1_tim: Some(apb_tim_freq), 276 pclk1_tim: Some(pclk1_tim),
324 hsi: hsi_freq, 277 pll1_p: pll.pll_p,
278 pll1_q: pll.pll_q,
279 pll1_r: pll.pll_r,
280 hsi: hsi,
281 hse: hse,
282 #[cfg(crs)]
325 hsi48: hsi48, 283 hsi48: hsi48,
326 hsi_div_8: hsi_div_8_freq,
327 hse: hse_freq,
328 lse: lse_freq,
329 lsi: lsi_freq,
330 pll1_q: pll1_q_freq,
331 pll1_p: pll1_p_freq,
332 rtc: rtc, 284 rtc: rtc,
333 hsi_div_488: None, 285 hsi_div_8: hsi.map(|h| h / 8u32),
286 hsi_div_488: hsi.map(|h| h / 488u32),
287
288 // TODO
289 lsi: None,
290 lse: None,
334 ); 291 );
335} 292}
293
294mod max {
295 use core::ops::RangeInclusive;
296
297 use crate::time::Hertz;
298
299 pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(48_000_000);
300 pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000);
301 pub(crate) const SYSCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(64_000_000);
302 pub(crate) const PCLK: RangeInclusive<Hertz> = Hertz(8)..=Hertz(64_000_000);
303 pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(64_000_000);
304 pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(2_660_000)..=Hertz(16_000_000);
305 pub(crate) const PLL_VCO: RangeInclusive<Hertz> = Hertz(96_000_000)..=Hertz(344_000_000);
306 pub(crate) const PLL_P: RangeInclusive<Hertz> = Hertz(3_090_000)..=Hertz(122_000_000);
307 pub(crate) const PLL_Q: RangeInclusive<Hertz> = Hertz(12_000_000)..=Hertz(128_000_000);
308 pub(crate) const PLL_R: RangeInclusive<Hertz> = Hertz(12_000_000)..=Hertz(64_000_000);
309}
diff --git a/examples/stm32g0/src/bin/hf_timer.rs b/examples/stm32g0/src/bin/hf_timer.rs
index 647ff0419..3ea06cdee 100644
--- a/examples/stm32g0/src/bin/hf_timer.rs
+++ b/examples/stm32g0/src/bin/hf_timer.rs
@@ -16,15 +16,16 @@ async fn main(_spawner: Spawner) {
16 let mut config = PeripheralConfig::default(); 16 let mut config = PeripheralConfig::default();
17 { 17 {
18 use embassy_stm32::rcc::*; 18 use embassy_stm32::rcc::*;
19 19 config.rcc.hsi = true;
20 config.rcc.sys = Sysclk::PLL(PllConfig { 20 config.rcc.pll = Some(Pll {
21 source: PllSource::HSI, 21 source: PllSource::HSI,
22 m: Pllm::DIV1, 22 prediv: PllPreDiv::DIV1,
23 n: Plln::MUL16, 23 mul: PllMul::MUL16,
24 r: Pllr::DIV4, // CPU clock comes from PLLR (HSI (16MHz) / 1 * 16 / 4 = 64MHz) 24 divp: None,
25 q: Some(Pllq::DIV2), // TIM1 or TIM15 can be sourced from PLLQ (HSI (16MHz) / 1 * 16 / 2 = 128MHz) 25 divq: Some(PllQDiv::DIV2), // 16 / 1 * 16 / 2 = 128 Mhz
26 p: None, 26 divr: Some(PllRDiv::DIV4), // 16 / 1 * 16 / 4 = 64 Mhz
27 }); 27 });
28 config.rcc.sys = Sysclk::PLL1_R;
28 29
29 // configure TIM1 mux to select PLLQ as clock source 30 // configure TIM1 mux to select PLLQ as clock source
30 // https://www.st.com/resource/en/reference_manual/rm0444-stm32g0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf 31 // https://www.st.com/resource/en/reference_manual/rm0444-stm32g0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index c3f39c04f..1587a6fb4 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -260,6 +260,19 @@ pub fn config() -> Config {
260 #[allow(unused_mut)] 260 #[allow(unused_mut)]
261 let mut config = Config::default(); 261 let mut config = Config::default();
262 262
263 #[cfg(feature = "stm32g071rb")]
264 {
265 config.rcc.hsi = true;
266 config.rcc.pll = Some(Pll {
267 source: PllSource::HSI,
268 prediv: PllPreDiv::DIV1,
269 mul: PllMul::MUL16,
270 divp: None,
271 divq: None,
272 divr: Some(PllRDiv::DIV4), // 16 / 1 * 16 / 4 = 64 Mhz
273 });
274 config.rcc.sys = Sysclk::PLL1_R;
275 }
263 #[cfg(feature = "stm32wb55rg")] 276 #[cfg(feature = "stm32wb55rg")]
264 { 277 {
265 config.rcc = embassy_stm32::rcc::WPAN_DEFAULT; 278 config.rcc = embassy_stm32::rcc::WPAN_DEFAULT;