aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThales Fragoso <[email protected]>2021-05-20 22:08:07 -0300
committerThales Fragoso <[email protected]>2021-05-21 20:16:25 -0300
commit7f65f491e528c64e4e72286624d076331020d1d7 (patch)
tree853682979b4181e6bc159eebc9b6c6083c06b75f
parent82ca5b495e67685af1bd5063d125476269e6ce18 (diff)
Finish initial H7 RCC support
-rw-r--r--embassy-stm32/src/lib.rs3
-rw-r--r--embassy-stm32/src/pwr/h7.rs71
-rw-r--r--embassy-stm32/src/pwr/mod.rs4
-rw-r--r--embassy-stm32/src/rcc/h7/mod.rs380
-rw-r--r--embassy-stm32/src/rcc/h7/pll.rs2
-rw-r--r--embassy-stm32/src/sdmmc/v2.rs1
6 files changed, 424 insertions, 37 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 8d7b67b74..2fc07cd5e 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -13,7 +13,8 @@ pub mod fmt;
13pub mod dma; 13pub mod dma;
14pub mod exti; 14pub mod exti;
15pub mod gpio; 15pub mod gpio;
16mod rcc; 16pub mod pwr;
17pub mod rcc;
17#[cfg(feature = "_rng")] 18#[cfg(feature = "_rng")]
18pub mod rng; 19pub mod rng;
19#[cfg(feature = "_sdmmc")] 20#[cfg(feature = "_sdmmc")]
diff --git a/embassy-stm32/src/pwr/h7.rs b/embassy-stm32/src/pwr/h7.rs
new file mode 100644
index 000000000..939e93eb2
--- /dev/null
+++ b/embassy-stm32/src/pwr/h7.rs
@@ -0,0 +1,71 @@
1use crate::pac::peripherals;
2use crate::pac::{PWR, RCC, SYSCFG};
3
4/// Voltage Scale
5///
6/// Represents the voltage range feeding the CPU core. The maximum core
7/// clock frequency depends on this value.
8#[derive(Copy, Clone, PartialEq)]
9pub enum VoltageScale {
10 /// VOS 0 range VCORE 1.26V - 1.40V
11 Scale0,
12 /// VOS 1 range VCORE 1.15V - 1.26V
13 Scale1,
14 /// VOS 2 range VCORE 1.05V - 1.15V
15 Scale2,
16 /// VOS 3 range VCORE 0.95V - 1.05V
17 Scale3,
18}
19
20/// Power Configuration
21///
22/// Generated when the PWR peripheral is frozen. The existence of this
23/// value indicates that the voltage scaling configuration can no
24/// longer be changed.
25pub struct Power {
26 pub(crate) vos: VoltageScale,
27}
28
29impl Power {
30 pub fn new(_peri: peripherals::PWR, enable_overdrive: bool) -> Self {
31 use crate::pac::rcc::vals::Apb4enrSyscfgen;
32
33 // NOTE(unsafe) we have the PWR singleton
34 unsafe {
35 // NB. The lower bytes of CR3 can only be written once after
36 // POR, and must be written with a valid combination. Refer to
37 // RM0433 Rev 7 6.8.4. This is partially enforced by dropping
38 // `self` at the end of this method, but of course we cannot
39 // know what happened between the previous POR and here.
40 PWR.cr3().modify(|w| {
41 w.set_scuen(true);
42 w.set_ldoen(true);
43 w.set_bypass(false);
44 });
45 // Validate the supply configuration. If you are stuck here, it is
46 // because the voltages on your board do not match those specified
47 // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset
48 // VOS = Scale 3, so check that the voltage on the VCAP pins =
49 // 1.0V.
50 while !PWR.csr1().read().actvosrdy() {}
51
52 // Go to Scale 1
53 PWR.d3cr().modify(|w| w.set_vos(0b11));
54 while !PWR.d3cr().read().vosrdy() {}
55
56 let vos = if !enable_overdrive {
57 VoltageScale::Scale1
58 } else {
59 critical_section::with(|_| {
60 RCC.apb4enr()
61 .modify(|w| w.set_syscfgen(Apb4enrSyscfgen::ENABLED));
62
63 SYSCFG.pwrcr().modify(|w| w.set_oden(1));
64 });
65 while !PWR.d3cr().read().vosrdy() {}
66 VoltageScale::Scale0
67 };
68 Self { vos }
69 }
70 }
71}
diff --git a/embassy-stm32/src/pwr/mod.rs b/embassy-stm32/src/pwr/mod.rs
new file mode 100644
index 000000000..0bf62ef7c
--- /dev/null
+++ b/embassy-stm32/src/pwr/mod.rs
@@ -0,0 +1,4 @@
1#[cfg(feature = "_stm32h7")]
2mod h7;
3#[cfg(feature = "_stm32h7")]
4pub use h7::*;
diff --git a/embassy-stm32/src/rcc/h7/mod.rs b/embassy-stm32/src/rcc/h7/mod.rs
index b27eff747..8112ae999 100644
--- a/embassy-stm32/src/rcc/h7/mod.rs
+++ b/embassy-stm32/src/rcc/h7/mod.rs
@@ -1,11 +1,12 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy::util::Unborrow; 3use embassy::util::Unborrow;
4use embassy_extras::unborrow;
5 4
6use crate::fmt::assert; 5use crate::fmt::{assert, panic};
7use crate::pac::peripherals; 6use crate::pac::peripherals;
8use crate::pac::RCC; 7use crate::pac::rcc::vals::Timpre;
8use crate::pac::{RCC, SYSCFG};
9use crate::pwr::{Power, VoltageScale};
9use crate::time::Hertz; 10use crate::time::Hertz;
10 11
11mod pll; 12mod pll;
@@ -17,6 +18,39 @@ const CSI: Hertz = Hertz(4_000_000);
17const HSI48: Hertz = Hertz(48_000_000); 18const HSI48: Hertz = Hertz(48_000_000);
18const LSI: Hertz = Hertz(32_000); 19const LSI: Hertz = Hertz(32_000);
19 20
21/// Core clock frequencies
22#[derive(Clone, Copy)]
23pub struct CoreClocks {
24 pub hclk: Hertz,
25 pub pclk1: Hertz,
26 pub pclk2: Hertz,
27 pub pclk3: Hertz,
28 pub pclk4: Hertz,
29 pub ppre1: u8,
30 pub ppre2: u8,
31 pub ppre3: u8,
32 pub ppre4: u8,
33 pub csi_ck: Option<Hertz>,
34 pub hsi_ck: Option<Hertz>,
35 pub hsi48_ck: Option<Hertz>,
36 pub lsi_ck: Option<Hertz>,
37 pub per_ck: Option<Hertz>,
38 pub hse_ck: Option<Hertz>,
39 pub pll1_p_ck: Option<Hertz>,
40 pub pll1_q_ck: Option<Hertz>,
41 pub pll1_r_ck: Option<Hertz>,
42 pub pll2_p_ck: Option<Hertz>,
43 pub pll2_q_ck: Option<Hertz>,
44 pub pll2_r_ck: Option<Hertz>,
45 pub pll3_p_ck: Option<Hertz>,
46 pub pll3_q_ck: Option<Hertz>,
47 pub pll3_r_ck: Option<Hertz>,
48 pub timx_ker_ck: Option<Hertz>,
49 pub timy_ker_ck: Option<Hertz>,
50 pub sys_ck: Hertz,
51 pub c_ck: Hertz,
52}
53
20/// Configuration of the core clocks 54/// Configuration of the core clocks
21#[non_exhaustive] 55#[non_exhaustive]
22#[derive(Default)] 56#[derive(Default)]
@@ -34,29 +68,6 @@ pub struct Config {
34 pub pll1: PllConfig, 68 pub pll1: PllConfig,
35 pub pll2: PllConfig, 69 pub pll2: PllConfig,
36 pub pll3: PllConfig, 70 pub pll3: PllConfig,
37 pub vos: VoltageScale,
38}
39
40/// Voltage Scale
41///
42/// Represents the voltage range feeding the CPU core. The maximum core
43/// clock frequency depends on this value.
44#[derive(Copy, Clone, PartialEq)]
45pub enum VoltageScale {
46 /// VOS 0 range VCORE 1.26V - 1.40V
47 Scale0,
48 /// VOS 1 range VCORE 1.15V - 1.26V
49 Scale1,
50 /// VOS 2 range VCORE 1.05V - 1.15V
51 Scale2,
52 /// VOS 3 range VCORE 0.95V - 1.05V
53 Scale3,
54}
55
56impl Default for VoltageScale {
57 fn default() -> Self {
58 Self::Scale1
59 }
60} 71}
61 72
62pub struct Rcc<'d> { 73pub struct Rcc<'d> {
@@ -91,12 +102,18 @@ impl<'d> Rcc<'d> {
91 /// function may also panic if a clock specification can be 102 /// function may also panic if a clock specification can be
92 /// achieved, but the mechanism for doing so is not yet 103 /// achieved, but the mechanism for doing so is not yet
93 /// implemented here. 104 /// implemented here.
94 pub fn freeze(mut self) { 105 pub fn freeze(mut self, pwr: &Power) -> CoreClocks {
95 use crate::pac::rcc::vals::{Ckpersel, Hpre, Hsidiv, Hsion, Lsion, Timpre}; 106 use crate::pac::rcc::vals::{
107 Apb4enrSyscfgen, Ckpersel, D1ppre, D2ppre1, D3ppre, Hpre, Hsebyp, Hsidiv, Hsion, Lsion,
108 Pllsrc, Sw,
109 };
96 110
97 let srcclk = self.config.hse.unwrap_or(HSI); // Available clocks 111 let srcclk = self.config.hse.unwrap_or(HSI); // Available clocks
98 let (sys_ck, sys_use_pll1_p) = self.sys_ck_setup(srcclk); 112 let (sys_ck, sys_use_pll1_p) = self.sys_ck_setup(srcclk);
99 113
114 // Configure traceclk from PLL if needed
115 self.traceclk_setup(sys_use_pll1_p);
116
100 // NOTE(unsafe) We have exclusive access to the RCC 117 // NOTE(unsafe) We have exclusive access to the RCC
101 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = 118 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) =
102 unsafe { pll_setup(srcclk.0, &self.config.pll1, 0) }; 119 unsafe { pll_setup(srcclk.0, &self.config.pll1, 0) };
@@ -137,13 +154,10 @@ impl<'d> Rcc<'d> {
137 let d1cpre_div = 1; 154 let d1cpre_div = 1;
138 let sys_d1cpre_ck = sys_ck.0 / d1cpre_div; 155 let sys_d1cpre_ck = sys_ck.0 / d1cpre_div;
139 156
140 // Timer prescaler selection
141 let timpre = Timpre::DEFAULTX2;
142
143 // Refer to part datasheet "General operating conditions" 157 // Refer to part datasheet "General operating conditions"
144 // table for (rev V). We do not assert checks for earlier 158 // table for (rev V). We do not assert checks for earlier
145 // revisions which may have lower limits. 159 // revisions which may have lower limits.
146 let (sys_d1cpre_ck_max, rcc_hclk_max, pclk_max) = match self.config.vos { 160 let (sys_d1cpre_ck_max, rcc_hclk_max, pclk_max) = match pwr.vos {
147 VoltageScale::Scale0 => (480_000_000, 240_000_000, 120_000_000), 161 VoltageScale::Scale0 => (480_000_000, 240_000_000, 120_000_000),
148 VoltageScale::Scale1 => (400_000_000, 200_000_000, 100_000_000), 162 VoltageScale::Scale1 => (400_000_000, 200_000_000, 100_000_000),
149 VoltageScale::Scale2 => (300_000_000, 150_000_000, 75_000_000), 163 VoltageScale::Scale2 => (300_000_000, 150_000_000, 75_000_000),
@@ -160,7 +174,7 @@ impl<'d> Rcc<'d> {
160 174
161 // Estimate divisor 175 // Estimate divisor
162 let (hpre_bits, hpre_div) = match (sys_d1cpre_ck + rcc_hclk - 1) / rcc_hclk { 176 let (hpre_bits, hpre_div) = match (sys_d1cpre_ck + rcc_hclk - 1) / rcc_hclk {
163 0 => unreachable!(), 177 0 => panic!(),
164 1 => (Hpre::DIV1, 1), 178 1 => (Hpre::DIV1, 1),
165 2 => (Hpre::DIV2, 2), 179 2 => (Hpre::DIV2, 2),
166 3..=5 => (Hpre::DIV4, 4), 180 3..=5 => (Hpre::DIV4, 4),
@@ -175,8 +189,246 @@ impl<'d> Rcc<'d> {
175 let rcc_hclk = sys_d1cpre_ck / hpre_div; 189 let rcc_hclk = sys_d1cpre_ck / hpre_div;
176 assert!(rcc_hclk <= rcc_hclk_max); 190 assert!(rcc_hclk <= rcc_hclk_max);
177 let rcc_aclk = rcc_hclk; // AXI clock is always equal to AHB clock on H7 191 let rcc_aclk = rcc_hclk; // AXI clock is always equal to AHB clock on H7
192 // Timer prescaler selection
193 let timpre = Timpre::DEFAULTX2;
194
195 let requested_pclk1 = self
196 .config
197 .pclk1
198 .map(|v| v.0)
199 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
200 let (rcc_pclk1, ppre1_bits, ppre1, rcc_timerx_ker_ck) =
201 Self::ppre_calculate(requested_pclk1, rcc_hclk, pclk_max, Some(timpre));
202
203 let requested_pclk2 = self
204 .config
205 .pclk2
206 .map(|v| v.0)
207 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
208 let (rcc_pclk2, ppre2_bits, ppre2, rcc_timery_ker_ck) =
209 Self::ppre_calculate(requested_pclk2, rcc_hclk, pclk_max, Some(timpre));
210
211 let requested_pclk3 = self
212 .config
213 .pclk3
214 .map(|v| v.0)
215 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
216 let (rcc_pclk3, ppre3_bits, ppre3, _) =
217 Self::ppre_calculate(requested_pclk3, rcc_hclk, pclk_max, None);
218
219 let requested_pclk4 = self
220 .config
221 .pclk4
222 .map(|v| v.0)
223 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
224 let (rcc_pclk4, ppre4_bits, ppre4, _) =
225 Self::ppre_calculate(requested_pclk4, rcc_hclk, pclk_max, None);
226
227 Self::flash_setup(rcc_aclk, pwr.vos);
228
229 // Start switching clocks -------------------
230 // NOTE(unsafe) We have the RCC singleton
231 unsafe {
232 // Ensure CSI is on and stable
233 RCC.cr().modify(|w| w.set_csion(Hsion::ON));
234 while !RCC.cr().read().csirdy() {}
235
236 // Ensure HSI48 is on and stable
237 RCC.cr().modify(|w| w.set_hsi48on(Hsion::ON));
238 while RCC.cr().read().hsi48on() == Hsion::OFF {}
239
240 // XXX: support MCO ?
241
242 let hse_ck = match self.config.hse {
243 Some(hse) => {
244 // Ensure HSE is on and stable
245 RCC.cr().modify(|w| {
246 w.set_hseon(Hsion::ON);
247 w.set_hsebyp(if self.config.bypass_hse {
248 Hsebyp::BYPASSED
249 } else {
250 Hsebyp::NOTBYPASSED
251 });
252 });
253 while !RCC.cr().read().hserdy() {}
254 Some(hse)
255 }
256 None => None,
257 };
258
259 let pllsrc = if self.config.hse.is_some() {
260 Pllsrc::HSE
261 } else {
262 Pllsrc::HSI
263 };
264 RCC.pllckselr().modify(|w| w.set_pllsrc(pllsrc));
265
266 if pll1_p_ck.is_some() {
267 RCC.cr().modify(|w| w.set_pll1on(Hsion::ON));
268 while !RCC.cr().read().pll1rdy() {}
269 }
270
271 if pll2_p_ck.is_some() {
272 RCC.cr().modify(|w| w.set_pll2on(Hsion::ON));
273 while !RCC.cr().read().pll2rdy() {}
274 }
275
276 if pll3_p_ck.is_some() {
277 RCC.cr().modify(|w| w.set_pll3on(Hsion::ON));
278 while !RCC.cr().read().pll3rdy() {}
279 }
178 280
179 todo!() 281 // Core Prescaler / AHB Prescaler / APB3 Prescaler
282 RCC.d1cfgr().modify(|w| {
283 w.set_d1cpre(Hpre(d1cpre_bits));
284 w.set_d1ppre(D1ppre(ppre3_bits));
285 w.set_hpre(hpre_bits)
286 });
287 // Ensure core prescaler value is valid before future lower
288 // core voltage
289 while RCC.d1cfgr().read().d1cpre().0 != d1cpre_bits {}
290
291 // APB1 / APB2 Prescaler
292 RCC.d2cfgr().modify(|w| {
293 w.set_d2ppre1(D2ppre1(ppre1_bits));
294 w.set_d2ppre2(D2ppre1(ppre2_bits));
295 });
296
297 // APB4 Prescaler
298 RCC.d3cfgr().modify(|w| w.set_d3ppre(D3ppre(ppre4_bits)));
299
300 // Peripheral Clock (per_ck)
301 RCC.d1ccipr().modify(|w| w.set_ckpersel(ckpersel));
302
303 // Set timer clocks prescaler setting
304 RCC.cfgr().modify(|w| w.set_timpre(timpre));
305
306 // Select system clock source
307 let sw = match (sys_use_pll1_p, self.config.hse.is_some()) {
308 (true, _) => Sw::PLL1,
309 (false, true) => Sw::HSE,
310 _ => Sw::HSI,
311 };
312 RCC.cfgr().modify(|w| w.set_sw(sw));
313 while RCC.cfgr().read().sws() != sw.0 {}
314
315 // IO compensation cell - Requires CSI clock and SYSCFG
316 assert!(RCC.cr().read().csirdy());
317 RCC.apb4enr()
318 .modify(|w| w.set_syscfgen(Apb4enrSyscfgen::ENABLED));
319
320 // Enable the compensation cell, using back-bias voltage code
321 // provide by the cell.
322 critical_section::with(|_| {
323 SYSCFG.cccsr().modify(|w| {
324 w.set_en(true);
325 w.set_cs(false);
326 w.set_hslv(false);
327 })
328 });
329 while !SYSCFG.cccsr().read().ready() {}
330
331 CoreClocks {
332 hclk: Hertz(rcc_hclk),
333 pclk1: Hertz(rcc_pclk1),
334 pclk2: Hertz(rcc_pclk2),
335 pclk3: Hertz(rcc_pclk3),
336 pclk4: Hertz(rcc_pclk4),
337 ppre1,
338 ppre2,
339 ppre3,
340 ppre4,
341 csi_ck: Some(CSI),
342 hsi_ck: Some(HSI),
343 hsi48_ck: Some(HSI48),
344 lsi_ck: Some(LSI),
345 per_ck: Some(per_ck),
346 hse_ck,
347 pll1_p_ck: pll1_p_ck.map(Hertz),
348 pll1_q_ck: pll1_q_ck.map(Hertz),
349 pll1_r_ck: pll1_r_ck.map(Hertz),
350 pll2_p_ck: pll2_p_ck.map(Hertz),
351 pll2_q_ck: pll2_q_ck.map(Hertz),
352 pll2_r_ck: pll2_r_ck.map(Hertz),
353 pll3_p_ck: pll3_p_ck.map(Hertz),
354 pll3_q_ck: pll3_q_ck.map(Hertz),
355 pll3_r_ck: pll3_r_ck.map(Hertz),
356 timx_ker_ck: rcc_timerx_ker_ck.map(Hertz),
357 timy_ker_ck: rcc_timery_ker_ck.map(Hertz),
358 sys_ck,
359 c_ck: Hertz(sys_d1cpre_ck),
360 }
361 }
362 }
363
364 /// Enables debugging during WFI/WFE
365 ///
366 /// Set `enable_dma1` to true if you do not have at least one bus master (other than the CPU)
367 /// enable during WFI/WFE
368 pub fn enable_debug_wfe(&mut self, enable_dma1: bool) {
369 use crate::pac::rcc::vals::Ahb1enrDma1en;
370
371 // NOTE(unsafe) We have exclusive access to the RCC
372 unsafe {
373 if enable_dma1 {
374 RCC.ahb1enr()
375 .modify(|w| w.set_dma1en(Ahb1enrDma1en::ENABLED));
376 }
377 }
378 }
379
380 /// Setup traceclk
381 /// Returns a pll1_r_ck
382 fn traceclk_setup(&mut self, sys_use_pll1_p: bool) {
383 let pll1_r_ck = match (sys_use_pll1_p, self.config.pll1.r_ck) {
384 // pll1_p_ck selected as system clock but pll1_r_ck not
385 // set. The traceclk mux is synchronous with the system
386 // clock mux, but has pll1_r_ck as an input. In order to
387 // keep traceclk running, we force a pll1_r_ck.
388 (true, None) => Some(Hertz(self.config.pll1.p_ck.unwrap().0 / 2)),
389
390 // Either pll1 not selected as system clock, free choice
391 // of pll1_r_ck. Or pll1 is selected, assume user has set
392 // a suitable pll1_r_ck frequency.
393 _ => self.config.pll1.r_ck,
394 };
395 self.config.pll1.r_ck = pll1_r_ck;
396 }
397
398 /// Divider calculator for pclk 1 - 4
399 ///
400 /// Returns real pclk, bits, ppre and the timer kernel clock
401 fn ppre_calculate(
402 requested_pclk: u32,
403 hclk: u32,
404 max_pclk: u32,
405 tim_pre: Option<Timpre>,
406 ) -> (u32, u8, u8, Option<u32>) {
407 let (bits, ppre) = match (hclk + requested_pclk - 1) / requested_pclk {
408 0 => panic!(),
409 1 => (0b000, 1),
410 2 => (0b100, 2),
411 3..=5 => (0b101, 4),
412 6..=11 => (0b110, 8),
413 _ => (0b111, 16),
414 };
415 let real_pclk = hclk / u32::from(ppre);
416 assert!(real_pclk < max_pclk);
417
418 let tim_ker_clk = if let Some(tim_pre) = tim_pre {
419 let clk = match (bits, tim_pre) {
420 (0b101, Timpre::DEFAULTX2) => hclk / 2,
421 (0b110, Timpre::DEFAULTX4) => hclk / 2,
422 (0b110, Timpre::DEFAULTX2) => hclk / 4,
423 (0b111, Timpre::DEFAULTX4) => hclk / 4,
424 (0b111, Timpre::DEFAULTX2) => hclk / 8,
425 _ => hclk,
426 };
427 Some(clk)
428 } else {
429 None
430 };
431 (real_pclk, bits, ppre, tim_ker_clk)
180 } 432 }
181 433
182 /// Setup sys_ck 434 /// Setup sys_ck
@@ -209,4 +461,64 @@ impl<'d> Rcc<'d> {
209 (sys_ck, false) 461 (sys_ck, false)
210 } 462 }
211 } 463 }
464
465 fn flash_setup(rcc_aclk: u32, vos: VoltageScale) {
466 use crate::pac::FLASH;
467
468 // ACLK in MHz, round down and subtract 1 from integers. eg.
469 // 61_999_999 -> 61MHz
470 // 62_000_000 -> 61MHz
471 // 62_000_001 -> 62MHz
472 let rcc_aclk_mhz = (rcc_aclk - 1) / 1_000_000;
473
474 // See RM0433 Rev 7 Table 17. FLASH recommended number of wait
475 // states and programming delay
476 let (wait_states, progr_delay) = match vos {
477 // VOS 0 range VCORE 1.26V - 1.40V
478 VoltageScale::Scale0 => match rcc_aclk_mhz {
479 0..=69 => (0, 0),
480 70..=139 => (1, 1),
481 140..=184 => (2, 1),
482 185..=209 => (2, 2),
483 210..=224 => (3, 2),
484 225..=239 => (4, 2),
485 _ => (7, 3),
486 },
487 // VOS 1 range VCORE 1.15V - 1.26V
488 VoltageScale::Scale1 => match rcc_aclk_mhz {
489 0..=69 => (0, 0),
490 70..=139 => (1, 1),
491 140..=184 => (2, 1),
492 185..=209 => (2, 2),
493 210..=224 => (3, 2),
494 _ => (7, 3),
495 },
496 // VOS 2 range VCORE 1.05V - 1.15V
497 VoltageScale::Scale2 => match rcc_aclk_mhz {
498 0..=54 => (0, 0),
499 55..=109 => (1, 1),
500 110..=164 => (2, 1),
501 165..=224 => (3, 2),
502 _ => (7, 3),
503 },
504 // VOS 3 range VCORE 0.95V - 1.05V
505 VoltageScale::Scale3 => match rcc_aclk_mhz {
506 0..=44 => (0, 0),
507 45..=89 => (1, 1),
508 90..=134 => (2, 1),
509 135..=179 => (3, 2),
510 180..=224 => (4, 2),
511 _ => (7, 3),
512 },
513 };
514
515 // NOTE(unsafe) Atomic write
516 unsafe {
517 FLASH.acr().write(|w| {
518 w.set_wrhighfreq(progr_delay);
519 w.set_latency(wait_states)
520 });
521 while FLASH.acr().read().latency() != wait_states {}
522 }
523 }
212} 524}
diff --git a/embassy-stm32/src/rcc/h7/pll.rs b/embassy-stm32/src/rcc/h7/pll.rs
index ead33e81e..af958d093 100644
--- a/embassy-stm32/src/rcc/h7/pll.rs
+++ b/embassy-stm32/src/rcc/h7/pll.rs
@@ -1,4 +1,4 @@
1use super::{Config, Hertz, HSI, RCC}; 1use super::{Hertz, RCC};
2use crate::fmt::assert; 2use crate::fmt::assert;
3 3
4const VCO_MIN: u32 = 150_000_000; 4const VCO_MIN: u32 = 150_000_000;
diff --git a/embassy-stm32/src/sdmmc/v2.rs b/embassy-stm32/src/sdmmc/v2.rs
index a4da4be8e..d1d485c29 100644
--- a/embassy-stm32/src/sdmmc/v2.rs
+++ b/embassy-stm32/src/sdmmc/v2.rs
@@ -1,7 +1,6 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::default::Default; 3use core::default::Default;
4use core::future::Future;
5use core::marker::PhantomData; 4use core::marker::PhantomData;
6use core::task::Poll; 5use core::task::Poll;
7 6