diff options
| author | Martin Algesten <[email protected]> | 2025-01-16 11:56:46 +0100 |
|---|---|---|
| committer | Martin Algesten <[email protected]> | 2025-01-16 15:31:41 +0100 |
| commit | 9a159a8db0638ea2971eed130a2ae34743da640a (patch) | |
| tree | bd52dd064e69a26156ade2c2b9ac74999762845a /embassy-stm32 | |
| parent | 169f9c27aa33a279aad51a92b52fc047a54b82af (diff) | |
Full RCC support for STM32F107
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/rcc/f013.rs | 112 |
1 files changed, 109 insertions, 3 deletions
diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs index 57c5cd5b2..27e43fa56 100644 --- a/embassy-stm32/src/rcc/f013.rs +++ b/embassy-stm32/src/rcc/f013.rs | |||
| @@ -4,11 +4,15 @@ 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::{ | ||
| 14 | I2s2src, Pll2mul as Pll2Mul, Prediv1 as PllPreDiv, Prediv1src as PreDiv1Src, Usbpre as UsbPre, | ||
| 15 | }; | ||
| 12 | use crate::pac::{FLASH, RCC}; | 16 | use crate::pac::{FLASH, RCC}; |
| 13 | use crate::time::Hertz; | 17 | use crate::time::Hertz; |
| 14 | 18 | ||
| @@ -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,14 @@ 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 prediv1_src: Option<PreDiv1Src>, | ||
| 104 | #[cfg(stm32f107)] | ||
| 105 | pub prediv2: Option<PllPreDiv>, | ||
| 88 | 106 | ||
| 89 | pub ahb_pre: AHBPrescaler, | 107 | pub ahb_pre: AHBPrescaler, |
| 90 | pub apb1_pre: APBPrescaler, | 108 | pub apb1_pre: APBPrescaler, |
| @@ -99,6 +117,11 @@ pub struct Config { | |||
| 99 | #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] | 117 | #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] |
| 100 | pub adc34: AdcClockSource, | 118 | pub adc34: AdcClockSource, |
| 101 | 119 | ||
| 120 | #[cfg(stm32f107)] | ||
| 121 | pub i2s2_src: Option<I2s2src>, | ||
| 122 | #[cfg(stm32f107)] | ||
| 123 | pub i2s3_src: Option<I2s2src>, | ||
| 124 | |||
| 102 | /// Per-peripheral kernel clock selection muxes | 125 | /// Per-peripheral kernel clock selection muxes |
| 103 | pub mux: super::mux::ClockMux, | 126 | pub mux: super::mux::ClockMux, |
| 104 | 127 | ||
| @@ -114,6 +137,16 @@ impl Default for Config { | |||
| 114 | hsi48: Some(Default::default()), | 137 | hsi48: Some(Default::default()), |
| 115 | sys: Sysclk::HSI, | 138 | sys: Sysclk::HSI, |
| 116 | pll: None, | 139 | pll: None, |
| 140 | |||
| 141 | #[cfg(stm32f107)] | ||
| 142 | pll2: None, | ||
| 143 | #[cfg(stm32f107)] | ||
| 144 | pll3: None, | ||
| 145 | #[cfg(stm32f107)] | ||
| 146 | prediv1_src: None, | ||
| 147 | #[cfg(stm32f107)] | ||
| 148 | prediv2: None, | ||
| 149 | |||
| 117 | ahb_pre: AHBPrescaler::DIV1, | 150 | ahb_pre: AHBPrescaler::DIV1, |
| 118 | apb1_pre: APBPrescaler::DIV1, | 151 | apb1_pre: APBPrescaler::DIV1, |
| 119 | #[cfg(not(stm32f0))] | 152 | #[cfg(not(stm32f0))] |
| @@ -129,6 +162,11 @@ impl Default for Config { | |||
| 129 | #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] | 162 | #[cfg(all(stm32f3, not(rcc_f37), any(peri_adc3_common, peri_adc34_common)))] |
| 130 | adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), | 163 | adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), |
| 131 | 164 | ||
| 165 | #[cfg(stm32f107)] | ||
| 166 | i2s2_src: None, | ||
| 167 | #[cfg(stm32f107)] | ||
| 168 | i2s3_src: None, | ||
| 169 | |||
| 132 | mux: Default::default(), | 170 | mux: Default::default(), |
| 133 | } | 171 | } |
| 134 | } | 172 | } |
| @@ -169,6 +207,13 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 169 | } | 207 | } |
| 170 | }; | 208 | }; |
| 171 | 209 | ||
| 210 | #[cfg(stm32f107)] | ||
| 211 | let pll2freq = config.pll2.map(|pll2| { | ||
| 212 | let prediv2 = config.prediv2.unwrap_or(PllPreDiv::DIV1); | ||
| 213 | let in_freq = hse.unwrap() / (prediv2.to_bits() + 1); | ||
| 214 | in_freq * pll2.mul | ||
| 215 | }); | ||
| 216 | |||
| 172 | // configure HSI48 | 217 | // configure HSI48 |
| 173 | #[cfg(crs)] | 218 | #[cfg(crs)] |
| 174 | let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); | 219 | let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); |
| @@ -177,6 +222,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 177 | 222 | ||
| 178 | // Enable PLL | 223 | // Enable PLL |
| 179 | let pll = config.pll.map(|pll| { | 224 | let pll = config.pll.map(|pll| { |
| 225 | #[cfg(stm32f107)] | ||
| 226 | let prediv1_src = config.prediv1_src.unwrap_or(PreDiv1Src::HSE); | ||
| 180 | let (src_val, src_freq) = match pll.src { | 227 | let (src_val, src_freq) = match pll.src { |
| 181 | #[cfg(any(rcc_f0v3, rcc_f0v4, rcc_f3v3))] | 228 | #[cfg(any(rcc_f0v3, rcc_f0v4, rcc_f3v3))] |
| 182 | PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), | 229 | PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), |
| @@ -187,21 +234,39 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 187 | } | 234 | } |
| 188 | (Pllsrc::HSI_DIV2, unwrap!(hsi)) | 235 | (Pllsrc::HSI_DIV2, unwrap!(hsi)) |
| 189 | } | 236 | } |
| 237 | #[cfg(not(stm32f107))] | ||
| 190 | PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), | 238 | PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), |
| 239 | #[cfg(stm32f107)] | ||
| 240 | PllSource::HSE => ( | ||
| 241 | Pllsrc::HSE_DIV_PREDIV, | ||
| 242 | match prediv1_src { | ||
| 243 | PreDiv1Src::HSE => unwrap!(hse), | ||
| 244 | PreDiv1Src::PLL2 => unwrap!(pll2freq), | ||
| 245 | }, | ||
| 246 | ), | ||
| 191 | #[cfg(rcc_f0v4)] | 247 | #[cfg(rcc_f0v4)] |
| 192 | PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), | 248 | PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), |
| 193 | }; | 249 | }; |
| 250 | #[cfg(not(stm32f107))] | ||
| 194 | let in_freq = src_freq / pll.prediv; | 251 | let in_freq = src_freq / pll.prediv; |
| 252 | |||
| 253 | #[cfg(stm32f107)] | ||
| 254 | let in_freq = src_freq / (pll.prediv.to_bits() + 1); | ||
| 255 | |||
| 195 | rcc_assert!(max::PLL_IN.contains(&in_freq)); | 256 | rcc_assert!(max::PLL_IN.contains(&in_freq)); |
| 196 | let out_freq = in_freq * pll.mul; | 257 | let out_freq = in_freq * pll.mul; |
| 197 | rcc_assert!(max::PLL_OUT.contains(&out_freq)); | 258 | rcc_assert!(max::PLL_OUT.contains(&out_freq)); |
| 198 | 259 | ||
| 199 | #[cfg(not(stm32f1))] | 260 | #[cfg(not(stm32f1))] |
| 200 | RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); | 261 | RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); |
| 262 | |||
| 263 | #[cfg(stm32f107)] | ||
| 264 | RCC.cfgr2().modify(|w| w.set_prediv1(pll.prediv)); | ||
| 265 | |||
| 201 | RCC.cfgr().modify(|w| { | 266 | RCC.cfgr().modify(|w| { |
| 202 | w.set_pllmul(pll.mul); | 267 | w.set_pllmul(pll.mul); |
| 203 | w.set_pllsrc(src_val); | 268 | w.set_pllsrc(src_val); |
| 204 | #[cfg(stm32f1)] | 269 | #[cfg(all(stm32f1, not(stm32f107)))] |
| 205 | w.set_pllxtpre(pll.prediv); | 270 | w.set_pllxtpre(pll.prediv); |
| 206 | }); | 271 | }); |
| 207 | RCC.cr().modify(|w| w.set_pllon(true)); | 272 | RCC.cr().modify(|w| w.set_pllon(true)); |
| @@ -210,10 +275,39 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 210 | out_freq | 275 | out_freq |
| 211 | }); | 276 | }); |
| 212 | 277 | ||
| 278 | // Prediv1 Source Mux (HSE or PLL2) | ||
| 279 | #[cfg(stm32f107)] | ||
| 280 | if let Some(prediv1_src) = config.prediv1_src { | ||
| 281 | RCC.cfgr2().modify(|w| w.set_prediv1src(prediv1_src)); | ||
| 282 | } | ||
| 283 | |||
| 284 | // pll2 and pll3 | ||
| 285 | #[cfg(stm32f107)] | ||
| 286 | { | ||
| 287 | // Common prediv for PLL2 and PLL3 | ||
| 288 | if let Some(prediv) = config.prediv2 { | ||
| 289 | RCC.cfgr2().modify(|w| w.set_prediv2(prediv)); | ||
| 290 | } | ||
| 291 | |||
| 292 | // Configure PLL2 | ||
| 293 | if let Some(pll2) = config.pll2 { | ||
| 294 | RCC.cfgr2().modify(|w| w.set_pll2mul(pll2.mul)); | ||
| 295 | RCC.cr().modify(|w| w.set_pll2on(true)); | ||
| 296 | while !RCC.cr().read().pll2rdy() {} | ||
| 297 | } | ||
| 298 | |||
| 299 | // Configure PLL3 | ||
| 300 | if let Some(pll3) = config.pll3 { | ||
| 301 | RCC.cfgr2().modify(|w| w.set_pll3mul(pll3.mul)); | ||
| 302 | RCC.cr().modify(|w| w.set_pll3on(true)); | ||
| 303 | while !RCC.cr().read().pll3rdy() {} | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 213 | #[cfg(stm32f3)] | 307 | #[cfg(stm32f3)] |
| 214 | let pll_mul_2 = pll.map(|pll| pll * 2u32); | 308 | let pll_mul_2 = pll.map(|pll| pll * 2u32); |
| 215 | 309 | ||
| 216 | #[cfg(any(rcc_f1, rcc_f1cl, stm32f3))] | 310 | #[cfg(any(rcc_f1, rcc_f1cl, stm32f3, stm32f107))] |
| 217 | let usb = match pll { | 311 | let usb = match pll { |
| 218 | Some(Hertz(72_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1_5), | 312 | 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), | 313 | Some(Hertz(48_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1), |
| @@ -293,6 +387,18 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 293 | w.set_adcpre(config.adc_pre); | 387 | w.set_adcpre(config.adc_pre); |
| 294 | }); | 388 | }); |
| 295 | 389 | ||
| 390 | // I2S2 and I2S3 | ||
| 391 | #[cfg(stm32f107)] | ||
| 392 | { | ||
| 393 | if let Some(i2s2_src) = config.i2s2_src { | ||
| 394 | RCC.cfgr2().modify(|w| w.set_i2s2src(i2s2_src)); | ||
| 395 | } | ||
| 396 | |||
| 397 | if let Some(i2s3_src) = config.i2s3_src { | ||
| 398 | RCC.cfgr2().modify(|w| w.set_i2s3src(i2s3_src)); | ||
| 399 | } | ||
| 400 | } | ||
| 401 | |||
| 296 | // Wait for the new prescalers to kick in | 402 | // Wait for the new prescalers to kick in |
| 297 | // "The clocks are divided with the new prescaler factor from | 403 | // "The clocks are divided with the new prescaler factor from |
| 298 | // 1 to 16 AHB cycles after write" | 404 | // 1 to 16 AHB cycles after write" |
