aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/rcc/f3.rs609
-rw-r--r--embassy-stm32/src/rcc/mco.rs24
-rw-r--r--examples/stm32f3/src/bin/hello.rs5
-rw-r--r--examples/stm32f3/src/bin/usb_serial.rs21
-rw-r--r--examples/stm32f334/src/bin/adc.rs24
-rw-r--r--examples/stm32f334/src/bin/hello.rs5
-rw-r--r--examples/stm32f334/src/bin/opamp.rs24
-rw-r--r--examples/stm32f334/src/bin/pwm.rs27
-rw-r--r--tests/stm32/src/common.rs18
10 files changed, 350 insertions, 411 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 3f5f12f06..24af17327 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -68,7 +68,7 @@ rand_core = "0.6.3"
68sdio-host = "0.5.0" 68sdio-host = "0.5.0"
69critical-section = "1.1" 69critical-section = "1.1"
70#stm32-metapac = { version = "15" } 70#stm32-metapac = { version = "15" }
71stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-5bf4bec597bdf0d85402789b40c3a37b0f5a8e76" } 71stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ae5bb5fe696a7e61fb41b8b797372aed8103a82" }
72vcell = "0.1.3" 72vcell = "0.1.3"
73bxcan = "0.7.0" 73bxcan = "0.7.0"
74nb = "1.0.0" 74nb = "1.0.0"
@@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] }
89proc-macro2 = "1.0.36" 89proc-macro2 = "1.0.36"
90quote = "1.0.15" 90quote = "1.0.15"
91#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} 91#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
92stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-5bf4bec597bdf0d85402789b40c3a37b0f5a8e76", default-features = false, features = ["metadata"]} 92stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-8ae5bb5fe696a7e61fb41b8b797372aed8103a82", default-features = false, features = ["metadata"]}
93 93
94 94
95[features] 95[features]
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index 25866e446..0a5e67b4a 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -1,208 +1,230 @@
1#[cfg(rcc_f3)]
2use crate::pac::adccommon::vals::Ckmode;
3use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
4pub use crate::pac::rcc::vals::Adcpres; 2pub use crate::pac::rcc::vals::{
5use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; 3 Adcpres as AdcPllPrescaler, Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Prediv as PllPreDiv,
4 Sw as Sysclk,
5};
6use crate::pac::rcc::vals::{Pllsrc, Usbpre};
6use crate::pac::{FLASH, RCC}; 7use crate::pac::{FLASH, RCC};
7use crate::time::Hertz; 8use crate::time::Hertz;
8 9
9/// HSI speed 10/// HSI speed
10pub const HSI_FREQ: Hertz = Hertz(8_000_000); 11pub const HSI_FREQ: Hertz = Hertz(8_000_000);
11 12
12#[cfg(rcc_f3)] 13#[derive(Clone, Copy, Eq, PartialEq)]
13impl From<AdcClockSource> for Ckmode { 14pub enum HseMode {
14 fn from(value: AdcClockSource) -> Self { 15 /// crystal/ceramic oscillator (HSEBYP=0)
15 match value { 16 Oscillator,
16 AdcClockSource::BusDiv1 => Ckmode::SYNCDIV1, 17 /// external analog clock (low swing) (HSEBYP=1)
17 AdcClockSource::BusDiv2 => Ckmode::SYNCDIV2, 18 Bypass,
18 AdcClockSource::BusDiv4 => Ckmode::SYNCDIV4, 19}
19 _ => unreachable!(), 20
20 } 21#[derive(Clone, Copy, Eq, PartialEq)]
21 } 22pub struct Hse {
23 /// HSE frequency.
24 pub freq: Hertz,
25 /// HSE mode.
26 pub mode: HseMode,
27}
28
29#[derive(Clone, Copy, Eq, PartialEq)]
30pub enum PllSource {
31 HSE,
32 HSI,
33}
34
35#[derive(Clone, Copy)]
36pub struct Pll {
37 pub src: PllSource,
38
39 /// PLL pre-divider.
40 ///
41 /// On some F3 chips, this must be 2 if `src == HSI`. Init will panic if this is not the case.
42 pub prediv: PllPreDiv,
43
44 /// PLL multiplication factor.
45 pub mul: PllMul,
22} 46}
23 47
24#[derive(Clone, Copy)] 48#[derive(Clone, Copy)]
25pub enum AdcClockSource { 49pub enum AdcClockSource {
26 Pll(Adcpres), 50 Pll(AdcPllPrescaler),
27 BusDiv1, 51 Hclk(AdcHclkPrescaler),
28 BusDiv2,
29 BusDiv4,
30} 52}
31 53
32impl AdcClockSource { 54#[derive(Clone, Copy, PartialEq, Eq)]
33 pub fn bus_div(&self) -> u32 { 55pub enum AdcHclkPrescaler {
34 match self { 56 Div1,
35 Self::BusDiv1 => 1, 57 Div2,
36 Self::BusDiv2 => 2, 58 Div4,
37 Self::BusDiv4 => 4,
38 _ => unreachable!(),
39 }
40 }
41} 59}
42 60
43#[derive(Default)] 61#[derive(Clone, Copy, PartialEq, Eq)]
44pub enum HrtimClockSource { 62pub enum HrtimClockSource {
45 #[default]
46 BusClk, 63 BusClk,
47 PllClk, 64 PllClk,
48} 65}
49 66
50/// Clocks configutation 67/// Clocks configutation
51#[non_exhaustive] 68#[non_exhaustive]
52#[derive(Default)]
53pub struct Config { 69pub struct Config {
54 /// Frequency of HSE oscillator 70 pub hsi: bool,
55 /// 4MHz to 32MHz 71 pub hse: Option<Hse>,
56 pub hse: Option<Hertz>, 72 pub sys: Sysclk,
57 /// Bypass HSE for an external clock 73
58 pub bypass_hse: bool, 74 pub pll: Option<Pll>,
59 /// Frequency of the System Clock 75
60 pub sysclk: Option<Hertz>, 76 pub ahb_pre: AHBPrescaler,
61 /// Frequency of AHB bus 77 pub apb1_pre: APBPrescaler,
62 pub hclk: Option<Hertz>, 78 pub apb2_pre: APBPrescaler,
63 /// Frequency of APB1 bus 79
64 /// - Max frequency 36MHz 80 #[cfg(not(rcc_f37))]
65 pub pclk1: Option<Hertz>, 81 pub adc: AdcClockSource,
66 /// Frequency of APB2 bus 82 #[cfg(all(not(rcc_f37), adc3_common))]
67 /// - Max frequency with HSE is 72MHz 83 pub adc34: AdcClockSource,
68 /// - Max frequency without HSE is 64MHz
69 pub pclk2: Option<Hertz>,
70 /// USB clock setup
71 /// It is valid only when,
72 /// - HSE is enabled,
73 /// - The System clock frequency is either 48MHz or 72MHz
74 /// - APB1 clock has a minimum frequency of 10MHz
75 pub pll48: bool,
76 #[cfg(rcc_f3)]
77 /// ADC clock setup
78 /// - For AHB, a psc of 4 or less must be used
79 pub adc: Option<AdcClockSource>,
80 #[cfg(rcc_f3)]
81 /// ADC clock setup
82 /// - For AHB, a psc of 4 or less must be used
83 pub adc34: Option<AdcClockSource>,
84 #[cfg(stm32f334)] 84 #[cfg(stm32f334)]
85 pub hrtim: HrtimClockSource, 85 pub hrtim: HrtimClockSource,
86
86 pub ls: super::LsConfig, 87 pub ls: super::LsConfig,
87} 88}
88 89
89// Information required to setup the PLL clock 90impl Default for Config {
90#[derive(Clone, Copy)] 91 fn default() -> Self {
91struct PllConfig { 92 Self {
92 pll_src: Pllsrc, 93 hsi: true,
93 pll_mul: Pllmul, 94 hse: None,
94 pll_div: Option<Prediv>, 95 sys: Sysclk::HSI,
96 pll: None,
97 ahb_pre: AHBPrescaler::DIV1,
98 apb1_pre: APBPrescaler::DIV1,
99 apb2_pre: APBPrescaler::DIV1,
100 ls: Default::default(),
101
102 #[cfg(not(rcc_f37))]
103 adc: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
104 #[cfg(all(not(rcc_f37), adc3_common))]
105 adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
106 #[cfg(stm32f334)]
107 hrtim: HrtimClockSource::BusClk,
108 }
109 }
95} 110}
96 111
97/// Initialize and Set the clock frequencies 112/// Initialize and Set the clock frequencies
98pub(crate) unsafe fn init(config: Config) { 113pub(crate) unsafe fn init(config: Config) {
99 // Calculate the real System clock, and PLL configuration if applicable 114 // Configure HSI
100 let (sysclk, pll_config) = get_sysclk(&config); 115 let hsi = match config.hsi {
101 assert!(sysclk.0 <= 72_000_000); 116 false => {
102 117 RCC.cr().modify(|w| w.set_hsion(false));
103 // Calculate real AHB clock 118 None
104 let hclk = config.hclk.map(|h| h).unwrap_or(sysclk); 119 }
105 let hpre = match sysclk.0 / hclk.0 { 120 true => {
106 0 => unreachable!(), 121 RCC.cr().modify(|w| w.set_hsion(true));
107 1 => Hpre::DIV1, 122 while !RCC.cr().read().hsirdy() {}
108 2 => Hpre::DIV2, 123 Some(HSI_FREQ)
109 3..=5 => Hpre::DIV4, 124 }
110 6..=11 => Hpre::DIV8,
111 12..=39 => Hpre::DIV16,
112 40..=95 => Hpre::DIV64,
113 96..=191 => Hpre::DIV128,
114 192..=383 => Hpre::DIV256,
115 _ => Hpre::DIV512,
116 };
117 let hclk = sysclk / hpre;
118 assert!(hclk <= Hertz(72_000_000));
119
120 // Calculate real APB1 clock
121 let pclk1 = config.pclk1.unwrap_or(hclk);
122 let ppre1 = match hclk / pclk1 {
123 0 => unreachable!(),
124 1 => Ppre::DIV1,
125 2 => Ppre::DIV2,
126 3..=5 => Ppre::DIV4,
127 6..=11 => Ppre::DIV8,
128 _ => Ppre::DIV16,
129 };
130 let timer_mul1 = if ppre1 == Ppre::DIV1 { 1u32 } else { 2 };
131 let pclk1 = hclk / ppre1;
132 assert!(pclk1 <= Hertz(36_000_000));
133
134 // Calculate real APB2 clock
135 let pclk2 = config.pclk2.unwrap_or(hclk);
136 let ppre2 = match hclk / pclk2 {
137 0 => unreachable!(),
138 1 => Ppre::DIV1,
139 2 => Ppre::DIV2,
140 3..=5 => Ppre::DIV4,
141 6..=11 => Ppre::DIV8,
142 _ => Ppre::DIV16,
143 }; 125 };
144 let timer_mul2 = if ppre2 == Ppre::DIV1 { 1u32 } else { 2 };
145 let pclk2 = hclk / ppre2;
146 assert!(pclk2 <= Hertz(72_000_000));
147 126
148 // Set latency based on HCLK frquency 127 // Configure HSE
149 // RM0316: "The prefetch buffer must be kept on when using a prescaler 128 let hse = match config.hse {
150 // different from 1 on the AHB clock.", "Half-cycle access cannot be 129 None => {
151 // used when there is a prescaler different from 1 on the AHB clock" 130 RCC.cr().modify(|w| w.set_hseon(false));
152 FLASH.acr().modify(|w| { 131 None
153 w.set_latency(if hclk <= Hertz(24_000_000) {
154 Latency::WS0
155 } else if hclk <= Hertz(48_000_000) {
156 Latency::WS1
157 } else {
158 Latency::WS2
159 });
160 if hpre != Hpre::DIV1 {
161 w.set_hlfcya(false);
162 w.set_prftbe(true);
163 } 132 }
164 }); 133 Some(hse) => {
134 match hse.mode {
135 HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)),
136 HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)),
137 }
165 138
166 // Enable HSE 139 RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator));
167 // RM0316: "Bits 31:26 Reserved, must be kept at reset value." 140 RCC.cr().modify(|w| w.set_hseon(true));
168 if config.hse.is_some() { 141 while !RCC.cr().read().hserdy() {}
169 RCC.cr().modify(|w| { 142 Some(hse.freq)
170 w.set_hsebyp(config.bypass_hse); 143 }
171 // We turn on clock security to switch to HSI when HSE fails 144 };
172 w.set_csson(true);
173 w.set_hseon(true);
174 });
175 while !RCC.cr().read().hserdy() {}
176 }
177 145
178 // Enable PLL 146 // Enable PLL
179 // RM0316: "Reserved, must be kept at reset value." 147 // RM0316: "Reserved, must be kept at reset value."
180 if let Some(ref pll_config) = pll_config { 148 let pll = config.pll.map(|pll| {
149 let (src_val, src_freq) = match pll.src {
150 #[cfg(rcc_f3v3)]
151 PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)),
152 #[cfg(not(rcc_f3v3))]
153 PllSource::HSI => {
154 if pll.prediv != PllPreDiv::DIV2 {
155 panic!("if PLL source is HSI, PLL prediv must be 2.");
156 }
157 (Pllsrc::HSI_DIV2, unwrap!(hsi))
158 }
159 PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)),
160 };
161 let in_freq = src_freq / pll.prediv;
162 assert!(max::PLL_IN.contains(&in_freq));
163 let out_freq = in_freq * pll.mul;
164 assert!(max::PLL_OUT.contains(&out_freq));
165
166 RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv));
181 RCC.cfgr().modify(|w| { 167 RCC.cfgr().modify(|w| {
182 w.set_pllmul(pll_config.pll_mul); 168 w.set_pllmul(pll.mul);
183 w.set_pllsrc(pll_config.pll_src); 169 w.set_pllsrc(src_val);
184 }); 170 });
185 if let Some(pll_div) = pll_config.pll_div {
186 RCC.cfgr2().modify(|w| w.set_prediv(pll_div));
187 }
188 RCC.cr().modify(|w| w.set_pllon(true)); 171 RCC.cr().modify(|w| w.set_pllon(true));
189 while !RCC.cr().read().pllrdy() {} 172 while !RCC.cr().read().pllrdy() {}
190 }
191 173
192 // CFGR has been written before (PLL) don't overwrite these settings 174 out_freq
193 if config.pll48 { 175 });
194 let usb_pre = get_usb_pre(&config, sysclk, pclk1, &pll_config); 176
195 RCC.cfgr().modify(|w| { 177 let usb = match pll {
196 w.set_usbpre(usb_pre); 178 Some(Hertz(72_000_000)) => {
197 }); 179 RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1_5));
198 } 180 Some(Hertz(48_000_000))
181 }
182 Some(Hertz(48_000_000)) => {
183 RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1));
184 Some(Hertz(48_000_000))
185 }
186 _ => None,
187 };
188
189 // Configure sysclk
190 let sys = match config.sys {
191 Sysclk::HSI => unwrap!(hsi),
192 Sysclk::HSE => unwrap!(hse),
193 Sysclk::PLL1_P => unwrap!(pll),
194 _ => unreachable!(),
195 };
196
197 let hclk = sys / config.ahb_pre;
198 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
199 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
200
201 assert!(max::HCLK.contains(&hclk));
202 assert!(max::PCLK1.contains(&pclk1));
203 assert!(max::PCLK2.contains(&pclk2));
204
205 // Set latency based on HCLK frquency
206 let latency = match hclk.0 {
207 ..=24_000_000 => Latency::WS0,
208 ..=48_000_000 => Latency::WS1,
209 _ => Latency::WS2,
210 };
211 FLASH.acr().modify(|w| {
212 w.set_latency(latency);
213 // RM0316: "The prefetch buffer must be kept on when using a prescaler
214 // different from 1 on the AHB clock.", "Half-cycle access cannot be
215 // used when there is a prescaler different from 1 on the AHB clock"
216 if config.ahb_pre != AHBPrescaler::DIV1 {
217 w.set_hlfcya(false);
218 w.set_prftbe(true);
219 }
220 });
199 221
200 // Set prescalers 222 // Set prescalers
201 // CFGR has been written before (PLL, PLL48) don't overwrite these settings 223 // CFGR has been written before (PLL, PLL48) don't overwrite these settings
202 RCC.cfgr().modify(|w| { 224 RCC.cfgr().modify(|w| {
203 w.set_ppre2(ppre2); 225 w.set_ppre2(config.apb1_pre);
204 w.set_ppre1(ppre1); 226 w.set_ppre1(config.apb2_pre);
205 w.set_hpre(hpre); 227 w.set_hpre(config.ahb_pre);
206 }); 228 });
207 229
208 // Wait for the new prescalers to kick in 230 // Wait for the new prescalers to kick in
@@ -211,53 +233,60 @@ pub(crate) unsafe fn init(config: Config) {
211 cortex_m::asm::delay(16); 233 cortex_m::asm::delay(16);
212 234
213 // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings 235 // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings
214 RCC.cfgr().modify(|w| { 236 RCC.cfgr().modify(|w| w.set_sw(config.sys));
215 w.set_sw(match (pll_config, config.hse) {
216 (Some(_), _) => Sw::PLL1_P,
217 (None, Some(_)) => Sw::HSE,
218 (None, None) => Sw::HSI,
219 })
220 });
221 237
222 #[cfg(rcc_f3)] 238 let rtc = config.ls.init();
223 let adc = config.adc.map(|adc| match adc { 239
240 #[cfg(not(rcc_f37))]
241 use crate::pac::adccommon::vals::Ckmode;
242
243 #[cfg(not(rcc_f37))]
244 let adc = match config.adc {
224 AdcClockSource::Pll(adcpres) => { 245 AdcClockSource::Pll(adcpres) => {
225 RCC.cfgr2().modify(|w| { 246 RCC.cfgr2().modify(|w| w.set_adc12pres(adcpres));
226 // Make sure that we're using the PLL 247 crate::pac::ADC_COMMON
227 pll_config.unwrap(); 248 .ccr()
228 w.set_adc12pres(adcpres); 249 .modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
229 250
230 sysclk / adcpres 251 unwrap!(pll) / adcpres
231 })
232 } 252 }
233 _ => crate::pac::ADC_COMMON.ccr().modify(|w| { 253 AdcClockSource::Hclk(adcpres) => {
234 assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1)); 254 assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
235 255
236 w.set_ckmode(adc.into()); 256 let (div, ckmode) = match adcpres {
257 AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
258 AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
259 AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
260 };
261 crate::pac::ADC_COMMON.ccr().modify(|w| w.set_ckmode(ckmode));
237 262
238 sysclk / adc.bus_div() 263 hclk / div
239 }), 264 }
240 }); 265 };
241 266
242 #[cfg(all(rcc_f3, adc3_common))] 267 #[cfg(all(not(rcc_f37), adc3_common))]
243 let adc34 = config.adc34.map(|adc| match adc { 268 let adc34 = match config.adc34 {
244 AdcClockSource::Pll(adcpres) => { 269 AdcClockSource::Pll(adcpres) => {
245 RCC.cfgr2().modify(|w| { 270 RCC.cfgr2().modify(|w| w.set_adc34pres(adcpres));
246 // Make sure that we're using the PLL 271 crate::pac::ADC3_COMMON
247 pll_config.unwrap(); 272 .ccr()
248 w.set_adc34pres(adcpres); 273 .modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
249 274
250 sysclk / adcpres 275 unwrap!(pll) / adcpres
251 })
252 } 276 }
253 _ => crate::pac::ADC_COMMON.ccr().modify(|w| { 277 AdcClockSource::Hclk(adcpres) => {
254 assert!(!(adc.bus_div() == 1 && hpre != Hpre::DIV1)); 278 assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
255 279
256 w.set_ckmode(adc.into()); 280 let (div, ckmode) = match adcpres {
281 AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
282 AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
283 AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
284 };
285 crate::pac::ADC3_COMMON.ccr().modify(|w| w.set_ckmode(ckmode));
257 286
258 sysclk / adc.bus_div() 287 hclk / div
259 }), 288 }
260 }); 289 };
261 290
262 #[cfg(stm32f334)] 291 #[cfg(stm32f334)]
263 let hrtim = match config.hrtim { 292 let hrtim = match config.hrtim {
@@ -267,195 +296,49 @@ pub(crate) unsafe fn init(config: Config) {
267 use crate::pac::rcc::vals::Timsw; 296 use crate::pac::rcc::vals::Timsw;
268 297
269 // Make sure that we're using the PLL 298 // Make sure that we're using the PLL
270 pll_config.unwrap(); 299 let pll = unwrap!(pll);
271 assert!((pclk2 == sysclk) || (pclk2 * 2u32 == sysclk)); 300 assert!((pclk2 == pll) || (pclk2 * 2u32 == pll));
272 301
273 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL1_P)); 302 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL1_P));
274 303
275 Some(sysclk * 2u32) 304 Some(pll * 2u32)
276 } 305 }
277 }; 306 };
278 307
279 let rtc = config.ls.init();
280
281 set_clocks!( 308 set_clocks!(
282 hsi: None, 309 hsi: hsi,
283 lse: None, 310 hse: hse,
284 pll1_p: None, 311 pll1_p: pll,
285 sys: Some(sysclk), 312 sys: Some(sys),
286 pclk1: Some(pclk1), 313 pclk1: Some(pclk1),
287 pclk2: Some(pclk2), 314 pclk2: Some(pclk2),
288 pclk1_tim: Some(pclk1 * timer_mul1), 315 pclk1_tim: Some(pclk1_tim),
289 pclk2_tim: Some(pclk2 * timer_mul2), 316 pclk2_tim: Some(pclk2_tim),
290 hclk1: Some(hclk), 317 hclk1: Some(hclk),
291 #[cfg(rcc_f3)] 318 #[cfg(not(rcc_f37))]
292 adc: adc, 319 adc: Some(adc),
293 #[cfg(all(rcc_f3, adc3_common))] 320 #[cfg(all(not(rcc_f37), adc3_common))]
294 adc34: adc34, 321 adc34: Some(adc34),
295 #[cfg(all(rcc_f3, not(adc3_common)))]
296 adc34: None,
297 #[cfg(stm32f334)] 322 #[cfg(stm32f334)]
298 hrtim: hrtim, 323 hrtim: hrtim,
299 rtc: rtc, 324 rtc: rtc,
325 usb: usb,
326 lse: None,
300 ); 327 );
301} 328}
302 329
303#[inline] 330mod max {
304fn get_sysclk(config: &Config) -> (Hertz, Option<PllConfig>) { 331 use core::ops::RangeInclusive;
305 match (config.sysclk, config.hse) {
306 (Some(sysclk), Some(hse)) if sysclk == hse => (hse, None),
307 (Some(sysclk), None) if sysclk == HSI_FREQ => (HSI_FREQ, None),
308 // If the user selected System clock is different from HSI or HSE
309 // we will have to setup PLL clock source
310 (Some(sysclk), _) => {
311 let (sysclk, pll_config) = calc_pll(config, sysclk);
312 (sysclk, Some(pll_config))
313 }
314 (None, Some(hse)) => (hse, None),
315 (None, None) => (HSI_FREQ, None),
316 }
317}
318 332
319#[inline] 333 use crate::time::Hertz;
320fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
321 // Calculates the Multiplier and the Divisor to arrive at
322 // the required System clock from PLL source frequency
323 let get_mul_div = |sysclk, pllsrcclk| {
324 let bus_div = gcd(sysclk, pllsrcclk);
325 let mut multiplier = sysclk / bus_div;
326 let mut divisor = pllsrcclk / bus_div;
327 // Minimum PLL multiplier is two
328 if multiplier == 1 {
329 multiplier *= 2;
330 divisor *= 2;
331 }
332 assert!(multiplier <= 16);
333 assert!(divisor <= 16);
334 (multiplier, divisor)
335 };
336 // Based on the source of Pll, we calculate the actual system clock
337 // frequency, PLL's source identifier, multiplier and divisor
338 let (act_sysclk, pll_src, pll_mul, pll_div) = match config.hse {
339 Some(Hertz(hse)) => {
340 let (multiplier, divisor) = get_mul_div(sysclk, hse);
341 (
342 Hertz((hse / divisor) * multiplier),
343 Pllsrc::HSE_DIV_PREDIV,
344 into_pll_mul(multiplier),
345 Some(into_pre_div(divisor)),
346 )
347 }
348 None => {
349 cfg_if::cfg_if! {
350 // For some chips PREDIV is always two, and cannot be changed
351 if #[cfg(any(flashsize_d, flashsize_e))] {
352 let (multiplier, divisor) = get_mul_div(sysclk, HSI_FREQ.0);
353 (
354 Hertz((HSI_FREQ.0 / divisor) * multiplier),
355 Pllsrc::HSI_DIV_PREDIV,
356 into_pll_mul(multiplier),
357 Some(into_pre_div(divisor)),
358 )
359 } else {
360 let pllsrcclk = HSI_FREQ.0 / 2;
361 let multiplier = sysclk / pllsrcclk;
362 assert!(multiplier <= 16);
363 (
364 Hertz(pllsrcclk * multiplier),
365 Pllsrc::HSI_DIV2,
366 into_pll_mul(multiplier),
367 None,
368 )
369 }
370 }
371 }
372 };
373 (
374 act_sysclk,
375 PllConfig {
376 pll_src,
377 pll_mul,
378 pll_div,
379 },
380 )
381}
382 334
383#[inline] 335 pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(32_000_000);
384#[allow(unused_variables)] 336 pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(32_000_000);
385fn get_usb_pre(config: &Config, sysclk: Hertz, pclk1: Hertz, pll_config: &Option<PllConfig>) -> Usbpre {
386 cfg_if::cfg_if! {
387 // Some chips do not have USB
388 if #[cfg(any(stm32f301, stm32f318, stm32f334))] {
389 panic!("USB clock not supported by the chip");
390 } else {
391 let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= Hertz(10_000_000));
392 match (usb_ok, sysclk) {
393 (true, Hertz(72_000_000)) => Usbpre::DIV1_5,
394 (true, Hertz(48_000_000)) => Usbpre::DIV1,
395 _ => panic!(
396 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz"
397 ),
398 }
399 }
400 }
401}
402
403// This function assumes cases when multiplier is one and it
404// being greater than 16 is made impossible
405#[inline]
406fn into_pll_mul(multiplier: u32) -> Pllmul {
407 match multiplier {
408 2 => Pllmul::MUL2,
409 3 => Pllmul::MUL3,
410 4 => Pllmul::MUL4,
411 5 => Pllmul::MUL5,
412 6 => Pllmul::MUL6,
413 7 => Pllmul::MUL7,
414 8 => Pllmul::MUL8,
415 9 => Pllmul::MUL9,
416 10 => Pllmul::MUL10,
417 11 => Pllmul::MUL11,
418 12 => Pllmul::MUL12,
419 13 => Pllmul::MUL13,
420 14 => Pllmul::MUL14,
421 15 => Pllmul::MUL15,
422 16 => Pllmul::MUL16,
423 _ => unreachable!(),
424 }
425}
426 337
427// This function assumes the incoming divisor cannot be greater 338 pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000);
428// than 16 339 pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(36_000_000);
429#[inline] 340 pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000);
430fn into_pre_div(divisor: u32) -> Prediv {
431 match divisor {
432 1 => Prediv::DIV1,
433 2 => Prediv::DIV2,
434 3 => Prediv::DIV3,
435 4 => Prediv::DIV4,
436 5 => Prediv::DIV5,
437 6 => Prediv::DIV6,
438 7 => Prediv::DIV7,
439 8 => Prediv::DIV8,
440 9 => Prediv::DIV9,
441 10 => Prediv::DIV10,
442 11 => Prediv::DIV11,
443 12 => Prediv::DIV12,
444 13 => Prediv::DIV13,
445 14 => Prediv::DIV14,
446 15 => Prediv::DIV15,
447 16 => Prediv::DIV16,
448 _ => unreachable!(),
449 }
450}
451 341
452// Determine GCD using Euclidean algorithm 342 pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(24_000_000);
453#[inline] 343 pub(crate) const PLL_OUT: RangeInclusive<Hertz> = Hertz(16_000_000)..=Hertz(72_000_000);
454fn gcd(mut a: u32, mut b: u32) -> u32 {
455 while b != 0 {
456 let r = a % b;
457 a = b;
458 b = r;
459 }
460 a
461} 344}
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
index eaaf8071c..db0df9fac 100644
--- a/embassy-stm32/src/rcc/mco.rs
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -4,7 +4,7 @@ use embassy_hal_internal::into_ref;
4 4
5use crate::gpio::sealed::AFType; 5use crate::gpio::sealed::AFType;
6use crate::gpio::Speed; 6use crate::gpio::Speed;
7#[cfg(not(stm32f1))] 7#[cfg(not(any(stm32f1, rcc_f3v1, rcc_f37)))]
8pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; 8pub use crate::pac::rcc::vals::Mcopre as McoPrescaler;
9#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))] 9#[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))]
10pub use crate::pac::rcc::vals::Mcosel as McoSource; 10pub use crate::pac::rcc::vals::Mcosel as McoSource;
@@ -13,10 +13,16 @@ pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source};
13use crate::pac::RCC; 13use crate::pac::RCC;
14use crate::{peripherals, Peripheral}; 14use crate::{peripherals, Peripheral};
15 15
16#[cfg(any(stm32f1, rcc_f3v1, rcc_f37))]
17#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
18pub enum McoPrescaler {
19 DIV1,
20}
21
16pub(crate) mod sealed { 22pub(crate) mod sealed {
17 pub trait McoInstance { 23 pub trait McoInstance {
18 type Source; 24 type Source;
19 unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: super::McoPrescaler); 25 unsafe fn apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler);
20 } 26 }
21} 27}
22 28
@@ -29,7 +35,7 @@ macro_rules! impl_peri {
29 impl sealed::McoInstance for peripherals::$peri { 35 impl sealed::McoInstance for peripherals::$peri {
30 type Source = $source; 36 type Source = $source;
31 37
32 unsafe fn apply_clock_settings(source: Self::Source, #[cfg(not(stm32f1))] prescaler: McoPrescaler) { 38 unsafe fn apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) {
33 #[cfg(not(any(stm32u5, stm32wba)))] 39 #[cfg(not(any(stm32u5, stm32wba)))]
34 let r = RCC.cfgr(); 40 let r = RCC.cfgr();
35 #[cfg(any(stm32u5, stm32wba))] 41 #[cfg(any(stm32u5, stm32wba))]
@@ -37,8 +43,8 @@ macro_rules! impl_peri {
37 43
38 r.modify(|w| { 44 r.modify(|w| {
39 w.$set_source(source); 45 w.$set_source(source);
40 #[cfg(not(stm32f1))] 46 #[cfg(not(any(stm32f1, rcc_f3v1, rcc_f37)))]
41 w.$set_prescaler(prescaler); 47 w.$set_prescaler(_prescaler);
42 }); 48 });
43 } 49 }
44 } 50 }
@@ -68,16 +74,12 @@ impl<'d, T: McoInstance> Mco<'d, T> {
68 _peri: impl Peripheral<P = T> + 'd, 74 _peri: impl Peripheral<P = T> + 'd,
69 pin: impl Peripheral<P = impl McoPin<T>> + 'd, 75 pin: impl Peripheral<P = impl McoPin<T>> + 'd,
70 source: T::Source, 76 source: T::Source,
71 #[cfg(not(stm32f1))] prescaler: McoPrescaler, 77 prescaler: McoPrescaler,
72 ) -> Self { 78 ) -> Self {
73 into_ref!(pin); 79 into_ref!(pin);
74 80
75 critical_section::with(|_| unsafe { 81 critical_section::with(|_| unsafe {
76 T::apply_clock_settings( 82 T::apply_clock_settings(source, prescaler);
77 source,
78 #[cfg(not(stm32f1))]
79 prescaler,
80 );
81 pin.set_as_af(pin.af_num(), AFType::OutputPushPull); 83 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
82 pin.set_speed(Speed::VeryHigh); 84 pin.set_speed(Speed::VeryHigh);
83 }); 85 });
diff --git a/examples/stm32f3/src/bin/hello.rs b/examples/stm32f3/src/bin/hello.rs
index fd54da53d..3c295612c 100644
--- a/examples/stm32f3/src/bin/hello.rs
+++ b/examples/stm32f3/src/bin/hello.rs
@@ -3,16 +3,13 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::time::Hertz;
7use embassy_stm32::Config; 6use embassy_stm32::Config;
8use embassy_time::Timer; 7use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
10 9
11#[embassy_executor::main] 10#[embassy_executor::main]
12async fn main(_spawner: Spawner) -> ! { 11async fn main(_spawner: Spawner) -> ! {
13 let mut config = Config::default(); 12 let config = Config::default();
14 config.rcc.hse = Some(Hertz(8_000_000));
15 config.rcc.sysclk = Some(Hertz(16_000_000));
16 let _p = embassy_stm32::init(config); 13 let _p = embassy_stm32::init(config);
17 14
18 loop { 15 loop {
diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs
index cf9ecedfa..ee1c43afd 100644
--- a/examples/stm32f3/src/bin/usb_serial.rs
+++ b/examples/stm32f3/src/bin/usb_serial.rs
@@ -21,11 +21,22 @@ bind_interrupts!(struct Irqs {
21#[embassy_executor::main] 21#[embassy_executor::main]
22async fn main(_spawner: Spawner) { 22async fn main(_spawner: Spawner) {
23 let mut config = Config::default(); 23 let mut config = Config::default();
24 config.rcc.hse = Some(mhz(8)); 24 {
25 config.rcc.sysclk = Some(mhz(48)); 25 use embassy_stm32::rcc::*;
26 config.rcc.pclk1 = Some(mhz(24)); 26 config.rcc.hse = Some(Hse {
27 config.rcc.pclk2 = Some(mhz(24)); 27 freq: mhz(8),
28 config.rcc.pll48 = true; 28 mode: HseMode::Bypass,
29 });
30 config.rcc.pll = Some(Pll {
31 src: PllSource::HSE,
32 prediv: PllPreDiv::DIV1,
33 mul: PllMul::MUL9,
34 });
35 config.rcc.sys = Sysclk::PLL1_P;
36 config.rcc.ahb_pre = AHBPrescaler::DIV1;
37 config.rcc.apb1_pre = APBPrescaler::DIV2;
38 config.rcc.apb2_pre = APBPrescaler::DIV1;
39 }
29 let p = embassy_stm32::init(config); 40 let p = embassy_stm32::init(config);
30 41
31 info!("Hello World!"); 42 info!("Hello World!");
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
index 063ee9dac..a9fb7f1a6 100644
--- a/examples/stm32f334/src/bin/adc.rs
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -5,7 +5,6 @@ use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime}; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC1; 7use embassy_stm32::peripherals::ADC1;
8use embassy_stm32::rcc::{AdcClockSource, Adcpres};
9use embassy_stm32::time::mhz; 8use embassy_stm32::time::mhz;
10use embassy_stm32::{adc, bind_interrupts, Config}; 9use embassy_stm32::{adc, bind_interrupts, Config};
11use embassy_time::{Delay, Timer}; 10use embassy_time::{Delay, Timer};
@@ -18,12 +17,23 @@ bind_interrupts!(struct Irqs {
18#[embassy_executor::main] 17#[embassy_executor::main]
19async fn main(_spawner: Spawner) -> ! { 18async fn main(_spawner: Spawner) -> ! {
20 let mut config = Config::default(); 19 let mut config = Config::default();
21 config.rcc.sysclk = Some(mhz(64)); 20 {
22 config.rcc.hclk = Some(mhz(64)); 21 use embassy_stm32::rcc::*;
23 config.rcc.pclk1 = Some(mhz(32)); 22 config.rcc.hse = Some(Hse {
24 config.rcc.pclk2 = Some(mhz(64)); 23 freq: mhz(8),
25 config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1)); 24 mode: HseMode::Bypass,
26 25 });
26 config.rcc.pll = Some(Pll {
27 src: PllSource::HSE,
28 prediv: PllPreDiv::DIV1,
29 mul: PllMul::MUL9,
30 });
31 config.rcc.sys = Sysclk::PLL1_P;
32 config.rcc.ahb_pre = AHBPrescaler::DIV1;
33 config.rcc.apb1_pre = APBPrescaler::DIV2;
34 config.rcc.apb2_pre = APBPrescaler::DIV1;
35 config.rcc.adc = AdcClockSource::Pll(AdcPllPrescaler::DIV1);
36 }
27 let mut p = embassy_stm32::init(config); 37 let mut p = embassy_stm32::init(config);
28 38
29 info!("create adc..."); 39 info!("create adc...");
diff --git a/examples/stm32f334/src/bin/hello.rs b/examples/stm32f334/src/bin/hello.rs
index fd54da53d..3c295612c 100644
--- a/examples/stm32f334/src/bin/hello.rs
+++ b/examples/stm32f334/src/bin/hello.rs
@@ -3,16 +3,13 @@
3 3
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::time::Hertz;
7use embassy_stm32::Config; 6use embassy_stm32::Config;
8use embassy_time::Timer; 7use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
10 9
11#[embassy_executor::main] 10#[embassy_executor::main]
12async fn main(_spawner: Spawner) -> ! { 11async fn main(_spawner: Spawner) -> ! {
13 let mut config = Config::default(); 12 let config = Config::default();
14 config.rcc.hse = Some(Hertz(8_000_000));
15 config.rcc.sysclk = Some(Hertz(16_000_000));
16 let _p = embassy_stm32::init(config); 13 let _p = embassy_stm32::init(config);
17 14
18 loop { 15 loop {
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs
index 850a0e335..6f25191be 100644
--- a/examples/stm32f334/src/bin/opamp.rs
+++ b/examples/stm32f334/src/bin/opamp.rs
@@ -6,7 +6,6 @@ use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime}; 6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::opamp::{OpAmp, OpAmpGain}; 7use embassy_stm32::opamp::{OpAmp, OpAmpGain};
8use embassy_stm32::peripherals::ADC2; 8use embassy_stm32::peripherals::ADC2;
9use embassy_stm32::rcc::{AdcClockSource, Adcpres};
10use embassy_stm32::time::mhz; 9use embassy_stm32::time::mhz;
11use embassy_stm32::{adc, bind_interrupts, Config}; 10use embassy_stm32::{adc, bind_interrupts, Config};
12use embassy_time::{Delay, Timer}; 11use embassy_time::{Delay, Timer};
@@ -19,12 +18,23 @@ bind_interrupts!(struct Irqs {
19#[embassy_executor::main] 18#[embassy_executor::main]
20async fn main(_spawner: Spawner) -> ! { 19async fn main(_spawner: Spawner) -> ! {
21 let mut config = Config::default(); 20 let mut config = Config::default();
22 config.rcc.sysclk = Some(mhz(64)); 21 {
23 config.rcc.hclk = Some(mhz(64)); 22 use embassy_stm32::rcc::*;
24 config.rcc.pclk1 = Some(mhz(32)); 23 config.rcc.hse = Some(Hse {
25 config.rcc.pclk2 = Some(mhz(64)); 24 freq: mhz(8),
26 config.rcc.adc = Some(AdcClockSource::Pll(Adcpres::DIV1)); 25 mode: HseMode::Bypass,
27 26 });
27 config.rcc.pll = Some(Pll {
28 src: PllSource::HSE,
29 prediv: PllPreDiv::DIV1,
30 mul: PllMul::MUL9,
31 });
32 config.rcc.sys = Sysclk::PLL1_P;
33 config.rcc.ahb_pre = AHBPrescaler::DIV1;
34 config.rcc.apb1_pre = APBPrescaler::DIV2;
35 config.rcc.apb2_pre = APBPrescaler::DIV1;
36 config.rcc.adc = AdcClockSource::Pll(AdcPllPrescaler::DIV1);
37 }
28 let mut p = embassy_stm32::init(config); 38 let mut p = embassy_stm32::init(config);
29 39
30 info!("create adc..."); 40 info!("create adc...");
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs
index c149cad92..7fc1ea926 100644
--- a/examples/stm32f334/src/bin/pwm.rs
+++ b/examples/stm32f334/src/bin/pwm.rs
@@ -4,7 +4,6 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::hrtim::*; 6use embassy_stm32::hrtim::*;
7use embassy_stm32::rcc::HrtimClockSource;
8use embassy_stm32::time::{khz, mhz}; 7use embassy_stm32::time::{khz, mhz};
9use embassy_stm32::Config; 8use embassy_stm32::Config;
10use embassy_time::Timer; 9use embassy_time::Timer;
@@ -12,14 +11,26 @@ use {defmt_rtt as _, panic_probe as _};
12 11
13#[embassy_executor::main] 12#[embassy_executor::main]
14async fn main(_spawner: Spawner) { 13async fn main(_spawner: Spawner) {
15 let mut config: Config = Default::default(); 14 let mut config = Config::default();
16 config.rcc.sysclk = Some(mhz(64)); 15 {
17 config.rcc.hclk = Some(mhz(64)); 16 use embassy_stm32::rcc::*;
18 config.rcc.pclk1 = Some(mhz(32)); 17 config.rcc.hse = Some(Hse {
19 config.rcc.pclk2 = Some(mhz(64)); 18 freq: mhz(8),
20 config.rcc.hrtim = HrtimClockSource::PllClk; 19 mode: HseMode::Bypass,
21 20 });
21 config.rcc.pll = Some(Pll {
22 src: PllSource::HSE,
23 prediv: PllPreDiv::DIV1,
24 mul: PllMul::MUL9,
25 });
26 config.rcc.sys = Sysclk::PLL1_P;
27 config.rcc.ahb_pre = AHBPrescaler::DIV1;
28 config.rcc.apb1_pre = APBPrescaler::DIV2;
29 config.rcc.apb2_pre = APBPrescaler::DIV1;
30 config.rcc.hrtim = HrtimClockSource::PllClk;
31 }
22 let p = embassy_stm32::init(config); 32 let p = embassy_stm32::init(config);
33
23 info!("Hello World!"); 34 info!("Hello World!");
24 35
25 let ch1 = PwmPin::new_cha(p.PA8); 36 let ch1 = PwmPin::new_cha(p.PA8);
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index fefe72c86..36fe8a235 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -276,6 +276,24 @@ pub fn config() -> Config {
276 config.rcc.apb2_pre = APBPrescaler::DIV2; 276 config.rcc.apb2_pre = APBPrescaler::DIV2;
277 } 277 }
278 278
279 #[cfg(feature = "stm32f303ze")]
280 {
281 use embassy_stm32::rcc::*;
282 config.rcc.hse = Some(Hse {
283 freq: Hertz(8_000_000),
284 mode: HseMode::Bypass,
285 });
286 config.rcc.pll = Some(Pll {
287 src: PllSource::HSE,
288 prediv: PllPreDiv::DIV1,
289 mul: PllMul::MUL9,
290 });
291 config.rcc.sys = Sysclk::PLL1_P;
292 config.rcc.ahb_pre = AHBPrescaler::DIV1;
293 config.rcc.apb1_pre = APBPrescaler::DIV2;
294 config.rcc.apb2_pre = APBPrescaler::DIV1;
295 }
296
279 #[cfg(feature = "stm32f429zi")] 297 #[cfg(feature = "stm32f429zi")]
280 { 298 {
281 use embassy_stm32::rcc::*; 299 use embassy_stm32::rcc::*;