aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/build.rs2
-rw-r--r--embassy-stm32/src/rcc/c0.rs72
-rw-r--r--embassy-stm32/src/rcc/f2.rs6
-rw-r--r--embassy-stm32/src/rcc/f3.rs187
-rw-r--r--embassy-stm32/src/rcc/g0.rs38
-rw-r--r--embassy-stm32/src/rcc/g4.rs127
-rw-r--r--embassy-stm32/src/rcc/h.rs12
-rw-r--r--embassy-stm32/src/rcc/l0.rs176
-rw-r--r--embassy-stm32/src/rcc/l1.rs207
-rw-r--r--embassy-stm32/src/rcc/l4.rs12
-rw-r--r--embassy-stm32/src/rcc/l5.rs12
-rw-r--r--embassy-stm32/src/rcc/wb.rs180
-rw-r--r--embassy-stm32/src/rcc/wba.rs8
-rw-r--r--embassy-stm32/src/rcc/wl.rs228
-rw-r--r--embassy-stm32/src/time.rs7
-rw-r--r--examples/stm32f334/src/bin/adc.rs4
-rw-r--r--examples/stm32f334/src/bin/opamp.rs4
-rw-r--r--examples/stm32g4/src/bin/adc.rs2
-rw-r--r--tests/stm32/src/common.rs8
20 files changed, 366 insertions, 930 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 70e8f2e29..b6641d71d 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -59,7 +59,7 @@ sdio-host = "0.5.0"
59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
60critical-section = "1.1" 60critical-section = "1.1"
61atomic-polyfill = "1.0.1" 61atomic-polyfill = "1.0.1"
62stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026" } 62stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ff45aa382efb704dd2275dd69e71af73343f149d" }
63vcell = "0.1.3" 63vcell = "0.1.3"
64bxcan = "0.7.0" 64bxcan = "0.7.0"
65nb = "1.0.0" 65nb = "1.0.0"
@@ -77,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] }
77[build-dependencies] 77[build-dependencies]
78proc-macro2 = "1.0.36" 78proc-macro2 = "1.0.36"
79quote = "1.0.15" 79quote = "1.0.15"
80stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026", default-features = false, features = ["metadata"]} 80stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ff45aa382efb704dd2275dd69e71af73343f149d", default-features = false, features = ["metadata"]}
81 81
82 82
83[features] 83[features]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 643f1b6e9..810da37e9 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -908,7 +908,7 @@ fn main() {
908 match e { 908 match e {
909 "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true, 909 "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true,
910 "Timpre" | "Pllrclkpre" => false, 910 "Timpre" | "Pllrclkpre" => false,
911 e if e.ends_with("pre") || e.ends_with("div") || e.ends_with("mul") => true, 911 e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
912 _ => false, 912 _ => false,
913 } 913 }
914 } 914 }
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs
index efa56de7b..34d339a78 100644
--- a/embassy-stm32/src/rcc/c0.rs
+++ b/embassy-stm32/src/rcc/c0.rs
@@ -1,6 +1,6 @@
1use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
2pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 2use crate::pac::rcc::vals::Sw;
3use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; 3pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Hsidiv as HSIPrescaler, Ppre as APBPrescaler};
4use crate::pac::{FLASH, RCC}; 4use crate::pac::{FLASH, RCC};
5use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 6use crate::time::Hertz;
@@ -19,33 +19,6 @@ pub enum ClockSrc {
19 LSI, 19 LSI,
20} 20}
21 21
22#[derive(Clone, Copy)]
23pub enum HSIPrescaler {
24 NotDivided,
25 Div2,
26 Div4,
27 Div8,
28 Div16,
29 Div32,
30 Div64,
31 Div128,
32}
33
34impl Into<Hsidiv> for HSIPrescaler {
35 fn into(self) -> Hsidiv {
36 match self {
37 HSIPrescaler::NotDivided => Hsidiv::DIV1,
38 HSIPrescaler::Div2 => Hsidiv::DIV2,
39 HSIPrescaler::Div4 => Hsidiv::DIV4,
40 HSIPrescaler::Div8 => Hsidiv::DIV8,
41 HSIPrescaler::Div16 => Hsidiv::DIV16,
42 HSIPrescaler::Div32 => Hsidiv::DIV32,
43 HSIPrescaler::Div64 => Hsidiv::DIV64,
44 HSIPrescaler::Div128 => Hsidiv::DIV128,
45 }
46 }
47}
48
49/// Clocks configutation 22/// Clocks configutation
50pub struct Config { 23pub struct Config {
51 pub mux: ClockSrc, 24 pub mux: ClockSrc,
@@ -57,7 +30,7 @@ impl Default for Config {
57 #[inline] 30 #[inline]
58 fn default() -> Config { 31 fn default() -> Config {
59 Config { 32 Config {
60 mux: ClockSrc::HSI(HSIPrescaler::NotDivided), 33 mux: ClockSrc::HSI(HSIPrescaler::DIV1),
61 ahb_pre: AHBPrescaler::DIV1, 34 ahb_pre: AHBPrescaler::DIV1,
62 apb_pre: APBPrescaler::DIV1, 35 apb_pre: APBPrescaler::DIV1,
63 } 36 }
@@ -68,33 +41,32 @@ pub(crate) unsafe fn init(config: Config) {
68 let (sys_clk, sw) = match config.mux { 41 let (sys_clk, sw) = match config.mux {
69 ClockSrc::HSI(div) => { 42 ClockSrc::HSI(div) => {
70 // Enable HSI 43 // Enable HSI
71 let div: Hsidiv = div.into();
72 RCC.cr().write(|w| { 44 RCC.cr().write(|w| {
73 w.set_hsidiv(div); 45 w.set_hsidiv(div);
74 w.set_hsion(true) 46 w.set_hsion(true)
75 }); 47 });
76 while !RCC.cr().read().hsirdy() {} 48 while !RCC.cr().read().hsirdy() {}
77 49
78 (HSI_FREQ.0 >> div.to_bits(), Sw::HSI) 50 (HSI_FREQ / div, Sw::HSI)
79 } 51 }
80 ClockSrc::HSE(freq) => { 52 ClockSrc::HSE(freq) => {
81 // Enable HSE 53 // Enable HSE
82 RCC.cr().write(|w| w.set_hseon(true)); 54 RCC.cr().write(|w| w.set_hseon(true));
83 while !RCC.cr().read().hserdy() {} 55 while !RCC.cr().read().hserdy() {}
84 56
85 (freq.0, Sw::HSE) 57 (freq, Sw::HSE)
86 } 58 }
87 ClockSrc::LSI => { 59 ClockSrc::LSI => {
88 // Enable LSI 60 // Enable LSI
89 RCC.csr2().write(|w| w.set_lsion(true)); 61 RCC.csr2().write(|w| w.set_lsion(true));
90 while !RCC.csr2().read().lsirdy() {} 62 while !RCC.csr2().read().lsirdy() {}
91 (LSI_FREQ.0, Sw::LSI) 63 (LSI_FREQ, Sw::LSI)
92 } 64 }
93 }; 65 };
94 66
95 // Determine the flash latency implied by the target clock speed 67 // Determine the flash latency implied by the target clock speed
96 // RM0454 § 3.3.4: 68 // RM0454 § 3.3.4:
97 let target_flash_latency = if sys_clk <= 24_000_000 { 69 let target_flash_latency = if sys_clk <= Hertz(24_000_000) {
98 Latency::WS0 70 Latency::WS0
99 } else { 71 } else {
100 Latency::WS1 72 Latency::WS1
@@ -129,7 +101,7 @@ pub(crate) unsafe fn init(config: Config) {
129 } 101 }
130 102
131 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once 103 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once
132 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre.into(), config.apb_pre.into()); 104 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre);
133 RCC.cfgr().modify(|w| { 105 RCC.cfgr().modify(|w| {
134 w.set_sw(sw); 106 w.set_sw(sw);
135 w.set_hpre(hpre); 107 w.set_hpre(hpre);
@@ -150,34 +122,20 @@ pub(crate) unsafe fn init(config: Config) {
150 FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); 122 FLASH.acr().modify(|w| w.set_latency(target_flash_latency));
151 } 123 }
152 124
153 let ahb_div = match config.ahb_pre { 125 let ahb_freq = sys_clk / config.ahb_pre;
154 AHBPrescaler::DIV1 => 1,
155 AHBPrescaler::DIV2 => 2,
156 AHBPrescaler::DIV4 => 4,
157 AHBPrescaler::DIV8 => 8,
158 AHBPrescaler::DIV16 => 16,
159 AHBPrescaler::DIV64 => 64,
160 AHBPrescaler::DIV128 => 128,
161 AHBPrescaler::DIV256 => 256,
162 AHBPrescaler::DIV512 => 512,
163 _ => unreachable!(),
164 };
165 let ahb_freq = sys_clk / ahb_div;
166 126
167 let (apb_freq, apb_tim_freq) = match config.apb_pre { 127 let (apb_freq, apb_tim_freq) = match config.apb_pre {
168 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 128 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
169 pre => { 129 pre => {
170 let pre: Ppre = pre.into(); 130 let freq = ahb_freq / pre;
171 let pre: u8 = 1 << (pre.to_bits() - 3); 131 (freq, freq * 2u32)
172 let freq = ahb_freq / pre as u32;
173 (freq, freq * 2)
174 } 132 }
175 }; 133 };
176 134
177 set_freqs(Clocks { 135 set_freqs(Clocks {
178 sys: Hertz(sys_clk), 136 sys: sys_clk,
179 ahb1: Hertz(ahb_freq), 137 ahb1: ahb_freq,
180 apb1: Hertz(apb_freq), 138 apb1: apb_freq,
181 apb1_tim: Hertz(apb_tim_freq), 139 apb1_tim: apb_tim_freq,
182 }); 140 });
183} 141}
diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs
index 07b816bf5..478d8894f 100644
--- a/embassy-stm32/src/rcc/f2.rs
+++ b/embassy-stm32/src/rcc/f2.rs
@@ -301,9 +301,9 @@ pub(crate) unsafe fn init(config: Config) {
301 301
302 RCC.cfgr().modify(|w| { 302 RCC.cfgr().modify(|w| {
303 w.set_sw(sw.into()); 303 w.set_sw(sw.into());
304 w.set_hpre(config.ahb_pre.into()); 304 w.set_hpre(config.ahb_pre);
305 w.set_ppre1(config.apb1_pre.into()); 305 w.set_ppre1(config.apb1_pre);
306 w.set_ppre2(config.apb2_pre.into()); 306 w.set_ppre2(config.apb2_pre);
307 }); 307 });
308 while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {} 308 while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {}
309 309
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index 630dbd4fe..a11eeee54 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -1,7 +1,8 @@
1#[cfg(rcc_f3)] 1#[cfg(rcc_f3)]
2use crate::pac::adccommon::vals::Ckmode; 2use crate::pac::adccommon::vals::Ckmode;
3use crate::pac::flash::vals::Latency; 3use crate::pac::flash::vals::Latency;
4use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; 4pub use crate::pac::rcc::vals::Adcpres;
5use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
5use crate::pac::{FLASH, RCC}; 6use crate::pac::{FLASH, RCC};
6use crate::rcc::{set_freqs, Clocks}; 7use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz; 8use crate::time::Hertz;
@@ -12,25 +13,6 @@ pub const HSI_FREQ: Hertz = Hertz(8_000_000);
12/// LSI speed 13/// LSI speed
13pub const LSI_FREQ: Hertz = Hertz(40_000); 14pub const LSI_FREQ: Hertz = Hertz(40_000);
14 15
15impl From<AdcClockSource> for Adcpres {
16 fn from(value: AdcClockSource) -> Self {
17 match value {
18 AdcClockSource::PllDiv1 => Adcpres::DIV1,
19 AdcClockSource::PllDiv2 => Adcpres::DIV2,
20 AdcClockSource::PllDiv4 => Adcpres::DIV4,
21 AdcClockSource::PllDiv6 => Adcpres::DIV6,
22 AdcClockSource::PllDiv8 => Adcpres::DIV8,
23 AdcClockSource::PllDiv12 => Adcpres::DIV12,
24 AdcClockSource::PllDiv16 => Adcpres::DIV16,
25 AdcClockSource::PllDiv32 => Adcpres::DIV32,
26 AdcClockSource::PllDiv64 => Adcpres::DIV64,
27 AdcClockSource::PllDiv128 => Adcpres::DIV128,
28 AdcClockSource::PllDiv256 => Adcpres::DIV256,
29 _ => unreachable!(),
30 }
31 }
32}
33
34#[cfg(rcc_f3)] 16#[cfg(rcc_f3)]
35impl From<AdcClockSource> for Ckmode { 17impl From<AdcClockSource> for Ckmode {
36 fn from(value: AdcClockSource) -> Self { 18 fn from(value: AdcClockSource) -> Self {
@@ -45,32 +27,13 @@ impl From<AdcClockSource> for Ckmode {
45 27
46#[derive(Clone, Copy)] 28#[derive(Clone, Copy)]
47pub enum AdcClockSource { 29pub enum AdcClockSource {
48 PllDiv1 = 1, 30 Pll(Adcpres),
49 PllDiv2 = 2,
50 PllDiv4 = 4,
51 PllDiv6 = 6,
52 PllDiv8 = 8,
53 PllDiv12 = 12,
54 PllDiv16 = 16,
55 PllDiv32 = 32,
56 PllDiv64 = 64,
57 PllDiv128 = 128,
58 PllDiv256 = 256,
59 BusDiv1, 31 BusDiv1,
60 BusDiv2, 32 BusDiv2,
61 BusDiv4, 33 BusDiv4,
62} 34}
63 35
64impl AdcClockSource { 36impl AdcClockSource {
65 pub fn is_bus(&self) -> bool {
66 match self {
67 Self::BusDiv1 => true,
68 Self::BusDiv2 => true,
69 Self::BusDiv4 => true,
70 _ => false,
71 }
72 }
73
74 pub fn bus_div(&self) -> u32 { 37 pub fn bus_div(&self) -> u32 {
75 match self { 38 match self {
76 Self::BusDiv1 => 1, 39 Self::BusDiv1 => 1,
@@ -137,67 +100,67 @@ struct PllConfig {
137/// Initialize and Set the clock frequencies 100/// Initialize and Set the clock frequencies
138pub(crate) unsafe fn init(config: Config) { 101pub(crate) unsafe fn init(config: Config) {
139 // Calculate the real System clock, and PLL configuration if applicable 102 // Calculate the real System clock, and PLL configuration if applicable
140 let (Hertz(sysclk), pll_config) = get_sysclk(&config); 103 let (sysclk, pll_config) = get_sysclk(&config);
141 assert!(sysclk <= 72_000_000); 104 assert!(sysclk.0 <= 72_000_000);
142 105
143 // Calculate real AHB clock 106 // Calculate real AHB clock
144 let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk); 107 let hclk = config.hclk.map(|h| h).unwrap_or(sysclk);
145 let (hpre_bits, hpre_div) = match sysclk / hclk { 108 let hpre = match sysclk.0 / hclk.0 {
146 0 => unreachable!(), 109 0 => unreachable!(),
147 1 => (Hpre::DIV1, 1), 110 1 => Hpre::DIV1,
148 2 => (Hpre::DIV2, 2), 111 2 => Hpre::DIV2,
149 3..=5 => (Hpre::DIV4, 4), 112 3..=5 => Hpre::DIV4,
150 6..=11 => (Hpre::DIV8, 8), 113 6..=11 => Hpre::DIV8,
151 12..=39 => (Hpre::DIV16, 16), 114 12..=39 => Hpre::DIV16,
152 40..=95 => (Hpre::DIV64, 64), 115 40..=95 => Hpre::DIV64,
153 96..=191 => (Hpre::DIV128, 128), 116 96..=191 => Hpre::DIV128,
154 192..=383 => (Hpre::DIV256, 256), 117 192..=383 => Hpre::DIV256,
155 _ => (Hpre::DIV512, 512), 118 _ => Hpre::DIV512,
156 }; 119 };
157 let hclk = sysclk / hpre_div; 120 let hclk = sysclk / hpre;
158 assert!(hclk <= 72_000_000); 121 assert!(hclk <= Hertz(72_000_000));
159 122
160 // Calculate real APB1 clock 123 // Calculate real APB1 clock
161 let pclk1 = config.pclk1.map(|p| p.0).unwrap_or(hclk); 124 let pclk1 = config.pclk1.unwrap_or(hclk);
162 let (ppre1_bits, ppre1) = match hclk / pclk1 { 125 let ppre1 = match hclk / pclk1 {
163 0 => unreachable!(), 126 0 => unreachable!(),
164 1 => (Ppre::DIV1, 1), 127 1 => Ppre::DIV1,
165 2 => (Ppre::DIV2, 2), 128 2 => Ppre::DIV2,
166 3..=5 => (Ppre::DIV4, 4), 129 3..=5 => Ppre::DIV4,
167 6..=11 => (Ppre::DIV8, 8), 130 6..=11 => Ppre::DIV8,
168 _ => (Ppre::DIV16, 16), 131 _ => Ppre::DIV16,
169 }; 132 };
170 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; 133 let timer_mul1 = if ppre1 == Ppre::DIV1 { 1u32 } else { 2 };
171 let pclk1 = hclk / ppre1; 134 let pclk1 = hclk / ppre1;
172 assert!(pclk1 <= 36_000_000); 135 assert!(pclk1 <= Hertz(36_000_000));
173 136
174 // Calculate real APB2 clock 137 // Calculate real APB2 clock
175 let pclk2 = config.pclk2.map(|p| p.0).unwrap_or(hclk); 138 let pclk2 = config.pclk2.unwrap_or(hclk);
176 let (ppre2_bits, ppre2) = match hclk / pclk2 { 139 let ppre2 = match hclk / pclk2 {
177 0 => unreachable!(), 140 0 => unreachable!(),
178 1 => (Ppre::DIV1, 1), 141 1 => Ppre::DIV1,
179 2 => (Ppre::DIV2, 2), 142 2 => Ppre::DIV2,
180 3..=5 => (Ppre::DIV4, 4), 143 3..=5 => Ppre::DIV4,
181 6..=11 => (Ppre::DIV8, 8), 144 6..=11 => Ppre::DIV8,
182 _ => (Ppre::DIV16, 16), 145 _ => Ppre::DIV16,
183 }; 146 };
184 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; 147 let timer_mul2 = if ppre2 == Ppre::DIV1 { 1u32 } else { 2 };
185 let pclk2 = hclk / ppre2; 148 let pclk2 = hclk / ppre2;
186 assert!(pclk2 <= 72_000_000); 149 assert!(pclk2 <= Hertz(72_000_000));
187 150
188 // Set latency based on HCLK frquency 151 // Set latency based on HCLK frquency
189 // RM0316: "The prefetch buffer must be kept on when using a prescaler 152 // RM0316: "The prefetch buffer must be kept on when using a prescaler
190 // different from 1 on the AHB clock.", "Half-cycle access cannot be 153 // different from 1 on the AHB clock.", "Half-cycle access cannot be
191 // used when there is a prescaler different from 1 on the AHB clock" 154 // used when there is a prescaler different from 1 on the AHB clock"
192 FLASH.acr().modify(|w| { 155 FLASH.acr().modify(|w| {
193 w.set_latency(if hclk <= 24_000_000 { 156 w.set_latency(if hclk <= Hertz(24_000_000) {
194 Latency::WS0 157 Latency::WS0
195 } else if hclk <= 48_000_000 { 158 } else if hclk <= Hertz(48_000_000) {
196 Latency::WS1 159 Latency::WS1
197 } else { 160 } else {
198 Latency::WS2 161 Latency::WS2
199 }); 162 });
200 if hpre_div != 1 { 163 if hpre != Hpre::DIV1 {
201 w.set_hlfcya(false); 164 w.set_hlfcya(false);
202 w.set_prftbe(true); 165 w.set_prftbe(true);
203 } 166 }
@@ -240,9 +203,9 @@ pub(crate) unsafe fn init(config: Config) {
240 // Set prescalers 203 // Set prescalers
241 // CFGR has been written before (PLL, PLL48) don't overwrite these settings 204 // CFGR has been written before (PLL, PLL48) don't overwrite these settings
242 RCC.cfgr().modify(|w| { 205 RCC.cfgr().modify(|w| {
243 w.set_ppre2(ppre2_bits); 206 w.set_ppre2(ppre2);
244 w.set_ppre1(ppre1_bits); 207 w.set_ppre1(ppre1);
245 w.set_hpre(hpre_bits); 208 w.set_hpre(hpre);
246 }); 209 });
247 210
248 // Wait for the new prescalers to kick in 211 // Wait for the new prescalers to kick in
@@ -260,45 +223,43 @@ pub(crate) unsafe fn init(config: Config) {
260 }); 223 });
261 224
262 #[cfg(rcc_f3)] 225 #[cfg(rcc_f3)]
263 let adc = config.adc.map(|adc| { 226 let adc = config.adc.map(|adc| match adc {
264 if !adc.is_bus() { 227 AdcClockSource::Pll(adcpres) => {
265 RCC.cfgr2().modify(|w| { 228 RCC.cfgr2().modify(|w| {
266 // Make sure that we're using the PLL 229 // Make sure that we're using the PLL
267 pll_config.unwrap(); 230 pll_config.unwrap();
268 w.set_adc12pres(adc.into()); 231 w.set_adc12pres(adcpres);
269 232
270 Hertz(sysclk / adc as u32) 233 sysclk / adcpres
271 }) 234 })
272 } else { 235 }
273 crate::pac::ADC_COMMON.ccr().modify(|w| { 236 _ => crate::pac::ADC_COMMON.ccr().modify(|w| {
274 assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1)); 237 assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
275 238
276 w.set_ckmode(adc.into()); 239 w.set_ckmode(adc.into());
277 240
278 Hertz(sysclk / adc.bus_div() as u32) 241 sysclk / adc.bus_div()
279 }) 242 }),
280 }
281 }); 243 });
282 244
283 #[cfg(all(rcc_f3, adc3_common))] 245 #[cfg(all(rcc_f3, adc3_common))]
284 let adc34 = config.adc.map(|adc| { 246 let adc34 = config.adc34.map(|adc| match adc {
285 if !adc.is_bus() { 247 AdcClockSource::Pll(adcpres) => {
286 RCC.cfgr2().modify(|w| { 248 RCC.cfgr2().modify(|w| {
287 // Make sure that we're using the PLL 249 // Make sure that we're using the PLL
288 pll_config.unwrap(); 250 pll_config.unwrap();
289 w.set_adc12pres(adc.into()); 251 w.set_adc34pres(adcpres);
290 252
291 Hertz(sysclk / adc as u32) 253 sysclk / adcpres
292 }) 254 })
293 } else { 255 }
294 crate::pac::ADC3_COMMON.ccr().modify(|w| { 256 _ => crate::pac::ADC_COMMON.ccr().modify(|w| {
295 assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1)); 257 assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1));
296 258
297 w.set_ckmode(adc.into()); 259 w.set_ckmode(adc.into());
298 260
299 Hertz(sysclk / adc.bus_div() as u32) 261 sysclk / adc.bus_div()
300 }) 262 }),
301 }
302 }); 263 });
303 264
304 #[cfg(stm32f334)] 265 #[cfg(stm32f334)]
@@ -310,21 +271,21 @@ pub(crate) unsafe fn init(config: Config) {
310 271
311 // Make sure that we're using the PLL 272 // Make sure that we're using the PLL
312 pll_config.unwrap(); 273 pll_config.unwrap();
313 assert!((pclk2 == sysclk) || (pclk2 * 2 == sysclk)); 274 assert!((pclk2 == sysclk) || (pclk2 * 2u32 == sysclk));
314 275
315 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL)); 276 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL));
316 277
317 Some(Hertz(sysclk * 2)) 278 Some(sysclk * 2u32)
318 } 279 }
319 }; 280 };
320 281
321 set_freqs(Clocks { 282 set_freqs(Clocks {
322 sys: Hertz(sysclk), 283 sys: sysclk,
323 apb1: Hertz(pclk1), 284 apb1: pclk1,
324 apb2: Hertz(pclk2), 285 apb2: pclk2,
325 apb1_tim: Hertz(pclk1 * timer_mul1), 286 apb1_tim: pclk1 * timer_mul1,
326 apb2_tim: Hertz(pclk2 * timer_mul2), 287 apb2_tim: pclk2 * timer_mul2,
327 ahb1: Hertz(hclk), 288 ahb1: hclk,
328 #[cfg(rcc_f3)] 289 #[cfg(rcc_f3)]
329 adc: adc, 290 adc: adc,
330 #[cfg(all(rcc_f3, adc3_common))] 291 #[cfg(all(rcc_f3, adc3_common))]
@@ -421,16 +382,16 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
421 382
422#[inline] 383#[inline]
423#[allow(unused_variables)] 384#[allow(unused_variables)]
424fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre { 385fn get_usb_pre(config: &Config, sysclk: Hertz, pclk1: Hertz, pll_config: &Option<PllConfig>) -> Usbpre {
425 cfg_if::cfg_if! { 386 cfg_if::cfg_if! {
426 // Some chips do not have USB 387 // Some chips do not have USB
427 if #[cfg(any(stm32f301, stm32f318, stm32f334))] { 388 if #[cfg(any(stm32f301, stm32f318, stm32f334))] {
428 panic!("USB clock not supported by the chip"); 389 panic!("USB clock not supported by the chip");
429 } else { 390 } else {
430 let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000); 391 let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= Hertz(10_000_000));
431 match (usb_ok, sysclk) { 392 match (usb_ok, sysclk) {
432 (true, 72_000_000) => Usbpre::DIV1_5, 393 (true, Hertz(72_000_000)) => Usbpre::DIV1_5,
433 (true, 48_000_000) => Usbpre::DIV1, 394 (true, Hertz(48_000_000)) => Usbpre::DIV1,
434 _ => panic!( 395 _ => panic!(
435 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz" 396 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz"
436 ), 397 ),
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index 5ac409113..823836af7 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -1,6 +1,8 @@
1use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
2use crate::pac::rcc::vals::{self, Hsidiv, Sw}; 2use crate::pac::rcc::vals::{self, Sw};
3pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler}; 3pub use crate::pac::rcc::vals::{
4 Hpre as AHBPrescaler, Hsidiv as HSI16Prescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler,
5};
4use crate::pac::{FLASH, PWR, RCC}; 6use crate::pac::{FLASH, PWR, RCC};
5use crate::rcc::{set_freqs, Clocks}; 7use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 8use crate::time::Hertz;
@@ -20,33 +22,6 @@ pub enum ClockSrc {
20 LSI, 22 LSI,
21} 23}
22 24
23#[derive(Clone, Copy)]
24pub enum HSI16Prescaler {
25 NotDivided,
26 Div2,
27 Div4,
28 Div8,
29 Div16,
30 Div32,
31 Div64,
32 Div128,
33}
34
35impl Into<Hsidiv> for HSI16Prescaler {
36 fn into(self) -> Hsidiv {
37 match self {
38 HSI16Prescaler::NotDivided => Hsidiv::DIV1,
39 HSI16Prescaler::Div2 => Hsidiv::DIV2,
40 HSI16Prescaler::Div4 => Hsidiv::DIV4,
41 HSI16Prescaler::Div8 => Hsidiv::DIV8,
42 HSI16Prescaler::Div16 => Hsidiv::DIV16,
43 HSI16Prescaler::Div32 => Hsidiv::DIV32,
44 HSI16Prescaler::Div64 => Hsidiv::DIV64,
45 HSI16Prescaler::Div128 => Hsidiv::DIV128,
46 }
47 }
48}
49
50/// The PLL configuration. 25/// The PLL configuration.
51/// 26///
52/// * `VCOCLK = source / m * n` 27/// * `VCOCLK = source / m * n`
@@ -104,7 +79,7 @@ impl Default for Config {
104 #[inline] 79 #[inline]
105 fn default() -> Config { 80 fn default() -> Config {
106 Config { 81 Config {
107 mux: ClockSrc::HSI16(HSI16Prescaler::NotDivided), 82 mux: ClockSrc::HSI16(HSI16Prescaler::DIV1),
108 ahb_pre: AHBPrescaler::DIV1, 83 ahb_pre: AHBPrescaler::DIV1,
109 apb_pre: APBPrescaler::DIV1, 84 apb_pre: APBPrescaler::DIV1,
110 low_power_run: false, 85 low_power_run: false,
@@ -195,7 +170,6 @@ pub(crate) unsafe fn init(config: Config) {
195 let (sys_clk, sw) = match config.mux { 170 let (sys_clk, sw) = match config.mux {
196 ClockSrc::HSI16(div) => { 171 ClockSrc::HSI16(div) => {
197 // Enable HSI16 172 // Enable HSI16
198 let div: Hsidiv = div.into();
199 RCC.cr().write(|w| { 173 RCC.cr().write(|w| {
200 w.set_hsidiv(div); 174 w.set_hsidiv(div);
201 w.set_hsion(true) 175 w.set_hsion(true)
@@ -262,7 +236,7 @@ pub(crate) unsafe fn init(config: Config) {
262 } 236 }
263 237
264 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once 238 // Configure SYSCLK source, HCLK divisor, and PCLK divisor all at once
265 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre.into(), config.apb_pre.into()); 239 let (sw, hpre, ppre) = (sw.into(), config.ahb_pre, config.apb_pre);
266 RCC.cfgr().modify(|w| { 240 RCC.cfgr().modify(|w| {
267 w.set_sw(sw); 241 w.set_sw(sw);
268 w.set_hpre(hpre); 242 w.set_hpre(hpre);
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index 08ccc5fe9..43256524d 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -3,7 +3,8 @@ use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
3use stm32_metapac::FLASH; 3use stm32_metapac::FLASH;
4 4
5pub use crate::pac::rcc::vals::{ 5pub use crate::pac::rcc::vals::{
6 Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler, 6 Adcsel as AdcClockSource, Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ,
7 Pllr as PllR, Ppre as APBPrescaler,
7}; 8};
8use crate::pac::{PWR, RCC}; 9use crate::pac::{PWR, RCC};
9use crate::rcc::sealed::RccPeripheral; 10use crate::rcc::sealed::RccPeripheral;
@@ -16,29 +17,6 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000);
16/// LSI speed 17/// LSI speed
17pub const LSI_FREQ: Hertz = Hertz(32_000); 18pub const LSI_FREQ: Hertz = Hertz(32_000);
18 19
19#[derive(Clone, Copy)]
20pub enum AdcClockSource {
21 NoClk,
22 SysClk,
23 PllP,
24}
25
26impl AdcClockSource {
27 pub fn adcsel(&self) -> Adcsel {
28 match self {
29 AdcClockSource::NoClk => Adcsel::NOCLK,
30 AdcClockSource::SysClk => Adcsel::SYSCLK,
31 AdcClockSource::PllP => Adcsel::PLLP,
32 }
33 }
34}
35
36impl Default for AdcClockSource {
37 fn default() -> Self {
38 Self::NoClk
39 }
40}
41
42/// System clock mux source 20/// System clock mux source
43#[derive(Clone, Copy)] 21#[derive(Clone, Copy)]
44pub enum ClockSrc { 22pub enum ClockSrc {
@@ -88,32 +66,6 @@ pub struct Pll {
88 pub div_r: Option<PllR>, 66 pub div_r: Option<PllR>,
89} 67}
90 68
91fn ahb_div(ahb: AHBPrescaler) -> u32 {
92 match ahb {
93 AHBPrescaler::DIV1 => 1,
94 AHBPrescaler::DIV2 => 2,
95 AHBPrescaler::DIV4 => 4,
96 AHBPrescaler::DIV8 => 8,
97 AHBPrescaler::DIV16 => 16,
98 AHBPrescaler::DIV64 => 64,
99 AHBPrescaler::DIV128 => 128,
100 AHBPrescaler::DIV256 => 256,
101 AHBPrescaler::DIV512 => 512,
102 _ => unreachable!(),
103 }
104}
105
106fn apb_div(apb: APBPrescaler) -> u32 {
107 match apb {
108 APBPrescaler::DIV1 => 1,
109 APBPrescaler::DIV2 => 2,
110 APBPrescaler::DIV4 => 4,
111 APBPrescaler::DIV8 => 8,
112 APBPrescaler::DIV16 => 16,
113 _ => unreachable!(),
114 }
115}
116
117/// Sets the source for the 48MHz clock to the USB and RNG peripherals. 69/// Sets the source for the 48MHz clock to the USB and RNG peripherals.
118pub enum Clock48MhzSrc { 70pub enum Clock48MhzSrc {
119 /// Use the High Speed Internal Oscillator. For USB usage, the CRS must be used to calibrate the 71 /// Use the High Speed Internal Oscillator. For USB usage, the CRS must be used to calibrate the
@@ -168,8 +120,8 @@ impl Default for Config {
168 low_power_run: false, 120 low_power_run: false,
169 pll: None, 121 pll: None,
170 clock_48mhz_src: None, 122 clock_48mhz_src: None,
171 adc12_clock_source: Default::default(), 123 adc12_clock_source: Adcsel::NOCLK,
172 adc345_clock_source: Default::default(), 124 adc345_clock_source: Adcsel::NOCLK,
173 } 125 }
174 } 126 }
175} 127}
@@ -203,8 +155,8 @@ pub(crate) unsafe fn init(config: Config) {
203 let internal_freq = src_freq / pll_config.prediv_m * pll_config.mul_n; 155 let internal_freq = src_freq / pll_config.prediv_m * pll_config.mul_n;
204 156
205 RCC.pllcfgr().write(|w| { 157 RCC.pllcfgr().write(|w| {
206 w.set_plln(pll_config.mul_n.into()); 158 w.set_plln(pll_config.mul_n);
207 w.set_pllm(pll_config.prediv_m.into()); 159 w.set_pllm(pll_config.prediv_m);
208 w.set_pllsrc(pll_config.source.into()); 160 w.set_pllsrc(pll_config.source.into());
209 }); 161 });
210 162
@@ -249,14 +201,14 @@ pub(crate) unsafe fn init(config: Config) {
249 RCC.cr().write(|w| w.set_hsion(true)); 201 RCC.cr().write(|w| w.set_hsion(true));
250 while !RCC.cr().read().hsirdy() {} 202 while !RCC.cr().read().hsirdy() {}
251 203
252 (HSI_FREQ.0, Sw::HSI16) 204 (HSI_FREQ, Sw::HSI16)
253 } 205 }
254 ClockSrc::HSE(freq) => { 206 ClockSrc::HSE(freq) => {
255 // Enable HSE 207 // Enable HSE
256 RCC.cr().write(|w| w.set_hseon(true)); 208 RCC.cr().write(|w| w.set_hseon(true));
257 while !RCC.cr().read().hserdy() {} 209 while !RCC.cr().read().hserdy() {}
258 210
259 (freq.0, Sw::HSE) 211 (freq, Sw::HSE)
260 } 212 }
261 ClockSrc::PLL => { 213 ClockSrc::PLL => {
262 assert!(pll_freq.is_some()); 214 assert!(pll_freq.is_some());
@@ -297,35 +249,32 @@ pub(crate) unsafe fn init(config: Config) {
297 } 249 }
298 } 250 }
299 251
300 (freq, Sw::PLLRCLK) 252 (Hertz(freq), Sw::PLLRCLK)
301 } 253 }
302 }; 254 };
303 255
304 RCC.cfgr().modify(|w| { 256 RCC.cfgr().modify(|w| {
305 w.set_sw(sw); 257 w.set_sw(sw);
306 w.set_hpre(config.ahb_pre.into()); 258 w.set_hpre(config.ahb_pre);
307 w.set_ppre1(config.apb1_pre.into()); 259 w.set_ppre1(config.apb1_pre);
308 w.set_ppre2(config.apb2_pre.into()); 260 w.set_ppre2(config.apb2_pre);
309 }); 261 });
310 262
311 let ahb_freq: u32 = match config.ahb_pre { 263 let ahb_freq = sys_clk / config.ahb_pre;
312 AHBPrescaler::DIV1 => sys_clk,
313 pre => sys_clk / ahb_div(pre),
314 };
315 264
316 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 265 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
317 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 266 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
318 pre => { 267 pre => {
319 let freq = ahb_freq / apb_div(pre); 268 let freq = ahb_freq / pre;
320 (freq, freq * 2) 269 (freq, freq * 2u32)
321 } 270 }
322 }; 271 };
323 272
324 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 273 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
325 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 274 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
326 pre => { 275 pre => {
327 let freq = ahb_freq / apb_div(pre); 276 let freq = ahb_freq / pre;
328 (freq, freq * 2) 277 (freq, freq * 2u32)
329 } 278 }
330 }; 279 };
331 280
@@ -373,42 +322,36 @@ pub(crate) unsafe fn init(config: Config) {
373 RCC.ccipr().modify(|w| w.set_clk48sel(source)); 322 RCC.ccipr().modify(|w| w.set_clk48sel(source));
374 } 323 }
375 324
376 RCC.ccipr() 325 RCC.ccipr().modify(|w| w.set_adc12sel(config.adc12_clock_source));
377 .modify(|w| w.set_adc12sel(config.adc12_clock_source.adcsel())); 326 RCC.ccipr().modify(|w| w.set_adc345sel(config.adc345_clock_source));
378 RCC.ccipr()
379 .modify(|w| w.set_adc345sel(config.adc345_clock_source.adcsel()));
380 327
381 let adc12_ck = match config.adc12_clock_source { 328 let adc12_ck = match config.adc12_clock_source {
382 AdcClockSource::NoClk => None, 329 AdcClockSource::NOCLK => None,
383 AdcClockSource::PllP => match &pll_freq { 330 AdcClockSource::PLLP => pll_freq.as_ref().unwrap().pll_p,
384 Some(pll) => pll.pll_p, 331 AdcClockSource::SYSCLK => Some(sys_clk),
385 None => None, 332 _ => unreachable!(),
386 },
387 AdcClockSource::SysClk => Some(Hertz(sys_clk)),
388 }; 333 };
389 334
390 let adc345_ck = match config.adc345_clock_source { 335 let adc345_ck = match config.adc345_clock_source {
391 AdcClockSource::NoClk => None, 336 AdcClockSource::NOCLK => None,
392 AdcClockSource::PllP => match &pll_freq { 337 AdcClockSource::PLLP => pll_freq.as_ref().unwrap().pll_p,
393 Some(pll) => pll.pll_p, 338 AdcClockSource::SYSCLK => Some(sys_clk),
394 None => None, 339 _ => unreachable!(),
395 },
396 AdcClockSource::SysClk => Some(Hertz(sys_clk)),
397 }; 340 };
398 341
399 if config.low_power_run { 342 if config.low_power_run {
400 assert!(sys_clk <= 2_000_000); 343 assert!(sys_clk <= Hertz(2_000_000));
401 PWR.cr1().modify(|w| w.set_lpr(true)); 344 PWR.cr1().modify(|w| w.set_lpr(true));
402 } 345 }
403 346
404 set_freqs(Clocks { 347 set_freqs(Clocks {
405 sys: Hertz(sys_clk), 348 sys: sys_clk,
406 ahb1: Hertz(ahb_freq), 349 ahb1: ahb_freq,
407 ahb2: Hertz(ahb_freq), 350 ahb2: ahb_freq,
408 apb1: Hertz(apb1_freq), 351 apb1: apb1_freq,
409 apb1_tim: Hertz(apb1_tim_freq), 352 apb1_tim: apb1_tim_freq,
410 apb2: Hertz(apb2_freq), 353 apb2: apb2_freq,
411 apb2_tim: Hertz(apb2_tim_freq), 354 apb2_tim: apb2_tim_freq,
412 adc: adc12_ck, 355 adc: adc12_ck,
413 adc34: adc345_ck, 356 adc34: adc345_ck,
414 }); 357 });
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index a11fd4737..d29064996 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -26,13 +26,13 @@ pub const HSI48_FREQ: Hertz = Hertz(48_000_000);
26/// LSI speed 26/// LSI speed
27pub const LSI_FREQ: Hertz = Hertz(32_000); 27pub const LSI_FREQ: Hertz = Hertz(32_000);
28 28
29const VCO_RANGE: RangeInclusive<u32> = 150_000_000..=420_000_000; 29const VCO_RANGE: RangeInclusive<Hertz> = Hertz(150_000_000)..=Hertz(420_000_000);
30#[cfg(any(stm32h5, pwr_h7rm0455))] 30#[cfg(any(stm32h5, pwr_h7rm0455))]
31const VCO_WIDE_RANGE: RangeInclusive<u32> = 128_000_000..=560_000_000; 31const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(128_000_000)..=Hertz(560_000_000);
32#[cfg(pwr_h7rm0468)] 32#[cfg(pwr_h7rm0468)]
33const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=836_000_000; 33const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(836_000_000);
34#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))] 34#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))]
35const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=960_000_000; 35const VCO_WIDE_RANGE: RangeInclusive<Hertz> = Hertz(192_000_000)..=Hertz(960_000_000);
36 36
37pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 37pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
38 38
@@ -641,9 +641,9 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
641 let wide_allowed = ref_range != Pllrge::RANGE1; 641 let wide_allowed = ref_range != Pllrge::RANGE1;
642 642
643 let vco_clk = ref_clk * config.mul; 643 let vco_clk = ref_clk * config.mul;
644 let vco_range = if VCO_RANGE.contains(&vco_clk.0) { 644 let vco_range = if VCO_RANGE.contains(&vco_clk) {
645 Pllvcosel::MEDIUMVCO 645 Pllvcosel::MEDIUMVCO
646 } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk.0) { 646 } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk) {
647 Pllvcosel::WIDEVCO 647 Pllvcosel::WIDEVCO
648 } else { 648 } else {
649 panic!("pll vco_clk out of range: {} mhz", vco_clk.0) 649 panic!("pll vco_clk out of range: {} mhz", vco_clk.0)
diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs
index b42361268..3fd8074d7 100644
--- a/embassy-stm32/src/rcc/l0.rs
+++ b/embassy-stm32/src/rcc/l0.rs
@@ -1,8 +1,10 @@
1use super::bd::BackupDomain; 1use super::bd::BackupDomain;
2use super::RtcClockSource; 2use super::RtcClockSource;
3pub use crate::pac::pwr::vals::Vos as VoltageScale; 3pub use crate::pac::pwr::vals::Vos as VoltageScale;
4use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; 4pub use crate::pac::rcc::vals::{
5pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 5 Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler,
6};
7use crate::pac::rcc::vals::{Pllsrc, Sw};
6#[cfg(crs)] 8#[cfg(crs)]
7use crate::pac::{crs, CRS, SYSCFG}; 9use crate::pac::{crs, CRS, SYSCFG};
8use crate::pac::{FLASH, PWR, RCC}; 10use crate::pac::{FLASH, PWR, RCC};
@@ -24,56 +26,6 @@ pub enum ClockSrc {
24 HSI16, 26 HSI16,
25} 27}
26 28
27/// MSI Clock Range
28///
29/// These ranges control the frequency of the MSI. Internally, these ranges map
30/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
31#[derive(Clone, Copy)]
32pub enum MSIRange {
33 /// Around 65.536 kHz
34 Range0,
35 /// Around 131.072 kHz
36 Range1,
37 /// Around 262.144 kHz
38 Range2,
39 /// Around 524.288 kHz
40 Range3,
41 /// Around 1.048 MHz
42 Range4,
43 /// Around 2.097 MHz (reset value)
44 Range5,
45 /// Around 4.194 MHz
46 Range6,
47}
48
49impl Default for MSIRange {
50 fn default() -> MSIRange {
51 MSIRange::Range5
52 }
53}
54
55/// PLL divider
56#[derive(Clone, Copy)]
57pub enum PLLDiv {
58 Div2,
59 Div3,
60 Div4,
61}
62
63/// PLL multiplier
64#[derive(Clone, Copy)]
65pub enum PLLMul {
66 Mul3,
67 Mul4,
68 Mul6,
69 Mul8,
70 Mul12,
71 Mul16,
72 Mul24,
73 Mul32,
74 Mul48,
75}
76
77/// PLL clock input source 29/// PLL clock input source
78#[derive(Clone, Copy)] 30#[derive(Clone, Copy)]
79pub enum PLLSource { 31pub enum PLLSource {
@@ -81,32 +33,6 @@ pub enum PLLSource {
81 HSE(Hertz), 33 HSE(Hertz),
82} 34}
83 35
84impl From<PLLMul> for Pllmul {
85 fn from(val: PLLMul) -> Pllmul {
86 match val {
87 PLLMul::Mul3 => Pllmul::MUL3,
88 PLLMul::Mul4 => Pllmul::MUL4,
89 PLLMul::Mul6 => Pllmul::MUL6,
90 PLLMul::Mul8 => Pllmul::MUL8,
91 PLLMul::Mul12 => Pllmul::MUL12,
92 PLLMul::Mul16 => Pllmul::MUL16,
93 PLLMul::Mul24 => Pllmul::MUL24,
94 PLLMul::Mul32 => Pllmul::MUL32,
95 PLLMul::Mul48 => Pllmul::MUL48,
96 }
97 }
98}
99
100impl From<PLLDiv> for Plldiv {
101 fn from(val: PLLDiv) -> Plldiv {
102 match val {
103 PLLDiv::Div2 => Plldiv::DIV2,
104 PLLDiv::Div3 => Plldiv::DIV3,
105 PLLDiv::Div4 => Plldiv::DIV4,
106 }
107 }
108}
109
110impl From<PLLSource> for Pllsrc { 36impl From<PLLSource> for Pllsrc {
111 fn from(val: PLLSource) -> Pllsrc { 37 fn from(val: PLLSource) -> Pllsrc {
112 match val { 38 match val {
@@ -116,20 +42,6 @@ impl From<PLLSource> for Pllsrc {
116 } 42 }
117} 43}
118 44
119impl From<MSIRange> for Msirange {
120 fn from(val: MSIRange) -> Msirange {
121 match val {
122 MSIRange::Range0 => Msirange::RANGE0,
123 MSIRange::Range1 => Msirange::RANGE1,
124 MSIRange::Range2 => Msirange::RANGE2,
125 MSIRange::Range3 => Msirange::RANGE3,
126 MSIRange::Range4 => Msirange::RANGE4,
127 MSIRange::Range5 => Msirange::RANGE5,
128 MSIRange::Range6 => Msirange::RANGE6,
129 }
130 }
131}
132
133/// Clocks configutation 45/// Clocks configutation
134pub struct Config { 46pub struct Config {
135 pub mux: ClockSrc, 47 pub mux: ClockSrc,
@@ -148,7 +60,7 @@ impl Default for Config {
148 #[inline] 60 #[inline]
149 fn default() -> Config { 61 fn default() -> Config {
150 Config { 62 Config {
151 mux: ClockSrc::MSI(MSIRange::default()), 63 mux: ClockSrc::MSI(MSIRange::RANGE5),
152 ahb_pre: AHBPrescaler::DIV1, 64 ahb_pre: AHBPrescaler::DIV1,
153 apb1_pre: APBPrescaler::DIV1, 65 apb1_pre: APBPrescaler::DIV1,
154 apb2_pre: APBPrescaler::DIV1, 66 apb2_pre: APBPrescaler::DIV1,
@@ -171,28 +83,28 @@ pub(crate) unsafe fn init(config: Config) {
171 let (sys_clk, sw) = match config.mux { 83 let (sys_clk, sw) = match config.mux {
172 ClockSrc::MSI(range) => { 84 ClockSrc::MSI(range) => {
173 // Set MSI range 85 // Set MSI range
174 RCC.icscr().write(|w| w.set_msirange(range.into())); 86 RCC.icscr().write(|w| w.set_msirange(range));
175 87
176 // Enable MSI 88 // Enable MSI
177 RCC.cr().write(|w| w.set_msion(true)); 89 RCC.cr().write(|w| w.set_msion(true));
178 while !RCC.cr().read().msirdy() {} 90 while !RCC.cr().read().msirdy() {}
179 91
180 let freq = 32_768 * (1 << (range as u8 + 1)); 92 let freq = 32_768 * (1 << (range as u8 + 1));
181 (freq, Sw::MSI) 93 (Hertz(freq), Sw::MSI)
182 } 94 }
183 ClockSrc::HSI16 => { 95 ClockSrc::HSI16 => {
184 // Enable HSI16 96 // Enable HSI16
185 RCC.cr().write(|w| w.set_hsi16on(true)); 97 RCC.cr().write(|w| w.set_hsi16on(true));
186 while !RCC.cr().read().hsi16rdyf() {} 98 while !RCC.cr().read().hsi16rdyf() {}
187 99
188 (HSI_FREQ.0, Sw::HSI16) 100 (HSI_FREQ, Sw::HSI16)
189 } 101 }
190 ClockSrc::HSE(freq) => { 102 ClockSrc::HSE(freq) => {
191 // Enable HSE 103 // Enable HSE
192 RCC.cr().write(|w| w.set_hseon(true)); 104 RCC.cr().write(|w| w.set_hseon(true));
193 while !RCC.cr().read().hserdy() {} 105 while !RCC.cr().read().hserdy() {}
194 106
195 (freq.0, Sw::HSE) 107 (freq, Sw::HSE)
196 } 108 }
197 ClockSrc::PLL(src, mul, div) => { 109 ClockSrc::PLL(src, mul, div) => {
198 let freq = match src { 110 let freq = match src {
@@ -200,13 +112,13 @@ pub(crate) unsafe fn init(config: Config) {
200 // Enable HSE 112 // Enable HSE
201 RCC.cr().write(|w| w.set_hseon(true)); 113 RCC.cr().write(|w| w.set_hseon(true));
202 while !RCC.cr().read().hserdy() {} 114 while !RCC.cr().read().hserdy() {}
203 freq.0 115 freq
204 } 116 }
205 PLLSource::HSI16 => { 117 PLLSource::HSI16 => {
206 // Enable HSI 118 // Enable HSI
207 RCC.cr().write(|w| w.set_hsi16on(true)); 119 RCC.cr().write(|w| w.set_hsi16on(true));
208 while !RCC.cr().read().hsi16rdyf() {} 120 while !RCC.cr().read().hsi16rdyf() {}
209 HSI_FREQ.0 121 HSI_FREQ
210 } 122 }
211 }; 123 };
212 124
@@ -214,28 +126,13 @@ pub(crate) unsafe fn init(config: Config) {
214 RCC.cr().modify(|w| w.set_pllon(false)); 126 RCC.cr().modify(|w| w.set_pllon(false));
215 while RCC.cr().read().pllrdy() {} 127 while RCC.cr().read().pllrdy() {}
216 128
217 let freq = match mul { 129 let freq = freq * mul / div;
218 PLLMul::Mul3 => freq * 3,
219 PLLMul::Mul4 => freq * 4,
220 PLLMul::Mul6 => freq * 6,
221 PLLMul::Mul8 => freq * 8,
222 PLLMul::Mul12 => freq * 12,
223 PLLMul::Mul16 => freq * 16,
224 PLLMul::Mul24 => freq * 24,
225 PLLMul::Mul32 => freq * 32,
226 PLLMul::Mul48 => freq * 48,
227 };
228 130
229 let freq = match div { 131 assert!(freq <= Hertz(32_000_000));
230 PLLDiv::Div2 => freq / 2,
231 PLLDiv::Div3 => freq / 3,
232 PLLDiv::Div4 => freq / 4,
233 };
234 assert!(freq <= 32_000_000);
235 132
236 RCC.cfgr().write(move |w| { 133 RCC.cfgr().write(move |w| {
237 w.set_pllmul(mul.into()); 134 w.set_pllmul(mul);
238 w.set_plldiv(div.into()); 135 w.set_plldiv(div);
239 w.set_pllsrc(src.into()); 136 w.set_pllsrc(src.into());
240 }); 137 });
241 138
@@ -254,11 +151,11 @@ pub(crate) unsafe fn init(config: Config) {
254 ); 151 );
255 152
256 let wait_states = match config.voltage_scale { 153 let wait_states = match config.voltage_scale {
257 VoltageScale::RANGE1 => match sys_clk { 154 VoltageScale::RANGE1 => match sys_clk.0 {
258 ..=16_000_000 => 0, 155 ..=16_000_000 => 0,
259 _ => 1, 156 _ => 1,
260 }, 157 },
261 VoltageScale::RANGE2 => match sys_clk { 158 VoltageScale::RANGE2 => match sys_clk.0 {
262 ..=8_000_000 => 0, 159 ..=8_000_000 => 0,
263 _ => 1, 160 _ => 1,
264 }, 161 },
@@ -271,37 +168,26 @@ pub(crate) unsafe fn init(config: Config) {
271 168
272 RCC.cfgr().modify(|w| { 169 RCC.cfgr().modify(|w| {
273 w.set_sw(sw); 170 w.set_sw(sw);
274 w.set_hpre(config.ahb_pre.into()); 171 w.set_hpre(config.ahb_pre);
275 w.set_ppre1(config.apb1_pre.into()); 172 w.set_ppre1(config.apb1_pre);
276 w.set_ppre2(config.apb2_pre.into()); 173 w.set_ppre2(config.apb2_pre);
277 }); 174 });
278 175
279 let ahb_freq: u32 = match config.ahb_pre { 176 let ahb_freq = sys_clk / config.ahb_pre;
280 AHBPrescaler::DIV1 => sys_clk,
281 pre => {
282 let pre: Hpre = pre.into();
283 let pre = 1 << (pre.to_bits() as u32 - 7);
284 sys_clk / pre
285 }
286 };
287 177
288 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 178 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
289 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 179 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
290 pre => { 180 pre => {
291 let pre: Ppre = pre.into(); 181 let freq = ahb_freq / pre;
292 let pre: u8 = 1 << (pre.to_bits() - 3); 182 (freq, freq * 2u32)
293 let freq = ahb_freq / pre as u32;
294 (freq, freq * 2)
295 } 183 }
296 }; 184 };
297 185
298 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 186 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
299 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 187 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
300 pre => { 188 pre => {
301 let pre: Ppre = pre.into(); 189 let freq = ahb_freq / pre;
302 let pre: u8 = 1 << (pre.to_bits() - 3); 190 (freq, freq * 2u32)
303 let freq = ahb_freq / pre as u32;
304 (freq, freq * 2)
305 } 191 }
306 }; 192 };
307 193
@@ -339,11 +225,11 @@ pub(crate) unsafe fn init(config: Config) {
339 } 225 }
340 226
341 set_freqs(Clocks { 227 set_freqs(Clocks {
342 sys: Hertz(sys_clk), 228 sys: sys_clk,
343 ahb1: Hertz(ahb_freq), 229 ahb1: ahb_freq,
344 apb1: Hertz(apb1_freq), 230 apb1: apb1_freq,
345 apb2: Hertz(apb2_freq), 231 apb2: apb2_freq,
346 apb1_tim: Hertz(apb1_tim_freq), 232 apb1_tim: apb1_tim_freq,
347 apb2_tim: Hertz(apb2_tim_freq), 233 apb2_tim: apb2_tim_freq,
348 }); 234 });
349} 235}
diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs
index e445a716e..7c75b888d 100644
--- a/embassy-stm32/src/rcc/l1.rs
+++ b/embassy-stm32/src/rcc/l1.rs
@@ -1,5 +1,7 @@
1use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; 1pub use crate::pac::rcc::vals::{
2pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 2 Hpre as AHBPrescaler, Msirange as MSIRange, Plldiv as PLLDiv, Pllmul as PLLMul, Ppre as APBPrescaler,
3};
4use crate::pac::rcc::vals::{Pllsrc, Sw};
3use crate::pac::{FLASH, RCC}; 5use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks}; 6use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz; 7use crate::time::Hertz;
@@ -19,56 +21,6 @@ pub enum ClockSrc {
19 HSI, 21 HSI,
20} 22}
21 23
22/// MSI Clock Range
23///
24/// These ranges control the frequency of the MSI. Internally, these ranges map
25/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
26#[derive(Clone, Copy)]
27pub enum MSIRange {
28 /// Around 65.536 kHz
29 Range0,
30 /// Around 131.072 kHz
31 Range1,
32 /// Around 262.144 kHz
33 Range2,
34 /// Around 524.288 kHz
35 Range3,
36 /// Around 1.048 MHz
37 Range4,
38 /// Around 2.097 MHz (reset value)
39 Range5,
40 /// Around 4.194 MHz
41 Range6,
42}
43
44impl Default for MSIRange {
45 fn default() -> MSIRange {
46 MSIRange::Range5
47 }
48}
49
50/// PLL divider
51#[derive(Clone, Copy)]
52pub enum PLLDiv {
53 Div2,
54 Div3,
55 Div4,
56}
57
58/// PLL multiplier
59#[derive(Clone, Copy)]
60pub enum PLLMul {
61 Mul3,
62 Mul4,
63 Mul6,
64 Mul8,
65 Mul12,
66 Mul16,
67 Mul24,
68 Mul32,
69 Mul48,
70}
71
72/// PLL clock input source 24/// PLL clock input source
73#[derive(Clone, Copy)] 25#[derive(Clone, Copy)]
74pub enum PLLSource { 26pub enum PLLSource {
@@ -76,32 +28,6 @@ pub enum PLLSource {
76 HSE(Hertz), 28 HSE(Hertz),
77} 29}
78 30
79impl From<PLLMul> for Pllmul {
80 fn from(val: PLLMul) -> Pllmul {
81 match val {
82 PLLMul::Mul3 => Pllmul::MUL3,
83 PLLMul::Mul4 => Pllmul::MUL4,
84 PLLMul::Mul6 => Pllmul::MUL6,
85 PLLMul::Mul8 => Pllmul::MUL8,
86 PLLMul::Mul12 => Pllmul::MUL12,
87 PLLMul::Mul16 => Pllmul::MUL16,
88 PLLMul::Mul24 => Pllmul::MUL24,
89 PLLMul::Mul32 => Pllmul::MUL32,
90 PLLMul::Mul48 => Pllmul::MUL48,
91 }
92 }
93}
94
95impl From<PLLDiv> for Plldiv {
96 fn from(val: PLLDiv) -> Plldiv {
97 match val {
98 PLLDiv::Div2 => Plldiv::DIV2,
99 PLLDiv::Div3 => Plldiv::DIV3,
100 PLLDiv::Div4 => Plldiv::DIV4,
101 }
102 }
103}
104
105impl From<PLLSource> for Pllsrc { 31impl From<PLLSource> for Pllsrc {
106 fn from(val: PLLSource) -> Pllsrc { 32 fn from(val: PLLSource) -> Pllsrc {
107 match val { 33 match val {
@@ -111,20 +37,6 @@ impl From<PLLSource> for Pllsrc {
111 } 37 }
112} 38}
113 39
114impl From<MSIRange> for Msirange {
115 fn from(val: MSIRange) -> Msirange {
116 match val {
117 MSIRange::Range0 => Msirange::RANGE0,
118 MSIRange::Range1 => Msirange::RANGE1,
119 MSIRange::Range2 => Msirange::RANGE2,
120 MSIRange::Range3 => Msirange::RANGE3,
121 MSIRange::Range4 => Msirange::RANGE4,
122 MSIRange::Range5 => Msirange::RANGE5,
123 MSIRange::Range6 => Msirange::RANGE6,
124 }
125 }
126}
127
128/// Clocks configutation 40/// Clocks configutation
129pub struct Config { 41pub struct Config {
130 pub mux: ClockSrc, 42 pub mux: ClockSrc,
@@ -137,7 +49,7 @@ impl Default for Config {
137 #[inline] 49 #[inline]
138 fn default() -> Config { 50 fn default() -> Config {
139 Config { 51 Config {
140 mux: ClockSrc::MSI(MSIRange::default()), 52 mux: ClockSrc::MSI(MSIRange::RANGE5),
141 ahb_pre: AHBPrescaler::DIV1, 53 ahb_pre: AHBPrescaler::DIV1,
142 apb1_pre: APBPrescaler::DIV1, 54 apb1_pre: APBPrescaler::DIV1,
143 apb2_pre: APBPrescaler::DIV1, 55 apb2_pre: APBPrescaler::DIV1,
@@ -149,28 +61,28 @@ pub(crate) unsafe fn init(config: Config) {
149 let (sys_clk, sw) = match config.mux { 61 let (sys_clk, sw) = match config.mux {
150 ClockSrc::MSI(range) => { 62 ClockSrc::MSI(range) => {
151 // Set MSI range 63 // Set MSI range
152 RCC.icscr().write(|w| w.set_msirange(range.into())); 64 RCC.icscr().write(|w| w.set_msirange(range));
153 65
154 // Enable MSI 66 // Enable MSI
155 RCC.cr().write(|w| w.set_msion(true)); 67 RCC.cr().write(|w| w.set_msion(true));
156 while !RCC.cr().read().msirdy() {} 68 while !RCC.cr().read().msirdy() {}
157 69
158 let freq = 32_768 * (1 << (range as u8 + 1)); 70 let freq = 32_768 * (1 << (range as u8 + 1));
159 (freq, Sw::MSI) 71 (Hertz(freq), Sw::MSI)
160 } 72 }
161 ClockSrc::HSI => { 73 ClockSrc::HSI => {
162 // Enable HSI 74 // Enable HSI
163 RCC.cr().write(|w| w.set_hsion(true)); 75 RCC.cr().write(|w| w.set_hsion(true));
164 while !RCC.cr().read().hsirdy() {} 76 while !RCC.cr().read().hsirdy() {}
165 77
166 (HSI_FREQ.0, Sw::HSI) 78 (HSI_FREQ, Sw::HSI)
167 } 79 }
168 ClockSrc::HSE(freq) => { 80 ClockSrc::HSE(freq) => {
169 // Enable HSE 81 // Enable HSE
170 RCC.cr().write(|w| w.set_hseon(true)); 82 RCC.cr().write(|w| w.set_hseon(true));
171 while !RCC.cr().read().hserdy() {} 83 while !RCC.cr().read().hserdy() {}
172 84
173 (freq.0, Sw::HSE) 85 (freq, Sw::HSE)
174 } 86 }
175 ClockSrc::PLL(src, mul, div) => { 87 ClockSrc::PLL(src, mul, div) => {
176 let freq = match src { 88 let freq = match src {
@@ -178,13 +90,13 @@ pub(crate) unsafe fn init(config: Config) {
178 // Enable HSE 90 // Enable HSE
179 RCC.cr().write(|w| w.set_hseon(true)); 91 RCC.cr().write(|w| w.set_hseon(true));
180 while !RCC.cr().read().hserdy() {} 92 while !RCC.cr().read().hserdy() {}
181 freq.0 93 freq
182 } 94 }
183 PLLSource::HSI => { 95 PLLSource::HSI => {
184 // Enable HSI 96 // Enable HSI
185 RCC.cr().write(|w| w.set_hsion(true)); 97 RCC.cr().write(|w| w.set_hsion(true));
186 while !RCC.cr().read().hsirdy() {} 98 while !RCC.cr().read().hsirdy() {}
187 HSI_FREQ.0 99 HSI_FREQ
188 } 100 }
189 }; 101 };
190 102
@@ -192,28 +104,13 @@ pub(crate) unsafe fn init(config: Config) {
192 RCC.cr().modify(|w| w.set_pllon(false)); 104 RCC.cr().modify(|w| w.set_pllon(false));
193 while RCC.cr().read().pllrdy() {} 105 while RCC.cr().read().pllrdy() {}
194 106
195 let freq = match mul { 107 let freq = freq * mul / div;
196 PLLMul::Mul3 => freq * 3,
197 PLLMul::Mul4 => freq * 4,
198 PLLMul::Mul6 => freq * 6,
199 PLLMul::Mul8 => freq * 8,
200 PLLMul::Mul12 => freq * 12,
201 PLLMul::Mul16 => freq * 16,
202 PLLMul::Mul24 => freq * 24,
203 PLLMul::Mul32 => freq * 32,
204 PLLMul::Mul48 => freq * 48,
205 };
206 108
207 let freq = match div { 109 assert!(freq <= Hertz(32_000_000));
208 PLLDiv::Div2 => freq / 2,
209 PLLDiv::Div3 => freq / 3,
210 PLLDiv::Div4 => freq / 4,
211 };
212 assert!(freq <= 32_000_000);
213 110
214 RCC.cfgr().write(move |w| { 111 RCC.cfgr().write(move |w| {
215 w.set_pllmul(mul.into()); 112 w.set_pllmul(mul);
216 w.set_plldiv(div.into()); 113 w.set_plldiv(div);
217 w.set_pllsrc(src.into()); 114 w.set_pllsrc(src.into());
218 }); 115 });
219 116
@@ -226,7 +123,7 @@ pub(crate) unsafe fn init(config: Config) {
226 }; 123 };
227 124
228 // Set flash 64-bit access, prefetch and wait states 125 // Set flash 64-bit access, prefetch and wait states
229 if sys_clk >= 16_000_000 { 126 if sys_clk >= Hertz(16_000_000) {
230 FLASH.acr().write(|w| w.set_acc64(true)); 127 FLASH.acr().write(|w| w.set_acc64(true));
231 FLASH.acr().modify(|w| w.set_prften(true)); 128 FLASH.acr().modify(|w| w.set_prften(true));
232 FLASH.acr().modify(|w| w.set_latency(true)); 129 FLASH.acr().modify(|w| w.set_latency(true));
@@ -234,46 +131,68 @@ pub(crate) unsafe fn init(config: Config) {
234 131
235 RCC.cfgr().modify(|w| { 132 RCC.cfgr().modify(|w| {
236 w.set_sw(sw); 133 w.set_sw(sw);
237 w.set_hpre(config.ahb_pre.into()); 134 w.set_hpre(config.ahb_pre);
238 w.set_ppre1(config.apb1_pre.into()); 135 w.set_ppre1(config.apb1_pre);
239 w.set_ppre2(config.apb2_pre.into()); 136 w.set_ppre2(config.apb2_pre);
240 }); 137 });
241 138
242 let ahb_freq: u32 = match config.ahb_pre { 139 let ahb_freq = sys_clk / config.ahb_pre;
243 AHBPrescaler::DIV1 => sys_clk,
244 pre => {
245 let pre: Hpre = pre.into();
246 let pre = 1 << (pre.to_bits() as u32 - 7);
247 sys_clk / pre
248 }
249 };
250 140
251 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 141 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
252 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 142 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
253 pre => { 143 pre => {
254 let pre: Ppre = pre.into(); 144 let freq = ahb_freq / pre;
255 let pre: u8 = 1 << (pre.to_bits() - 3); 145 (freq, freq * 2u32)
256 let freq = ahb_freq / pre as u32;
257 (freq, freq * 2)
258 } 146 }
259 }; 147 };
260 148
261 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 149 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
262 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 150 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
263 pre => { 151 pre => {
264 let pre: Ppre = pre.into(); 152 let freq = ahb_freq / pre;
265 let pre: u8 = 1 << (pre.to_bits() - 3); 153 (freq, freq * 2u32)
266 let freq = ahb_freq / pre as u32;
267 (freq, freq * 2)
268 } 154 }
269 }; 155 };
270 156
157 #[cfg(crs)]
158 if config.enable_hsi48 {
159 // Reset CRS peripheral
160 RCC.apb1rstr().modify(|w| w.set_crsrst(true));
161 RCC.apb1rstr().modify(|w| w.set_crsrst(false));
162
163 // Enable CRS peripheral
164 RCC.apb1enr().modify(|w| w.set_crsen(true));
165
166 // Initialize CRS
167 CRS.cfgr().write(|w|
168
169 // Select LSE as synchronization source
170 w.set_syncsrc(crs::vals::Syncsrc::LSE));
171 CRS.cr().modify(|w| {
172 w.set_autotrimen(true);
173 w.set_cen(true);
174 });
175
176 // Enable VREFINT reference for HSI48 oscillator
177 SYSCFG.cfgr3().modify(|w| {
178 w.set_enref_hsi48(true);
179 w.set_en_vrefint(true);
180 });
181
182 // Select HSI48 as USB clock
183 RCC.ccipr().modify(|w| w.set_hsi48msel(true));
184
185 // Enable dedicated USB clock
186 RCC.crrcr().modify(|w| w.set_hsi48on(true));
187 while !RCC.crrcr().read().hsi48rdy() {}
188 }
189
271 set_freqs(Clocks { 190 set_freqs(Clocks {
272 sys: Hertz(sys_clk), 191 sys: sys_clk,
273 ahb1: Hertz(ahb_freq), 192 ahb1: ahb_freq,
274 apb1: Hertz(apb1_freq), 193 apb1: apb1_freq,
275 apb2: Hertz(apb2_freq), 194 apb2: apb2_freq,
276 apb1_tim: Hertz(apb1_tim_freq), 195 apb1_tim: apb1_tim_freq,
277 apb2_tim: Hertz(apb2_tim_freq), 196 apb2_tim: apb2_tim_freq,
278 }); 197 });
279} 198}
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs
index 0e35b42e8..686bbd4ee 100644
--- a/embassy-stm32/src/rcc/l4.rs
+++ b/embassy-stm32/src/rcc/l4.rs
@@ -101,8 +101,7 @@ pub(crate) unsafe fn init(config: Config) {
101 ClockSrc::MSI(range) => { 101 ClockSrc::MSI(range) => {
102 // Enable MSI 102 // Enable MSI
103 RCC.cr().write(|w| { 103 RCC.cr().write(|w| {
104 let bits: Msirange = range.into(); 104 w.set_msirange(range);
105 w.set_msirange(bits);
106 w.set_msirgsel(true); 105 w.set_msirgsel(true);
107 w.set_msion(true); 106 w.set_msion(true);
108 107
@@ -154,8 +153,7 @@ pub(crate) unsafe fn init(config: Config) {
154 PLLSource::MSI(range) => { 153 PLLSource::MSI(range) => {
155 // Enable MSI 154 // Enable MSI
156 RCC.cr().write(|w| { 155 RCC.cr().write(|w| {
157 let bits: Msirange = range.into(); 156 w.set_msirange(range);
158 w.set_msirange(bits);
159 w.set_msipllen(false); // should be turned on if LSE is started 157 w.set_msipllen(false); // should be turned on if LSE is started
160 w.set_msirgsel(true); 158 w.set_msirgsel(true);
161 w.set_msion(true); 159 w.set_msion(true);
@@ -255,9 +253,9 @@ pub(crate) unsafe fn init(config: Config) {
255 253
256 RCC.cfgr().modify(|w| { 254 RCC.cfgr().modify(|w| {
257 w.set_sw(sw); 255 w.set_sw(sw);
258 w.set_hpre(config.ahb_pre.into()); 256 w.set_hpre(config.ahb_pre);
259 w.set_ppre1(config.apb1_pre.into()); 257 w.set_ppre1(config.apb1_pre);
260 w.set_ppre2(config.apb2_pre.into()); 258 w.set_ppre2(config.apb2_pre);
261 }); 259 });
262 260
263 let ahb_freq = sys_clk / config.ahb_pre; 261 let ahb_freq = sys_clk / config.ahb_pre;
diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs
index d9b3ee282..ac4804d4f 100644
--- a/embassy-stm32/src/rcc/l5.rs
+++ b/embassy-stm32/src/rcc/l5.rs
@@ -100,8 +100,7 @@ pub(crate) unsafe fn init(config: Config) {
100 ClockSrc::MSI(range) => { 100 ClockSrc::MSI(range) => {
101 // Enable MSI 101 // Enable MSI
102 RCC.cr().write(|w| { 102 RCC.cr().write(|w| {
103 let bits: Msirange = range.into(); 103 w.set_msirange(range);
104 w.set_msirange(bits);
105 w.set_msirgsel(true); 104 w.set_msirgsel(true);
106 w.set_msion(true); 105 w.set_msion(true);
107 106
@@ -153,8 +152,7 @@ pub(crate) unsafe fn init(config: Config) {
153 PLLSource::MSI(range) => { 152 PLLSource::MSI(range) => {
154 // Enable MSI 153 // Enable MSI
155 RCC.cr().write(|w| { 154 RCC.cr().write(|w| {
156 let bits: Msirange = range.into(); 155 w.set_msirange(range);
157 w.set_msirange(bits);
158 w.set_msipllen(false); // should be turned on if LSE is started 156 w.set_msipllen(false); // should be turned on if LSE is started
159 w.set_msirgsel(true); 157 w.set_msirgsel(true);
160 w.set_msion(true); 158 w.set_msion(true);
@@ -250,9 +248,9 @@ pub(crate) unsafe fn init(config: Config) {
250 248
251 RCC.cfgr().modify(|w| { 249 RCC.cfgr().modify(|w| {
252 w.set_sw(sw); 250 w.set_sw(sw);
253 w.set_hpre(config.ahb_pre.into()); 251 w.set_hpre(config.ahb_pre);
254 w.set_ppre1(config.apb1_pre.into()); 252 w.set_ppre1(config.apb1_pre);
255 w.set_ppre2(config.apb2_pre.into()); 253 w.set_ppre2(config.apb2_pre);
256 }); 254 });
257 255
258 let ahb_freq = sys_clk / config.ahb_pre; 256 let ahb_freq = sys_clk / config.ahb_pre;
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs
index ee2a8ae10..f8eeaa953 100644
--- a/embassy-stm32/src/rcc/wb.rs
+++ b/embassy-stm32/src/rcc/wb.rs
@@ -1,107 +1,42 @@
1pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 1pub use crate::pac::rcc::vals::{
2 Hpre as AHBPrescaler, Hsepre as HsePrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Pllsrc as PllSource,
3 Ppre as APBPrescaler, Sw as Sysclk,
4};
2use crate::rcc::bd::{BackupDomain, RtcClockSource}; 5use crate::rcc::bd::{BackupDomain, RtcClockSource};
3use crate::rcc::Clocks; 6use crate::rcc::Clocks;
4use crate::time::{khz, mhz, Hertz}; 7use crate::time::{khz, mhz, Hertz};
5 8
6/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
7/// and with the addition of the init function to configure a system clock.
8
9/// Only the basic setup using the HSE and HSI clocks are supported as of now.
10
11/// HSI speed 9/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(16_000_000); 10pub const HSI_FREQ: Hertz = Hertz(16_000_000);
13 11
14/// LSI speed 12/// LSI speed
15pub const LSI_FREQ: Hertz = Hertz(32_000); 13pub const LSI_FREQ: Hertz = Hertz(32_000);
16 14
17#[derive(Clone, Copy)]
18pub enum HsePrescaler {
19 NotDivided,
20 Div2,
21}
22
23impl From<HsePrescaler> for bool {
24 fn from(value: HsePrescaler) -> Self {
25 match value {
26 HsePrescaler::NotDivided => false,
27 HsePrescaler::Div2 => true,
28 }
29 }
30}
31
32pub struct Hse { 15pub struct Hse {
33 pub prediv: HsePrescaler, 16 pub prediv: HsePrescaler,
34 17
35 pub frequency: Hertz, 18 pub frequency: Hertz,
36} 19}
37 20
38/// System clock mux source
39#[derive(Clone, Copy, PartialEq)]
40pub enum Sysclk {
41 /// MSI selected as sysclk
42 MSI,
43 /// HSI selected as sysclk
44 HSI,
45 /// HSE selected as sysclk
46 HSE,
47 /// PLL selected as sysclk
48 Pll,
49}
50
51impl From<Sysclk> for u8 {
52 fn from(value: Sysclk) -> Self {
53 match value {
54 Sysclk::MSI => 0b00,
55 Sysclk::HSI => 0b01,
56 Sysclk::HSE => 0b10,
57 Sysclk::Pll => 0b11,
58 }
59 }
60}
61
62#[derive(Clone, Copy, PartialEq)]
63pub enum PllSource {
64 Hsi,
65 Msi,
66 Hse,
67}
68
69impl From<PllSource> for u8 {
70 fn from(value: PllSource) -> Self {
71 match value {
72 PllSource::Msi => 0b01,
73 PllSource::Hsi => 0b10,
74 PllSource::Hse => 0b11,
75 }
76 }
77}
78
79pub enum Pll48Source {
80 PllSai,
81 Pll,
82 Msi,
83 Hsi48,
84}
85
86pub struct PllMux { 21pub struct PllMux {
87 /// Source clock selection. 22 /// Source clock selection.
88 pub source: PllSource, 23 pub source: PllSource,
89 24
90 /// PLL pre-divider (DIVM). Must be between 1 and 63. 25 /// PLL pre-divider (DIVM). Must be between 1 and 63.
91 pub prediv: u8, 26 pub prediv: Pllm,
92} 27}
93 28
94pub struct Pll { 29pub struct Pll {
95 /// PLL multiplication factor. Must be between 4 and 512. 30 /// PLL multiplication factor. Must be between 4 and 512.
96 pub mul: u16, 31 pub mul: Plln,
97 32
98 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128. 33 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
99 /// On PLL1, it must be even (in particular, it cannot be 1.) 34 /// On PLL1, it must be even (in particular, it cannot be 1.)
100 pub divp: Option<u16>, 35 pub divp: Option<Pllp>,
101 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128. 36 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
102 pub divq: Option<u16>, 37 pub divq: Option<Pllq>,
103 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128. 38 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
104 pub divr: Option<u16>, 39 pub divr: Option<Pllr>,
105} 40}
106 41
107/// Clocks configutation 42/// Clocks configutation
@@ -111,7 +46,6 @@ pub struct Config {
111 pub lsi: bool, 46 pub lsi: bool,
112 pub sys: Sysclk, 47 pub sys: Sysclk,
113 pub mux: Option<PllMux>, 48 pub mux: Option<PllMux>,
114 pub pll48: Option<Pll48Source>,
115 pub rtc: Option<RtcClockSource>, 49 pub rtc: Option<RtcClockSource>,
116 50
117 pub pll: Option<Pll>, 51 pub pll: Option<Pll>,
@@ -127,23 +61,22 @@ pub struct Config {
127pub const WPAN_DEFAULT: Config = Config { 61pub const WPAN_DEFAULT: Config = Config {
128 hse: Some(Hse { 62 hse: Some(Hse {
129 frequency: mhz(32), 63 frequency: mhz(32),
130 prediv: HsePrescaler::NotDivided, 64 prediv: HsePrescaler::DIV1,
131 }), 65 }),
132 lse: Some(khz(32)), 66 lse: Some(khz(32)),
133 sys: Sysclk::Pll, 67 sys: Sysclk::PLL,
134 mux: Some(PllMux { 68 mux: Some(PllMux {
135 source: PllSource::Hse, 69 source: PllSource::HSE,
136 prediv: 2, 70 prediv: Pllm::DIV2,
137 }), 71 }),
138 pll48: None,
139 rtc: Some(RtcClockSource::LSE), 72 rtc: Some(RtcClockSource::LSE),
140 lsi: false, 73 lsi: false,
141 74
142 pll: Some(Pll { 75 pll: Some(Pll {
143 mul: 12, 76 mul: Plln::MUL12,
144 divp: Some(3), 77 divp: Some(Pllp::DIV3),
145 divq: Some(4), 78 divq: Some(Pllq::DIV4),
146 divr: Some(3), 79 divr: Some(Pllr::DIV3),
147 }), 80 }),
148 pllsai: None, 81 pllsai: None,
149 82
@@ -160,9 +93,8 @@ impl Default for Config {
160 Config { 93 Config {
161 hse: None, 94 hse: None,
162 lse: None, 95 lse: None,
163 sys: Sysclk::HSI, 96 sys: Sysclk::HSI16,
164 mux: None, 97 mux: None,
165 pll48: None,
166 pll: None, 98 pll: None,
167 pllsai: None, 99 pllsai: None,
168 rtc: None, 100 rtc: None,
@@ -178,15 +110,12 @@ impl Default for Config {
178} 110}
179 111
180pub(crate) fn compute_clocks(config: &Config) -> Clocks { 112pub(crate) fn compute_clocks(config: &Config) -> Clocks {
181 let hse_clk = config.hse.as_ref().map(|hse| match hse.prediv { 113 let hse_clk = config.hse.as_ref().map(|hse| hse.frequency / hse.prediv);
182 HsePrescaler::NotDivided => hse.frequency,
183 HsePrescaler::Div2 => hse.frequency / 2u32,
184 });
185 114
186 let mux_clk = config.mux.as_ref().map(|pll_mux| { 115 let mux_clk = config.mux.as_ref().map(|pll_mux| {
187 (match pll_mux.source { 116 (match pll_mux.source {
188 PllSource::Hse => hse_clk.unwrap(), 117 PllSource::HSE => hse_clk.unwrap(),
189 PllSource::Hsi => HSI_FREQ, 118 PllSource::HSI16 => HSI_FREQ,
190 _ => unreachable!(), 119 _ => unreachable!(),
191 } / pll_mux.prediv) 120 } / pll_mux.prediv)
192 }); 121 });
@@ -206,44 +135,19 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
206 135
207 let sys_clk = match config.sys { 136 let sys_clk = match config.sys {
208 Sysclk::HSE => hse_clk.unwrap(), 137 Sysclk::HSE => hse_clk.unwrap(),
209 Sysclk::HSI => HSI_FREQ, 138 Sysclk::HSI16 => HSI_FREQ,
210 Sysclk::Pll => pll_r.unwrap(), 139 Sysclk::PLL => pll_r.unwrap(),
211 _ => unreachable!(), 140 _ => unreachable!(),
212 }; 141 };
213 142
214 let ahb1_clk = match config.ahb1_pre { 143 let ahb1_clk = sys_clk / config.ahb1_pre;
215 AHBPrescaler::DIV1 => sys_clk, 144 let ahb2_clk = sys_clk / config.ahb2_pre;
216 pre => { 145 let ahb3_clk = sys_clk / config.ahb3_pre;
217 let pre: u8 = pre.into();
218 let pre = 1u32 << (pre as u32 - 7);
219 sys_clk / pre
220 }
221 };
222
223 let ahb2_clk = match config.ahb2_pre {
224 AHBPrescaler::DIV1 => sys_clk,
225 pre => {
226 let pre: u8 = pre.into();
227 let pre = 1u32 << (pre as u32 - 7);
228 sys_clk / pre
229 }
230 };
231
232 let ahb3_clk = match config.ahb3_pre {
233 AHBPrescaler::DIV1 => sys_clk,
234 pre => {
235 let pre: u8 = pre.into();
236 let pre = 1u32 << (pre as u32 - 7);
237 sys_clk / pre
238 }
239 };
240 146
241 let (apb1_clk, apb1_tim_clk) = match config.apb1_pre { 147 let (apb1_clk, apb1_tim_clk) = match config.apb1_pre {
242 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk), 148 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
243 pre => { 149 pre => {
244 let pre: u8 = pre.into(); 150 let freq = ahb1_clk / pre;
245 let pre: u8 = 1 << (pre - 3);
246 let freq = ahb1_clk / pre as u32;
247 (freq, freq * 2u32) 151 (freq, freq * 2u32)
248 } 152 }
249 }; 153 };
@@ -251,9 +155,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
251 let (apb2_clk, apb2_tim_clk) = match config.apb2_pre { 155 let (apb2_clk, apb2_tim_clk) = match config.apb2_pre {
252 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk), 156 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
253 pre => { 157 pre => {
254 let pre: u8 = pre.into(); 158 let freq = ahb1_clk / pre;
255 let pre: u8 = 1 << (pre - 3);
256 let freq = ahb1_clk / pre as u32;
257 (freq, freq * 2u32) 159 (freq, freq * 2u32)
258 } 160 }
259 }; 161 };
@@ -282,12 +184,12 @@ pub(crate) fn configure_clocks(config: &Config) {
282 let rcc = crate::pac::RCC; 184 let rcc = crate::pac::RCC;
283 185
284 let needs_hsi = if let Some(pll_mux) = &config.mux { 186 let needs_hsi = if let Some(pll_mux) = &config.mux {
285 pll_mux.source == PllSource::Hsi 187 pll_mux.source == PllSource::HSI16
286 } else { 188 } else {
287 false 189 false
288 }; 190 };
289 191
290 if needs_hsi || config.sys == Sysclk::HSI { 192 if needs_hsi || config.sys == Sysclk::HSI16 {
291 rcc.cr().modify(|w| { 193 rcc.cr().modify(|w| {
292 w.set_hsion(true); 194 w.set_hsion(true);
293 }); 195 });
@@ -306,7 +208,7 @@ pub(crate) fn configure_clocks(config: &Config) {
306 match &config.hse { 208 match &config.hse {
307 Some(hse) => { 209 Some(hse) => {
308 rcc.cr().modify(|w| { 210 rcc.cr().modify(|w| {
309 w.set_hsepre(hse.prediv.into()); 211 w.set_hsepre(hse.prediv);
310 w.set_hseon(true); 212 w.set_hseon(true);
311 }); 213 });
312 214
@@ -328,18 +230,18 @@ pub(crate) fn configure_clocks(config: &Config) {
328 match &config.pll { 230 match &config.pll {
329 Some(pll) => { 231 Some(pll) => {
330 rcc.pllcfgr().modify(|w| { 232 rcc.pllcfgr().modify(|w| {
331 w.set_plln(pll.mul as u8); 233 w.set_plln(pll.mul);
332 pll.divp.map(|divp| { 234 pll.divp.map(|divp| {
333 w.set_pllpen(true); 235 w.set_pllpen(true);
334 w.set_pllp((divp - 1) as u8) 236 w.set_pllp(divp)
335 }); 237 });
336 pll.divq.map(|divq| { 238 pll.divq.map(|divq| {
337 w.set_pllqen(true); 239 w.set_pllqen(true);
338 w.set_pllq((divq - 1) as u8) 240 w.set_pllq(divq)
339 }); 241 });
340 pll.divr.map(|divr| { 242 pll.divr.map(|divr| {
341 // w.set_pllren(true); 243 w.set_pllren(true);
342 w.set_pllr((divr - 1) as u8); 244 w.set_pllr(divr);
343 }); 245 });
344 }); 246 });
345 247
@@ -352,13 +254,13 @@ pub(crate) fn configure_clocks(config: &Config) {
352 254
353 rcc.cfgr().modify(|w| { 255 rcc.cfgr().modify(|w| {
354 w.set_sw(config.sys.into()); 256 w.set_sw(config.sys.into());
355 w.set_hpre(config.ahb1_pre.into()); 257 w.set_hpre(config.ahb1_pre);
356 w.set_ppre1(config.apb1_pre.into()); 258 w.set_ppre1(config.apb1_pre);
357 w.set_ppre2(config.apb2_pre.into()); 259 w.set_ppre2(config.apb2_pre);
358 }); 260 });
359 261
360 rcc.extcfgr().modify(|w| { 262 rcc.extcfgr().modify(|w| {
361 w.set_c2hpre(config.ahb2_pre.into()); 263 w.set_c2hpre(config.ahb2_pre);
362 w.set_shdhpre(config.ahb3_pre.into()); 264 w.set_shdhpre(config.ahb3_pre);
363 }); 265 });
364} 266}
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs
index c5d7ab62f..9ade369f5 100644
--- a/embassy-stm32/src/rcc/wba.rs
+++ b/embassy-stm32/src/rcc/wba.rs
@@ -108,13 +108,13 @@ pub(crate) unsafe fn init(config: Config) {
108 }); 108 });
109 109
110 RCC.cfgr2().modify(|w| { 110 RCC.cfgr2().modify(|w| {
111 w.set_hpre(config.ahb_pre.into()); 111 w.set_hpre(config.ahb_pre);
112 w.set_ppre1(config.apb1_pre.into()); 112 w.set_ppre1(config.apb1_pre);
113 w.set_ppre2(config.apb2_pre.into()); 113 w.set_ppre2(config.apb2_pre);
114 }); 114 });
115 115
116 RCC.cfgr3().modify(|w| { 116 RCC.cfgr3().modify(|w| {
117 w.set_ppre7(config.apb7_pre.into()); 117 w.set_ppre7(config.apb7_pre);
118 }); 118 });
119 119
120 let ahb_freq = sys_clk / config.ahb_pre; 120 let ahb_freq = sys_clk / config.ahb_pre;
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs
index 7baedfcdb..f12588a59 100644
--- a/embassy-stm32/src/rcc/wl.rs
+++ b/embassy-stm32/src/rcc/wl.rs
@@ -1,16 +1,14 @@
1pub use crate::pac::pwr::vals::Vos as VoltageScale; 1pub use crate::pac::pwr::vals::Vos as VoltageScale;
2use crate::pac::rcc::vals::Adcsel; 2use crate::pac::rcc::vals::Sw;
3pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; 3pub use crate::pac::rcc::vals::{
4 Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm, Plln, Pllp, Pllq, Pllr,
5 Pllsrc as PllSource, Ppre as APBPrescaler,
6};
4use crate::pac::{FLASH, RCC}; 7use crate::pac::{FLASH, RCC};
5use crate::rcc::bd::{BackupDomain, RtcClockSource}; 8use crate::rcc::bd::{BackupDomain, RtcClockSource};
6use crate::rcc::{set_freqs, Clocks}; 9use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz; 10use crate::time::Hertz;
8 11
9/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
10/// and with the addition of the init function to configure a system clock.
11
12/// Only the basic setup using the HSE and HSI clocks are supported as of now.
13
14/// HSI speed 12/// HSI speed
15pub const HSI_FREQ: Hertz = Hertz(16_000_000); 13pub const HSI_FREQ: Hertz = Hertz(16_000_000);
16 14
@@ -28,109 +26,6 @@ pub enum ClockSrc {
28 HSI16, 26 HSI16,
29} 27}
30 28
31#[derive(Clone, Copy, PartialOrd, PartialEq)]
32pub enum MSIRange {
33 /// Around 100 kHz
34 Range0,
35 /// Around 200 kHz
36 Range1,
37 /// Around 400 kHz
38 Range2,
39 /// Around 800 kHz
40 Range3,
41 /// Around 1 MHz
42 Range4,
43 /// Around 2 MHz
44 Range5,
45 /// Around 4 MHz (reset value)
46 Range6,
47 /// Around 8 MHz
48 Range7,
49 /// Around 16 MHz
50 Range8,
51 /// Around 24 MHz
52 Range9,
53 /// Around 32 MHz
54 Range10,
55 /// Around 48 MHz
56 Range11,
57}
58
59impl MSIRange {
60 fn freq(&self) -> u32 {
61 match self {
62 MSIRange::Range0 => 100_000,
63 MSIRange::Range1 => 200_000,
64 MSIRange::Range2 => 400_000,
65 MSIRange::Range3 => 800_000,
66 MSIRange::Range4 => 1_000_000,
67 MSIRange::Range5 => 2_000_000,
68 MSIRange::Range6 => 4_000_000,
69 MSIRange::Range7 => 8_000_000,
70 MSIRange::Range8 => 16_000_000,
71 MSIRange::Range9 => 24_000_000,
72 MSIRange::Range10 => 32_000_000,
73 MSIRange::Range11 => 48_000_000,
74 }
75 }
76
77 fn vos(&self) -> VoltageScale {
78 if self > &MSIRange::Range8 {
79 VoltageScale::RANGE1
80 } else {
81 VoltageScale::RANGE2
82 }
83 }
84}
85
86impl Default for MSIRange {
87 fn default() -> MSIRange {
88 MSIRange::Range6
89 }
90}
91
92impl Into<u8> for MSIRange {
93 fn into(self) -> u8 {
94 match self {
95 MSIRange::Range0 => 0b0000,
96 MSIRange::Range1 => 0b0001,
97 MSIRange::Range2 => 0b0010,
98 MSIRange::Range3 => 0b0011,
99 MSIRange::Range4 => 0b0100,
100 MSIRange::Range5 => 0b0101,
101 MSIRange::Range6 => 0b0110,
102 MSIRange::Range7 => 0b0111,
103 MSIRange::Range8 => 0b1000,
104 MSIRange::Range9 => 0b1001,
105 MSIRange::Range10 => 0b1010,
106 MSIRange::Range11 => 0b1011,
107 }
108 }
109}
110
111#[derive(Clone, Copy)]
112pub enum AdcClockSource {
113 HSI16,
114 PLLPCLK,
115 SYSCLK,
116}
117
118impl AdcClockSource {
119 pub fn adcsel(&self) -> Adcsel {
120 match self {
121 AdcClockSource::HSI16 => Adcsel::HSI16,
122 AdcClockSource::PLLPCLK => Adcsel::PLLPCLK,
123 AdcClockSource::SYSCLK => Adcsel::SYSCLK,
124 }
125 }
126}
127
128impl Default for AdcClockSource {
129 fn default() -> Self {
130 Self::HSI16
131 }
132}
133
134/// Clocks configutation 29/// Clocks configutation
135pub struct Config { 30pub struct Config {
136 pub mux: ClockSrc, 31 pub mux: ClockSrc,
@@ -148,7 +43,7 @@ impl Default for Config {
148 #[inline] 43 #[inline]
149 fn default() -> Config { 44 fn default() -> Config {
150 Config { 45 Config {
151 mux: ClockSrc::MSI(MSIRange::default()), 46 mux: ClockSrc::MSI(MSIRange::RANGE4M),
152 ahb_pre: AHBPrescaler::DIV1, 47 ahb_pre: AHBPrescaler::DIV1,
153 shd_ahb_pre: AHBPrescaler::DIV1, 48 shd_ahb_pre: AHBPrescaler::DIV1,
154 apb1_pre: APBPrescaler::DIV1, 49 apb1_pre: APBPrescaler::DIV1,
@@ -156,73 +51,46 @@ impl Default for Config {
156 rtc_mux: RtcClockSource::LSI, 51 rtc_mux: RtcClockSource::LSI,
157 lsi: true, 52 lsi: true,
158 lse: None, 53 lse: None,
159 adc_clock_source: AdcClockSource::default(), 54 adc_clock_source: AdcClockSource::HSI16,
160 } 55 }
161 } 56 }
162} 57}
163 58
164#[repr(u8)]
165pub enum Lsedrv {
166 Low = 0,
167 MediumLow = 1,
168 MediumHigh = 2,
169 High = 3,
170}
171
172pub(crate) unsafe fn init(config: Config) { 59pub(crate) unsafe fn init(config: Config) {
173 let (sys_clk, sw, vos) = match config.mux { 60 let (sys_clk, sw, vos) = match config.mux {
174 ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::RANGE2), 61 ClockSrc::HSI16 => (HSI_FREQ, Sw::HSI16, VoltageScale::RANGE2),
175 ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::RANGE1), 62 ClockSrc::HSE32 => (HSE32_FREQ, Sw::HSE32, VoltageScale::RANGE1),
176 ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()), 63 ClockSrc::MSI(range) => (msirange_to_hertz(range), Sw::MSI, msirange_to_vos(range)),
177 }; 64 };
178 65
179 let ahb_freq: u32 = match config.ahb_pre { 66 let ahb_freq = sys_clk / config.ahb_pre;
180 AHBPrescaler::DIV1 => sys_clk, 67 let shd_ahb_freq = sys_clk / config.shd_ahb_pre;
181 pre => {
182 let pre: u8 = pre.into();
183 let pre = 1 << (pre as u32 - 7);
184 sys_clk / pre
185 }
186 };
187
188 let shd_ahb_freq: u32 = match config.shd_ahb_pre {
189 AHBPrescaler::DIV1 => sys_clk,
190 pre => {
191 let pre: u8 = pre.into();
192 let pre = 1 << (pre as u32 - 7);
193 sys_clk / pre
194 }
195 };
196 68
197 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 69 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
198 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 70 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
199 pre => { 71 pre => {
200 let pre: u8 = pre.into(); 72 let freq = ahb_freq / pre;
201 let pre: u8 = 1 << (pre - 3); 73 (freq, freq * 2u32)
202 let freq = ahb_freq / pre as u32;
203 (freq, freq * 2)
204 } 74 }
205 }; 75 };
206 76
207 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 77 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
208 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 78 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
209 pre => { 79 pre => {
210 let pre: u8 = pre.into(); 80 let freq = ahb_freq / pre;
211 let pre: u8 = 1 << (pre - 3); 81 (freq, freq * 2u32)
212 let freq = ahb_freq / pre as u32;
213 (freq, freq * 2)
214 } 82 }
215 }; 83 };
216 84
217 // Adjust flash latency 85 // Adjust flash latency
218 let flash_clk_src_freq: u32 = shd_ahb_freq; 86 let flash_clk_src_freq = shd_ahb_freq;
219 let ws = match vos { 87 let ws = match vos {
220 VoltageScale::RANGE1 => match flash_clk_src_freq { 88 VoltageScale::RANGE1 => match flash_clk_src_freq.0 {
221 0..=18_000_000 => 0b000, 89 0..=18_000_000 => 0b000,
222 18_000_001..=36_000_000 => 0b001, 90 18_000_001..=36_000_000 => 0b001,
223 _ => 0b010, 91 _ => 0b010,
224 }, 92 },
225 VoltageScale::RANGE2 => match flash_clk_src_freq { 93 VoltageScale::RANGE2 => match flash_clk_src_freq.0 {
226 0..=6_000_000 => 0b000, 94 0..=6_000_000 => 0b000,
227 6_000_001..=12_000_000 => 0b001, 95 6_000_001..=12_000_000 => 0b001,
228 _ => 0b010, 96 _ => 0b010,
@@ -258,7 +126,7 @@ pub(crate) unsafe fn init(config: Config) {
258 assert!(!cr.msion() || cr.msirdy()); 126 assert!(!cr.msion() || cr.msirdy());
259 RCC.cr().write(|w| { 127 RCC.cr().write(|w| {
260 w.set_msirgsel(true); 128 w.set_msirgsel(true);
261 w.set_msirange(range.into()); 129 w.set_msirange(range);
262 w.set_msion(true); 130 w.set_msion(true);
263 131
264 if config.rtc_mux == RtcClockSource::LSE { 132 if config.rtc_mux == RtcClockSource::LSE {
@@ -273,34 +141,56 @@ pub(crate) unsafe fn init(config: Config) {
273 } 141 }
274 142
275 RCC.extcfgr().modify(|w| { 143 RCC.extcfgr().modify(|w| {
276 if config.shd_ahb_pre == AHBPrescaler::DIV1 { 144 w.set_shdhpre(config.shd_ahb_pre);
277 w.set_shdhpre(0);
278 } else {
279 w.set_shdhpre(config.shd_ahb_pre.into());
280 }
281 }); 145 });
282 146
283 RCC.cfgr().modify(|w| { 147 RCC.cfgr().modify(|w| {
284 w.set_sw(sw.into()); 148 w.set_sw(sw.into());
285 w.set_hpre(config.ahb_pre); 149 w.set_hpre(config.ahb_pre);
286 w.set_ppre1(config.apb1_pre.into()); 150 w.set_ppre1(config.apb1_pre);
287 w.set_ppre2(config.apb2_pre.into()); 151 w.set_ppre2(config.apb2_pre);
288 }); 152 });
289 153
290 // ADC clock MUX 154 // ADC clock MUX
291 RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source.adcsel())); 155 RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
292 156
293 // TODO: switch voltage range 157 // TODO: switch voltage range
294 158
295 set_freqs(Clocks { 159 set_freqs(Clocks {
296 sys: Hertz(sys_clk), 160 sys: sys_clk,
297 ahb1: Hertz(ahb_freq), 161 ahb1: ahb_freq,
298 ahb2: Hertz(ahb_freq), 162 ahb2: ahb_freq,
299 ahb3: Hertz(shd_ahb_freq), 163 ahb3: shd_ahb_freq,
300 apb1: Hertz(apb1_freq), 164 apb1: apb1_freq,
301 apb2: Hertz(apb2_freq), 165 apb2: apb2_freq,
302 apb3: Hertz(shd_ahb_freq), 166 apb3: shd_ahb_freq,
303 apb1_tim: Hertz(apb1_tim_freq), 167 apb1_tim: apb1_tim_freq,
304 apb2_tim: Hertz(apb2_tim_freq), 168 apb2_tim: apb2_tim_freq,
305 }); 169 });
306} 170}
171
172fn msirange_to_hertz(range: MSIRange) -> Hertz {
173 match range {
174 MSIRange::RANGE100K => Hertz(100_000),
175 MSIRange::RANGE200K => Hertz(200_000),
176 MSIRange::RANGE400K => Hertz(400_000),
177 MSIRange::RANGE800K => Hertz(800_000),
178 MSIRange::RANGE1M => Hertz(1_000_000),
179 MSIRange::RANGE2M => Hertz(2_000_000),
180 MSIRange::RANGE4M => Hertz(4_000_000),
181 MSIRange::RANGE8M => Hertz(8_000_000),
182 MSIRange::RANGE16M => Hertz(16_000_000),
183 MSIRange::RANGE24M => Hertz(24_000_000),
184 MSIRange::RANGE32M => Hertz(32_000_000),
185 MSIRange::RANGE48M => Hertz(48_000_000),
186 _ => unreachable!(),
187 }
188}
189
190fn msirange_to_vos(range: MSIRange) -> VoltageScale {
191 if range.to_bits() > MSIRange::RANGE16M.to_bits() {
192 VoltageScale::RANGE1
193 } else {
194 VoltageScale::RANGE2
195 }
196}
diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs
index 604503e61..a0bc33944 100644
--- a/embassy-stm32/src/time.rs
+++ b/embassy-stm32/src/time.rs
@@ -77,3 +77,10 @@ impl Div<u8> for Hertz {
77 self / (rhs as u32) 77 self / (rhs as u32)
78 } 78 }
79} 79}
80
81impl Div<Hertz> for Hertz {
82 type Output = u32;
83 fn div(self, rhs: Hertz) -> Self::Output {
84 self.0 / rhs.0
85 }
86}
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index ed246a7db..a9286c44c 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -6,7 +6,7 @@ use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime}; 7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::peripherals::ADC1; 8use embassy_stm32::peripherals::ADC1;
9use embassy_stm32::rcc::AdcClockSource; 9use embassy_stm32::rcc::{AdcClockSource, Adcpres};
10use embassy_stm32::time::mhz; 10use embassy_stm32::time::mhz;
11use embassy_stm32::{adc, bind_interrupts, Config}; 11use embassy_stm32::{adc, bind_interrupts, Config};
12use embassy_time::{Delay, Duration, Timer}; 12use embassy_time::{Delay, Duration, Timer};
@@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) -> ! {
23 config.rcc.hclk = Some(mhz(64)); 23 config.rcc.hclk = Some(mhz(64));
24 config.rcc.pclk1 = Some(mhz(32)); 24 config.rcc.pclk1 = Some(mhz(32));
25 config.rcc.pclk2 = Some(mhz(64)); 25 config.rcc.pclk2 = Some(mhz(64));
26 config.rcc.adc = Some(AdcClockSource::PllDiv1); 26 config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1));
27 27
28 let mut p = embassy_stm32::init(config); 28 let mut p = embassy_stm32::init(config);
29 29
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
index 3fffcfb1f..fb5a85bcb 100644
--- a/examples/stm32f334/src/bin/opamp.rs
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -7,7 +7,7 @@ use embassy_executor::Spawner;
7use embassy_stm32::adc::{Adc, SampleTime}; 7use embassy_stm32::adc::{Adc, SampleTime};
8use embassy_stm32::opamp::{OpAmp, OpAmpGain}; 8use embassy_stm32::opamp::{OpAmp, OpAmpGain};
9use embassy_stm32::peripherals::ADC2; 9use embassy_stm32::peripherals::ADC2;
10use embassy_stm32::rcc::AdcClockSource; 10use embassy_stm32::rcc::{AdcClockSource, Adcpres};
11use embassy_stm32::time::mhz; 11use embassy_stm32::time::mhz;
12use embassy_stm32::{adc, bind_interrupts, Config}; 12use embassy_stm32::{adc, bind_interrupts, Config};
13use embassy_time::{Delay, Duration, Timer}; 13use embassy_time::{Delay, Duration, Timer};
@@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) -> ! {
24 config.rcc.hclk = Some(mhz(64)); 24 config.rcc.hclk = Some(mhz(64));
25 config.rcc.pclk1 = Some(mhz(32)); 25 config.rcc.pclk1 = Some(mhz(32));
26 config.rcc.pclk2 = Some(mhz(64)); 26 config.rcc.pclk2 = Some(mhz(64));
27 config.rcc.adc = Some(AdcClockSource::PllDiv1); 27 config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1));
28 28
29 let mut p = embassy_stm32::init(config); 29 let mut p = embassy_stm32::init(config);
30 30
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs
index da9b18a0e..30a112b7e 100644
--- a/examples/stm32g4/src/bin/adc.rs
+++ b/examples/stm32g4/src/bin/adc.rs
@@ -24,7 +24,7 @@ async fn main(_spawner: Spawner) {
24 div_r: Some(PllR::DIV2), 24 div_r: Some(PllR::DIV2),
25 }); 25 });
26 26
27 config.rcc.adc12_clock_source = AdcClockSource::SysClk; 27 config.rcc.adc12_clock_source = AdcClockSource::SYSCLK;
28 config.rcc.mux = ClockSrc::PLL; 28 config.rcc.mux = ClockSrc::PLL;
29 29
30 let mut p = embassy_stm32::init(config); 30 let mut p = embassy_stm32::init(config);
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 79a9b5e86..f2ba5f7fc 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -322,8 +322,8 @@ pub fn config() -> Config {
322 config.rcc.mux = ClockSrc::PLL( 322 config.rcc.mux = ClockSrc::PLL(
323 // 32Mhz clock (16 * 4 / 2) 323 // 32Mhz clock (16 * 4 / 2)
324 PLLSource::HSI16, 324 PLLSource::HSI16,
325 PLLMul::Mul4, 325 PLLMul::MUL4,
326 PLLDiv::Div2, 326 PLLDiv::DIV2,
327 ); 327 );
328 } 328 }
329 329
@@ -333,8 +333,8 @@ pub fn config() -> Config {
333 config.rcc.mux = ClockSrc::PLL( 333 config.rcc.mux = ClockSrc::PLL(
334 // 32Mhz clock (16 * 4 / 2) 334 // 32Mhz clock (16 * 4 / 2)
335 PLLSource::HSI, 335 PLLSource::HSI,
336 PLLMul::Mul4, 336 PLLMul::MUL4,
337 PLLDiv::Div2, 337 PLLDiv::DIV2,
338 ); 338 );
339 } 339 }
340 340