aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Glynn <[email protected]>2023-10-05 22:05:05 -0500
committerWill Glynn <[email protected]>2023-10-05 22:13:27 -0500
commit38e7709a24982231a6a68dca4dddb75eb934c6bf (patch)
treee27a42e1d65b46352175da1c1dbf6035f33f12ad
parent65ed19aae272d6d6320554446f9187ec2ef8bf39 (diff)
stm32: u5: implement >55 MHz clock speeds
This commit allows STM32U5 devices to operate at 160 MHz. On STM32U5, MSIS can run at 48 MHz and HSE can reach 50 MHz. Faster clocks require using PLL1's R output, though PLL1 can serve other functions besides using the R output for the system clock. This commit extracts a public `PllConfig` struct, primarily to place associated constructors on that type, but also with an eye towards enabling the P and Q outputs in a later commit. STM32U5 PLLs have various frequency requirements on each stage: after the `m` prescaler, after the `n` multiplier, and after the `r` divider. This commit implements the associated checks as assertions. This commit fixes clock calculation and PLL register configuration errors in PLL initialization. STM32U5 has a PWR peripheral which can be configured to push Vcore into different voltage ranges. System clocks exceeding 55 MHz require range 2, and system clocks exceeding 110 MHz require range 1. This commit adds `voltage_range` to `Config` and configures PWR as directed. The voltage range implies different performance limits on various clock signals, including inside a PLL. This commit implements voltage range <-> frequency range checks as assertions, and extracts the otherwise-repeated MSIS, HSI16, and HSE initialization into private methods on `Config`. STM32U5 frequencies above 55 MHz require using the PWR EPOD booster. The EPOD booster requires configuring a second `m` term for PLL1, `mboost`, such that it falls in a particular range. (Recall that >50 MHz cannot be reached without PLL1, so there is no scenario where EPOD is needed but PLL1 is not.) This commit configures and enables the EPOD booster automatically as required.
-rw-r--r--embassy-stm32/src/rcc/u5.rs346
-rw-r--r--examples/stm32u5/src/bin/usb_serial.rs7
2 files changed, 267 insertions, 86 deletions
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index d9a531285..14b8577df 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -1,7 +1,7 @@
1use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw}; 1use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllmboost, Pllrge, Pllsrc, Sw};
2 2
3pub use super::bus::{AHBPrescaler, APBPrescaler}; 3pub use super::bus::{AHBPrescaler, APBPrescaler};
4use crate::pac::{FLASH, RCC}; 4use crate::pac::{FLASH, PWR, RCC};
5use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 6use crate::time::Hertz;
7 7
@@ -15,23 +15,86 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale;
15 15
16#[derive(Copy, Clone)] 16#[derive(Copy, Clone)]
17pub enum ClockSrc { 17pub enum ClockSrc {
18 /// Use an internal medium speed oscillator (MSIS) as the system clock.
18 MSI(MSIRange), 19 MSI(MSIRange),
20 /// Use the external high speed clock as the system clock.
21 ///
22 /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
23 /// never exceed 50 MHz.
19 HSE(Hertz), 24 HSE(Hertz),
25 /// Use the 16 MHz internal high speed oscillator as the system clock.
20 HSI16, 26 HSI16,
21 PLL1R(PllSrc, PllM, PllN, PllClkDiv), 27 /// Use PLL1 as the system clock.
28 PLL1R(PllConfig),
29}
30
31impl Default for ClockSrc {
32 fn default() -> Self {
33 // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9
34 ClockSrc::MSI(MSIRange::Range4mhz)
35 }
36}
37
38#[derive(Clone, Copy, Debug)]
39pub struct PllConfig {
40 /// The clock source for the PLL.
41 pub source: PllSrc,
42 /// The PLL prescaler.
43 ///
44 /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz.
45 pub m: PllM,
46 /// The PLL multiplier.
47 ///
48 /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544
49 /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`.
50 pub n: PllN,
51 /// The divider for the R output.
52 ///
53 /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r`
54 /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default
55 /// `Config { voltage_range }`.
56 pub r: PllClkDiv,
57}
58
59impl PllConfig {
60 /// A configuration for HSI16 / 1 * 10 / 1 = 160 MHz
61 pub const fn hsi16_160mhz() -> Self {
62 PllConfig {
63 source: PllSrc::HSI16,
64 m: PllM::NotDivided,
65 n: PllN::Mul10,
66 r: PllClkDiv::NotDivided,
67 }
68 }
69
70 /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz
71 pub const fn msis_160mhz() -> Self {
72 PllConfig {
73 source: PllSrc::MSIS(MSIRange::Range48mhz),
74 m: PllM::Div3,
75 n: PllN::Mul10,
76 r: PllClkDiv::NotDivided,
77 }
78 }
22} 79}
23 80
24#[derive(Clone, Copy, Debug)] 81#[derive(Clone, Copy, Debug)]
25pub enum PllSrc { 82pub enum PllSrc {
26 MSI(MSIRange), 83 /// Use an internal medium speed oscillator as the PLL source.
84 MSIS(MSIRange),
85 /// Use the external high speed clock as the system PLL source.
86 ///
87 /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must
88 /// never exceed 50 MHz.
27 HSE(Hertz), 89 HSE(Hertz),
90 /// Use the 16 MHz internal high speed oscillator as the PLL source.
28 HSI16, 91 HSI16,
29} 92}
30 93
31impl Into<Pllsrc> for PllSrc { 94impl Into<Pllsrc> for PllSrc {
32 fn into(self) -> Pllsrc { 95 fn into(self) -> Pllsrc {
33 match self { 96 match self {
34 PllSrc::MSI(..) => Pllsrc::MSIS, 97 PllSrc::MSIS(..) => Pllsrc::MSIS,
35 PllSrc::HSE(..) => Pllsrc::HSE, 98 PllSrc::HSE(..) => Pllsrc::HSE,
36 PllSrc::HSI16 => Pllsrc::HSI16, 99 PllSrc::HSI16 => Pllsrc::HSI16,
37 } 100 }
@@ -41,57 +104,45 @@ impl Into<Pllsrc> for PllSrc {
41seq_macro::seq!(N in 2..=128 { 104seq_macro::seq!(N in 2..=128 {
42 #[derive(Copy, Clone, Debug)] 105 #[derive(Copy, Clone, Debug)]
43 pub enum PllClkDiv { 106 pub enum PllClkDiv {
44 NotDivided, 107 NotDivided = 1,
45 #( 108 #(
46 Div~N = (N-1), 109 Div~N = N,
47 )* 110 )*
48 } 111 }
49 112
50 impl PllClkDiv { 113 impl PllClkDiv {
51 fn to_div(&self) -> u8 { 114 fn to_div(&self) -> u8 {
52 match self { 115 match self {
53 PllClkDiv::NotDivided => 1, 116 PllClkDiv::NotDivided => 0,
54 #( 117 #(
55 PllClkDiv::Div~N => N + 1, 118 PllClkDiv::Div~N => N - 1,
56 )* 119 )*
57 } 120 }
58 } 121 }
59 } 122 }
60}); 123});
61 124
62impl Into<u8> for PllClkDiv {
63 fn into(self) -> u8 {
64 (self as u8) + 1
65 }
66}
67
68seq_macro::seq!(N in 4..=512 { 125seq_macro::seq!(N in 4..=512 {
69 #[derive(Copy, Clone, Debug)] 126 #[derive(Copy, Clone, Debug)]
70 pub enum PllN { 127 pub enum PllN {
71 NotMultiplied, 128 NotMultiplied = 1,
72 #( 129 #(
73 Mul~N = N-1, 130 Mul~N = N,
74 )* 131 )*
75 } 132 }
76 133
77 impl PllN { 134 impl PllN {
78 fn to_mul(&self) -> u16 { 135 fn to_mul(&self) -> u16 {
79 match self { 136 match self {
80 PllN::NotMultiplied => 1, 137 PllN::NotMultiplied => 0,
81 #( 138 #(
82 PllN::Mul~N => N + 1, 139 PllN::Mul~N => N - 1,
83 )* 140 )*
84 } 141 }
85 } 142 }
86 } 143 }
87}); 144});
88 145
89impl Into<u16> for PllN {
90 fn into(self) -> u16 {
91 (self as u16) + 1
92 }
93}
94
95// Pre-division 146// Pre-division
96#[derive(Copy, Clone, Debug)] 147#[derive(Copy, Clone, Debug)]
97pub enum PllM { 148pub enum PllM {
@@ -132,6 +183,7 @@ impl Into<Sw> for ClockSrc {
132 183
133#[derive(Debug, Copy, Clone)] 184#[derive(Debug, Copy, Clone)]
134pub enum MSIRange { 185pub enum MSIRange {
186 /// The 48 MHz MSI speed is unavailable in `VoltageScale::RANGE4`.
135 Range48mhz = 48_000_000, 187 Range48mhz = 48_000_000,
136 Range24mhz = 24_000_000, 188 Range24mhz = 24_000_000,
137 Range16mhz = 16_000_000, 189 Range16mhz = 16_000_000,
@@ -179,12 +231,6 @@ impl Into<Msirange> for MSIRange {
179 } 231 }
180} 232}
181 233
182impl Default for MSIRange {
183 fn default() -> Self {
184 MSIRange::Range4mhz
185 }
186}
187
188#[derive(Copy, Clone)] 234#[derive(Copy, Clone)]
189pub struct Config { 235pub struct Config {
190 pub mux: ClockSrc, 236 pub mux: ClockSrc,
@@ -193,103 +239,220 @@ pub struct Config {
193 pub apb2_pre: APBPrescaler, 239 pub apb2_pre: APBPrescaler,
194 pub apb3_pre: APBPrescaler, 240 pub apb3_pre: APBPrescaler,
195 pub hsi48: bool, 241 pub hsi48: bool,
242 /// The voltage range influences the maximum clock frequencies for different parts of the
243 /// device. In particular, system clocks exceeding 110 MHz require `RANGE1`, and system clocks
244 /// exceeding 55 MHz require at least `RANGE2`.
245 ///
246 /// See RM0456 § 10.5.4 for a general overview and § 11.4.10 for clock source frequency limits.
247 pub voltage_range: VoltageScale,
248}
249
250impl Config {
251 unsafe fn init_hsi16(&self) -> Hertz {
252 RCC.cr().write(|w| w.set_hsion(true));
253 while !RCC.cr().read().hsirdy() {}
254
255 HSI_FREQ
256 }
257
258 unsafe fn init_hse(&self, frequency: Hertz) -> Hertz {
259 // Check frequency limits per RM456 § 11.4.10
260 match self.voltage_range {
261 VoltageScale::RANGE1 | VoltageScale::RANGE2 | VoltageScale::RANGE3 => {
262 assert!(frequency.0 <= 50_000_000);
263 }
264 VoltageScale::RANGE4 => {
265 assert!(frequency.0 <= 25_000_000);
266 }
267 }
268
269 // Enable HSE, and wait for it to stabilize
270 RCC.cr().write(|w| w.set_hseon(true));
271 while !RCC.cr().read().hserdy() {}
272
273 frequency
274 }
275
276 unsafe fn init_msis(&self, range: MSIRange) -> Hertz {
277 // Check MSI output per RM0456 § 11.4.10
278 match self.voltage_range {
279 VoltageScale::RANGE4 => {
280 assert!(range as u32 <= 24_000_000);
281 }
282 _ => {}
283 }
284
285 // RM0456 § 11.8.2: spin until MSIS is off or MSIS is ready before setting its range
286 loop {
287 let cr = RCC.cr().read();
288 if cr.msison() == false || cr.msisrdy() == true {
289 break;
290 }
291 }
292
293 RCC.icscr1().modify(|w| {
294 let bits: Msirange = range.into();
295 w.set_msisrange(bits);
296 w.set_msirgsel(Msirgsel::RCC_ICSCR1);
297 });
298 RCC.cr().write(|w| {
299 w.set_msipllen(false);
300 w.set_msison(true);
301 });
302 while !RCC.cr().read().msisrdy() {}
303 Hertz(range as u32)
304 }
196} 305}
197 306
198impl Default for Config { 307impl Default for Config {
199 fn default() -> Self { 308 fn default() -> Self {
200 Self { 309 Self {
201 mux: ClockSrc::MSI(MSIRange::default()), 310 mux: ClockSrc::default(),
202 ahb_pre: AHBPrescaler::DIV1, 311 ahb_pre: AHBPrescaler::DIV1,
203 apb1_pre: APBPrescaler::DIV1, 312 apb1_pre: APBPrescaler::DIV1,
204 apb2_pre: APBPrescaler::DIV1, 313 apb2_pre: APBPrescaler::DIV1,
205 apb3_pre: APBPrescaler::DIV1, 314 apb3_pre: APBPrescaler::DIV1,
206 hsi48: false, 315 hsi48: false,
316 voltage_range: VoltageScale::RANGE3,
207 } 317 }
208 } 318 }
209} 319}
210 320
211pub(crate) unsafe fn init(config: Config) { 321pub(crate) unsafe fn init(config: Config) {
322 // Ensure PWR peripheral clock is enabled
323 RCC.ahb3enr().modify(|w| {
324 w.set_pwren(true);
325 });
326 RCC.ahb3enr().read(); // synchronize
327
328 // Set the requested power mode
329 PWR.vosr().modify(|w| {
330 w.set_vos(config.voltage_range);
331 });
332 while !PWR.vosr().read().vosrdy() {}
333
212 let sys_clk = match config.mux { 334 let sys_clk = match config.mux {
213 ClockSrc::MSI(range) => { 335 ClockSrc::MSI(range) => config.init_msis(range),
214 RCC.icscr1().modify(|w| { 336 ClockSrc::HSE(freq) => config.init_hse(freq),
215 let bits: Msirange = range.into(); 337 ClockSrc::HSI16 => config.init_hsi16(),
216 w.set_msisrange(bits); 338 ClockSrc::PLL1R(pll) => {
217 w.set_msirgsel(Msirgsel::RCC_ICSCR1); 339 // Configure the PLL source
218 }); 340 let source_clk = match pll.source {
219 RCC.cr().write(|w| { 341 PllSrc::MSIS(range) => config.init_msis(range),
220 w.set_msipllen(false); 342 PllSrc::HSE(hertz) => config.init_hse(hertz),
221 w.set_msison(true); 343 PllSrc::HSI16 => config.init_hsi16(),
222 }); 344 };
223 while !RCC.cr().read().msisrdy() {}
224 345
225 range.into() 346 // Calculate the reference clock, which is the source divided by m
226 } 347 let reference_clk = source_clk / (pll.m as u8 as u32 + 1);
227 ClockSrc::HSE(freq) => {
228 RCC.cr().write(|w| w.set_hseon(true));
229 while !RCC.cr().read().hserdy() {}
230 348
231 freq.0 349 // Check limits per RM0456 § 11.4.6
232 } 350 assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16));
233 ClockSrc::HSI16 => {
234 RCC.cr().write(|w| w.set_hsion(true));
235 while !RCC.cr().read().hsirdy() {}
236 351
237 HSI_FREQ.0 352 // Calculate the PLL1 VCO clock and PLL1 R output clock
238 } 353 let pll1_clk = reference_clk * (pll.n as u8 as u32);
239 ClockSrc::PLL1R(src, m, n, div) => { 354 let pll1r_clk = pll1_clk / (pll.r as u8 as u32);
240 let freq = match src { 355
241 PllSrc::MSI(_) => { 356 // Check system clock per RM0456 § 11.4.9
242 // TODO: enable MSI 357 assert!(pll1r_clk <= Hertz::mhz(160));
243 MSIRange::default().into() 358
359 // Check PLL clocks per RM0456 § 11.4.10
360 match config.voltage_range {
361 VoltageScale::RANGE1 => {
362 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544));
363 assert!(pll1r_clk <= Hertz::mhz(208));
244 } 364 }
245 PllSrc::HSE(hertz) => { 365 VoltageScale::RANGE2 => {
246 // TODO: enable HSE 366 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(544));
247 hertz.0 367 assert!(pll1r_clk <= Hertz::mhz(110));
248 } 368 }
249 PllSrc::HSI16 => { 369 VoltageScale::RANGE3 => {
250 RCC.cr().write(|w| w.set_hsion(true)); 370 assert!(pll1_clk >= Hertz::mhz(128) && pll1_clk <= Hertz::mhz(330));
251 while !RCC.cr().read().hsirdy() {} 371 assert!(pll1r_clk <= Hertz::mhz(55));
372 }
373 VoltageScale::RANGE4 => {
374 panic!("PLL is unavailable in voltage range 4");
375 }
376 }
252 377
253 HSI_FREQ.0 378 // § 10.5.4: if we're targeting >= 55 MHz, we must configure PLL1MBOOST to a prescaler
379 // value that results in an output between 4 and 16 MHz for the PWR EPOD boost
380 let mboost = if pll1r_clk >= Hertz::mhz(55) {
381 // source_clk can be up to 50 MHz, so there's just a few cases:
382 if source_clk > Hertz::mhz(32) {
383 // Divide by 4, giving EPOD 8-12.5 MHz
384 Pllmboost::DIV4
385 } else if source_clk > Hertz::mhz(16) {
386 // Divide by 2, giving EPOD 8-16 MHz
387 Pllmboost::DIV2
388 } else {
389 // Bypass, giving EPOD 4-16 MHz
390 Pllmboost::BYPASS
254 } 391 }
392 } else {
393 // Nothing to do
394 Pllmboost::BYPASS
255 }; 395 };
256 396
257 // disable 397 // Disable the PLL, and wait for it to disable
258 RCC.cr().modify(|w| w.set_pllon(0, false)); 398 RCC.cr().modify(|w| w.set_pllon(0, false));
259 while RCC.cr().read().pllrdy(0) {} 399 while RCC.cr().read().pllrdy(0) {}
260 400
261 let vco = freq * n as u8 as u32; 401 // Configure the PLL
262 let pll_ck = vco / (div as u8 as u32 + 1);
263
264 RCC.pll1cfgr().write(|w| { 402 RCC.pll1cfgr().write(|w| {
265 w.set_pllm(m.into()); 403 // Configure PLL1 source and prescaler
266 w.set_pllsrc(src.into()); 404 w.set_pllsrc(pll.source.into());
405 w.set_pllm(pll.m.into());
406
407 // Configure PLL1 input frequncy range
408 let input_range = if reference_clk <= Hertz::mhz(8) {
409 Pllrge::FREQ_4TO8MHZ
410 } else {
411 Pllrge::FREQ_8TO16MHZ
412 };
413 w.set_pllrge(input_range);
414
415 // Set the prescaler for PWR EPOD
416 w.set_pllmboost(mboost);
417
418 // Enable PLL1R output
267 w.set_pllren(true); 419 w.set_pllren(true);
268 }); 420 });
269 421
422 // Configure the PLL divisors
270 RCC.pll1divr().modify(|w| { 423 RCC.pll1divr().modify(|w| {
271 w.set_pllr(div.to_div()); 424 // Set the VCO multiplier
272 w.set_plln(n.to_mul()); 425 w.set_plln(pll.n.to_mul());
426 // Set the R output divisor
427 w.set_pllr(pll.r.to_div());
273 }); 428 });
274 429
275 // Enable PLL 430 // Do we need the EPOD booster to reach the target clock speed per § 10.5.4?
431 if pll1r_clk >= Hertz::mhz(55) {
432 // Enable the booster
433 PWR.vosr().modify(|w| {
434 w.set_boosten(true);
435 });
436 while !PWR.vosr().read().boostrdy() {}
437 }
438
439 // Enable the PLL
276 RCC.cr().modify(|w| w.set_pllon(0, true)); 440 RCC.cr().modify(|w| w.set_pllon(0, true));
277 while !RCC.cr().read().pllrdy(0) {} 441 while !RCC.cr().read().pllrdy(0) {}
278 442
279 pll_ck 443 pll1r_clk
280 } 444 }
281 }; 445 }
446 .0;
282 447
283 if config.hsi48 { 448 if config.hsi48 {
284 RCC.cr().modify(|w| w.set_hsi48on(true)); 449 RCC.cr().modify(|w| w.set_hsi48on(true));
285 while !RCC.cr().read().hsi48rdy() {} 450 while !RCC.cr().read().hsi48rdy() {}
286 } 451 }
287 452
288 // TODO make configurable 453 // The clock source is ready
289 let power_vos = VoltageScale::RANGE3; 454 // Calculate and set the flash wait states
290 455 let wait_states = match config.voltage_range {
291 // states and programming delay
292 let wait_states = match power_vos {
293 // VOS 1 range VCORE 1.26V - 1.40V 456 // VOS 1 range VCORE 1.26V - 1.40V
294 VoltageScale::RANGE1 => { 457 VoltageScale::RANGE1 => {
295 if sys_clk < 32_000_000 { 458 if sys_clk < 32_000_000 {
@@ -335,21 +498,34 @@ pub(crate) unsafe fn init(config: Config) {
335 } 498 }
336 } 499 }
337 }; 500 };
338
339 FLASH.acr().modify(|w| { 501 FLASH.acr().modify(|w| {
340 w.set_latency(wait_states); 502 w.set_latency(wait_states);
341 }); 503 });
342 504
505 // Switch the system clock source
343 RCC.cfgr1().modify(|w| { 506 RCC.cfgr1().modify(|w| {
344 w.set_sw(config.mux.into()); 507 w.set_sw(config.mux.into());
345 }); 508 });
346 509
510 // RM0456 § 11.4.9 specifies maximum bus frequencies per voltage range, but the maximum bus
511 // frequency for each voltage range exactly matches the maximum permitted PLL output frequency.
512 // Given that:
513 //
514 // 1. Any bus frequency can never exceed the system clock frequency;
515 // 2. We checked the PLL output frequency if we're using it as a system clock;
516 // 3. The maximum HSE frequencies at each voltage range are lower than the bus limits, and
517 // we checked the HSE frequency if configured as a system clock; and
518 // 4. The maximum frequencies from the other clock sources are lower than the lowest bus
519 // frequency limit
520 //
521 // ...then we do not need to perform additional bus-related frequency checks.
522
523 // Configure the bus prescalers
347 RCC.cfgr2().modify(|w| { 524 RCC.cfgr2().modify(|w| {
348 w.set_hpre(config.ahb_pre.into()); 525 w.set_hpre(config.ahb_pre.into());
349 w.set_ppre1(config.apb1_pre.into()); 526 w.set_ppre1(config.apb1_pre.into());
350 w.set_ppre2(config.apb2_pre.into()); 527 w.set_ppre2(config.apb2_pre.into());
351 }); 528 });
352
353 RCC.cfgr3().modify(|w| { 529 RCC.cfgr3().modify(|w| {
354 w.set_ppre3(config.apb3_pre.into()); 530 w.set_ppre3(config.apb3_pre.into());
355 }); 531 });
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs
index 9e47fb18a..278bd30f0 100644
--- a/examples/stm32u5/src/bin/usb_serial.rs
+++ b/examples/stm32u5/src/bin/usb_serial.rs
@@ -23,7 +23,12 @@ async fn main(_spawner: Spawner) {
23 info!("Hello World!"); 23 info!("Hello World!");
24 24
25 let mut config = Config::default(); 25 let mut config = Config::default();
26 config.rcc.mux = ClockSrc::PLL1R(PllSrc::HSI16, PllM::Div2, PllN::Mul10, PllClkDiv::NotDivided); 26 config.rcc.mux = ClockSrc::PLL1R(PllConfig {
27 source: PllSrc::HSI16,
28 m: PllM::Div2,
29 n: PllN::Mul10,
30 r: PllClkDiv::NotDivided,
31 });
27 //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); 32 //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz);
28 config.rcc.hsi48 = true; 33 config.rcc.hsi48 = true;
29 34