aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-01-24 09:13:45 +0000
committerGitHub <[email protected]>2025-01-24 09:13:45 +0000
commit4e3d066251578b33d3cb0b8e3d2e44875a001ee5 (patch)
tree2e05dcf5534b4332a1dc5f3fee05fd44a4906a78 /embassy-stm32
parent195b1a593a4f51ebc7ae61b5045c620a1dbd25d8 (diff)
parent4743501172dadc405f71dec34b0b9fa933c916b8 (diff)
Merge pull request #3779 from algesten/fix/f107-rcc
Full RCC support for STM32F107
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/build.rs2
-rw-r--r--embassy-stm32/src/rcc/f013.rs94
2 files changed, 91 insertions, 5 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 21cdfee50..83a836fb2 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -1387,7 +1387,7 @@ fn main() {
1387 for e in rcc_registers.ir.enums { 1387 for e in rcc_registers.ir.enums {
1388 fn is_rcc_name(e: &str) -> bool { 1388 fn is_rcc_name(e: &str) -> bool {
1389 match e { 1389 match e {
1390 "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true, 1390 "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" => true,
1391 "Timpre" | "Pllrclkpre" => false, 1391 "Timpre" | "Pllrclkpre" => false,
1392 e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, 1392 e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true,
1393 _ => false, 1393 _ => false,
diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs
index 57c5cd5b2..13b0ae38e 100644
--- a/embassy-stm32/src/rcc/f013.rs
+++ b/embassy-stm32/src/rcc/f013.rs
@@ -4,11 +4,13 @@ pub use crate::pac::rcc::vals::Adcpre as ADCPrescaler;
4#[cfg(stm32f3)] 4#[cfg(stm32f3)]
5pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler; 5pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler;
6use crate::pac::rcc::vals::Pllsrc; 6use crate::pac::rcc::vals::Pllsrc;
7#[cfg(stm32f1)] 7#[cfg(all(stm32f1, not(stm32f107)))]
8pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv; 8pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv;
9#[cfg(any(stm32f0, stm32f3))] 9#[cfg(any(stm32f0, stm32f3))]
10pub use crate::pac::rcc::vals::Prediv as PllPreDiv; 10pub use crate::pac::rcc::vals::Prediv as PllPreDiv;
11pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Sw as Sysclk}; 11pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Sw as Sysclk};
12#[cfg(stm32f107)]
13pub use crate::pac::rcc::vals::{I2s2src, Pll2mul as Pll2Mul, Prediv1 as PllPreDiv, Prediv1src, Usbpre as UsbPre};
12use crate::pac::{FLASH, RCC}; 14use crate::pac::{FLASH, RCC};
13use crate::time::Hertz; 15use crate::time::Hertz;
14 16
@@ -37,6 +39,8 @@ pub enum PllSource {
37 HSI, 39 HSI,
38 #[cfg(rcc_f0v4)] 40 #[cfg(rcc_f0v4)]
39 HSI48, 41 HSI48,
42 #[cfg(stm32f107)]
43 PLL2,
40} 44}
41 45
42#[derive(Clone, Copy)] 46#[derive(Clone, Copy)]
@@ -52,6 +56,12 @@ pub struct Pll {
52 pub mul: PllMul, 56 pub mul: PllMul,
53} 57}
54 58
59#[cfg(stm32f107)]
60#[derive(Clone, Copy)]
61pub struct Pll2Or3 {
62 pub mul: Pll2Mul,
63}
64
55#[cfg(all(stm32f3, not(rcc_f37)))] 65#[cfg(all(stm32f3, not(rcc_f37)))]
56#[derive(Clone, Copy)] 66#[derive(Clone, Copy)]
57pub enum AdcClockSource { 67pub enum AdcClockSource {
@@ -85,6 +95,12 @@ pub struct Config {
85 pub sys: Sysclk, 95 pub sys: Sysclk,
86 96
87 pub pll: Option<Pll>, 97 pub pll: Option<Pll>,
98 #[cfg(stm32f107)]
99 pub pll2: Option<Pll2Or3>,
100 #[cfg(stm32f107)]
101 pub pll3: Option<Pll2Or3>,
102 #[cfg(stm32f107)]
103 pub prediv2: PllPreDiv,
88 104
89 pub ahb_pre: AHBPrescaler, 105 pub ahb_pre: AHBPrescaler,
90 pub apb1_pre: APBPrescaler, 106 pub apb1_pre: APBPrescaler,
@@ -99,6 +115,11 @@ pub struct Config {
99 #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] 115 #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))]
100 pub adc34: AdcClockSource, 116 pub adc34: AdcClockSource,
101 117
118 #[cfg(stm32f107)]
119 pub i2s2_src: I2s2src,
120 #[cfg(stm32f107)]
121 pub i2s3_src: I2s2src,
122
102 /// Per-peripheral kernel clock selection muxes 123 /// Per-peripheral kernel clock selection muxes
103 pub mux: super::mux::ClockMux, 124 pub mux: super::mux::ClockMux,
104 125
@@ -114,6 +135,14 @@ impl Default for Config {
114 hsi48: Some(Default::default()), 135 hsi48: Some(Default::default()),
115 sys: Sysclk::HSI, 136 sys: Sysclk::HSI,
116 pll: None, 137 pll: None,
138
139 #[cfg(stm32f107)]
140 pll2: None,
141 #[cfg(stm32f107)]
142 pll3: None,
143 #[cfg(stm32f107)]
144 prediv2: PllPreDiv::DIV1,
145
117 ahb_pre: AHBPrescaler::DIV1, 146 ahb_pre: AHBPrescaler::DIV1,
118 apb1_pre: APBPrescaler::DIV1, 147 apb1_pre: APBPrescaler::DIV1,
119 #[cfg(not(stm32f0))] 148 #[cfg(not(stm32f0))]
@@ -129,6 +158,11 @@ impl Default for Config {
129 #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] 158 #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))]
130 adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), 159 adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1),
131 160
161 #[cfg(stm32f107)]
162 i2s2_src: I2s2src::SYS,
163 #[cfg(stm32f107)]
164 i2s3_src: I2s2src::SYS,
165
132 mux: Default::default(), 166 mux: Default::default(),
133 } 167 }
134 } 168 }
@@ -175,6 +209,28 @@ pub(crate) unsafe fn init(config: Config) {
175 #[cfg(not(crs))] 209 #[cfg(not(crs))]
176 let hsi48: Option<Hertz> = None; 210 let hsi48: Option<Hertz> = None;
177 211
212 // PLL2 and PLL3
213 // Configure this before PLL since PLL2 can be the source for PLL.
214 #[cfg(stm32f107)]
215 {
216 // Common prediv for PLL2 and PLL3
217 RCC.cfgr2().modify(|w| w.set_prediv2(config.prediv2));
218
219 // Configure PLL2
220 if let Some(pll2) = config.pll2 {
221 RCC.cfgr2().modify(|w| w.set_pll2mul(pll2.mul));
222 RCC.cr().modify(|w| w.set_pll2on(true));
223 while !RCC.cr().read().pll2rdy() {}
224 }
225
226 // Configure PLL3
227 if let Some(pll3) = config.pll3 {
228 RCC.cfgr2().modify(|w| w.set_pll3mul(pll3.mul));
229 RCC.cr().modify(|w| w.set_pll3on(true));
230 while !RCC.cr().read().pll3rdy() {}
231 }
232 }
233
178 // Enable PLL 234 // Enable PLL
179 let pll = config.pll.map(|pll| { 235 let pll = config.pll.map(|pll| {
180 let (src_val, src_freq) = match pll.src { 236 let (src_val, src_freq) = match pll.src {
@@ -187,21 +243,44 @@ pub(crate) unsafe fn init(config: Config) {
187 } 243 }
188 (Pllsrc::HSI_DIV2, unwrap!(hsi)) 244 (Pllsrc::HSI_DIV2, unwrap!(hsi))
189 } 245 }
190 PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), 246 PllSource::HSE => {
247 #[cfg(stm32f107)]
248 RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::HSE));
249
250 (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse))
251 }
191 #[cfg(rcc_f0v4)] 252 #[cfg(rcc_f0v4)]
192 PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), 253 PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)),
254 #[cfg(stm32f107)]
255 PllSource::PLL2 => {
256 if config.pll2.is_none() {
257 panic!("if PLL source is PLL2, Config::pll2 must also be set.");
258 }
259 RCC.cfgr2().modify(|w| w.set_prediv1src(Prediv1src::PLL2));
260
261 let pll2 = unwrap!(config.pll2);
262 let in_freq = hse.unwrap() / config.prediv2;
263 let pll2freq = in_freq * pll2.mul;
264
265 (Pllsrc::HSE_DIV_PREDIV, pll2freq)
266 }
193 }; 267 };
194 let in_freq = src_freq / pll.prediv; 268 let in_freq = src_freq / pll.prediv;
269
195 rcc_assert!(max::PLL_IN.contains(&in_freq)); 270 rcc_assert!(max::PLL_IN.contains(&in_freq));
196 let out_freq = in_freq * pll.mul; 271 let out_freq = in_freq * pll.mul;
197 rcc_assert!(max::PLL_OUT.contains(&out_freq)); 272 rcc_assert!(max::PLL_OUT.contains(&out_freq));
198 273
199 #[cfg(not(stm32f1))] 274 #[cfg(not(stm32f1))]
200 RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); 275 RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv));
276
277 #[cfg(stm32f107)]
278 RCC.cfgr2().modify(|w| w.set_prediv1(pll.prediv));
279
201 RCC.cfgr().modify(|w| { 280 RCC.cfgr().modify(|w| {
202 w.set_pllmul(pll.mul); 281 w.set_pllmul(pll.mul);
203 w.set_pllsrc(src_val); 282 w.set_pllsrc(src_val);
204 #[cfg(stm32f1)] 283 #[cfg(all(stm32f1, not(stm32f107)))]
205 w.set_pllxtpre(pll.prediv); 284 w.set_pllxtpre(pll.prediv);
206 }); 285 });
207 RCC.cr().modify(|w| w.set_pllon(true)); 286 RCC.cr().modify(|w| w.set_pllon(true));
@@ -213,7 +292,7 @@ pub(crate) unsafe fn init(config: Config) {
213 #[cfg(stm32f3)] 292 #[cfg(stm32f3)]
214 let pll_mul_2 = pll.map(|pll| pll * 2u32); 293 let pll_mul_2 = pll.map(|pll| pll * 2u32);
215 294
216 #[cfg(any(rcc_f1, rcc_f1cl, stm32f3))] 295 #[cfg(any(rcc_f1, rcc_f1cl, stm32f3, stm32f107))]
217 let usb = match pll { 296 let usb = match pll {
218 Some(Hertz(72_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1_5), 297 Some(Hertz(72_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1_5),
219 Some(Hertz(48_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1), 298 Some(Hertz(48_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1),
@@ -293,6 +372,13 @@ pub(crate) unsafe fn init(config: Config) {
293 w.set_adcpre(config.adc_pre); 372 w.set_adcpre(config.adc_pre);
294 }); 373 });
295 374
375 // I2S2 and I2S3
376 #[cfg(stm32f107)]
377 {
378 RCC.cfgr2().modify(|w| w.set_i2s2src(config.i2s2_src));
379 RCC.cfgr2().modify(|w| w.set_i2s3src(config.i2s3_src));
380 }
381
296 // Wait for the new prescalers to kick in 382 // Wait for the new prescalers to kick in
297 // "The clocks are divided with the new prescaler factor from 383 // "The clocks are divided with the new prescaler factor from
298 // 1 to 16 AHB cycles after write" 384 // 1 to 16 AHB cycles after write"