diff options
| -rw-r--r-- | embassy-stm32/build.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f013.rs | 94 |
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)] |
| 5 | pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler; | 5 | pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler; |
| 6 | use crate::pac::rcc::vals::Pllsrc; | 6 | use crate::pac::rcc::vals::Pllsrc; |
| 7 | #[cfg(stm32f1)] | 7 | #[cfg(all(stm32f1, not(stm32f107)))] |
| 8 | pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv; | 8 | pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv; |
| 9 | #[cfg(any(stm32f0, stm32f3))] | 9 | #[cfg(any(stm32f0, stm32f3))] |
| 10 | pub use crate::pac::rcc::vals::Prediv as PllPreDiv; | 10 | pub use crate::pac::rcc::vals::Prediv as PllPreDiv; |
| 11 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Sw as Sysclk}; | 11 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Sw as Sysclk}; |
| 12 | #[cfg(stm32f107)] | ||
| 13 | pub use crate::pac::rcc::vals::{I2s2src, Pll2mul as Pll2Mul, Prediv1 as PllPreDiv, Prediv1src, Usbpre as UsbPre}; | ||
| 12 | use crate::pac::{FLASH, RCC}; | 14 | use crate::pac::{FLASH, RCC}; |
| 13 | use crate::time::Hertz; | 15 | use 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)] | ||
| 61 | pub 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)] |
| 57 | pub enum AdcClockSource { | 67 | pub 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" |
