diff options
| author | Dario Nieuwenhuis <[email protected]> | 2024-02-14 00:10:59 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2024-02-14 17:24:20 +0100 |
| commit | 1860e2269311df018a47a9a52f9f942c0285c97b (patch) | |
| tree | 8a9581f7881184fc2545172433715213d4fa131a | |
| parent | ccd2c574c37d26d09f67d6410d79e7e3e16e6119 (diff) | |
stm32/rcc: unify f0, f1, f3.
| -rw-r--r-- | embassy-stm32/Cargo.toml | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f0.rs | 232 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f013.rs (renamed from embassy-stm32/src/rcc/f3.rs) | 163 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f1.rs | 257 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f247.rs (renamed from embassy-stm32/src/rcc/f.rs) | 0 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 6 |
6 files changed, 137 insertions, 525 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 4c27164ce..c384f14f1 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -68,7 +68,7 @@ rand_core = "0.6.3" | |||
| 68 | sdio-host = "0.5.0" | 68 | sdio-host = "0.5.0" |
| 69 | critical-section = "1.1" | 69 | critical-section = "1.1" |
| 70 | #stm32-metapac = { version = "15" } | 70 | #stm32-metapac = { version = "15" } |
| 71 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7734584b2007766b1c5a6a7f2654fdb442fa211a" } | 71 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3cc1a1603e61881a6f0a1a47c12c16c57c245ba8" } |
| 72 | vcell = "0.1.3" | 72 | vcell = "0.1.3" |
| 73 | bxcan = "0.7.0" | 73 | bxcan = "0.7.0" |
| 74 | nb = "1.0.0" | 74 | nb = "1.0.0" |
| @@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] } | |||
| 89 | proc-macro2 = "1.0.36" | 89 | proc-macro2 = "1.0.36" |
| 90 | quote = "1.0.15" | 90 | quote = "1.0.15" |
| 91 | #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} | 91 | #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} |
| 92 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7734584b2007766b1c5a6a7f2654fdb442fa211a", default-features = false, features = ["metadata"]} | 92 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-3cc1a1603e61881a6f0a1a47c12c16c57c245ba8", default-features = false, features = ["metadata"]} |
| 93 | 93 | ||
| 94 | 94 | ||
| 95 | [features] | 95 | [features] |
diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs deleted file mode 100644 index d6f995e45..000000000 --- a/embassy-stm32/src/rcc/f0.rs +++ /dev/null | |||
| @@ -1,232 +0,0 @@ | |||
| 1 | use crate::pac::flash::vals::Latency; | ||
| 2 | use crate::pac::rcc::vals::Pllsrc; | ||
| 3 | pub use crate::pac::rcc::vals::{ | ||
| 4 | Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Prediv as PllPreDiv, Sw as Sysclk, | ||
| 5 | }; | ||
| 6 | use crate::pac::{FLASH, RCC}; | ||
| 7 | use crate::time::Hertz; | ||
| 8 | |||
| 9 | /// HSI speed | ||
| 10 | pub const HSI_FREQ: Hertz = Hertz(8_000_000); | ||
| 11 | |||
| 12 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 13 | pub enum HseMode { | ||
| 14 | /// crystal/ceramic oscillator (HSEBYP=0) | ||
| 15 | Oscillator, | ||
| 16 | /// external analog clock (low swing) (HSEBYP=1) | ||
| 17 | Bypass, | ||
| 18 | } | ||
| 19 | |||
| 20 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 21 | pub struct Hse { | ||
| 22 | /// HSE frequency. | ||
| 23 | pub freq: Hertz, | ||
| 24 | /// HSE mode. | ||
| 25 | pub mode: HseMode, | ||
| 26 | } | ||
| 27 | |||
| 28 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 29 | pub enum PllSource { | ||
| 30 | HSE, | ||
| 31 | HSI, | ||
| 32 | #[cfg(rcc_f0v4)] | ||
| 33 | HSI48, | ||
| 34 | } | ||
| 35 | |||
| 36 | #[derive(Clone, Copy)] | ||
| 37 | pub struct Pll { | ||
| 38 | pub src: PllSource, | ||
| 39 | |||
| 40 | /// PLL pre-divider. | ||
| 41 | /// | ||
| 42 | /// On some chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. | ||
| 43 | pub prediv: PllPreDiv, | ||
| 44 | |||
| 45 | /// PLL multiplication factor. | ||
| 46 | pub mul: PllMul, | ||
| 47 | } | ||
| 48 | |||
| 49 | /// Clocks configutation | ||
| 50 | #[non_exhaustive] | ||
| 51 | pub struct Config { | ||
| 52 | pub hsi: bool, | ||
| 53 | pub hse: Option<Hse>, | ||
| 54 | #[cfg(crs)] | ||
| 55 | pub hsi48: Option<super::Hsi48Config>, | ||
| 56 | pub sys: Sysclk, | ||
| 57 | |||
| 58 | pub pll: Option<Pll>, | ||
| 59 | |||
| 60 | pub ahb_pre: AHBPrescaler, | ||
| 61 | pub apb1_pre: APBPrescaler, | ||
| 62 | |||
| 63 | pub ls: super::LsConfig, | ||
| 64 | } | ||
| 65 | |||
| 66 | impl Default for Config { | ||
| 67 | fn default() -> Self { | ||
| 68 | Self { | ||
| 69 | hsi: true, | ||
| 70 | hse: None, | ||
| 71 | #[cfg(crs)] | ||
| 72 | hsi48: Some(Default::default()), | ||
| 73 | sys: Sysclk::HSI, | ||
| 74 | pll: None, | ||
| 75 | ahb_pre: AHBPrescaler::DIV1, | ||
| 76 | apb1_pre: APBPrescaler::DIV1, | ||
| 77 | ls: Default::default(), | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Initialize and Set the clock frequencies | ||
| 83 | pub(crate) unsafe fn init(config: Config) { | ||
| 84 | // Configure HSI | ||
| 85 | let hsi = match config.hsi { | ||
| 86 | false => { | ||
| 87 | RCC.cr().modify(|w| w.set_hsion(false)); | ||
| 88 | None | ||
| 89 | } | ||
| 90 | true => { | ||
| 91 | RCC.cr().modify(|w| w.set_hsion(true)); | ||
| 92 | while !RCC.cr().read().hsirdy() {} | ||
| 93 | Some(HSI_FREQ) | ||
| 94 | } | ||
| 95 | }; | ||
| 96 | |||
| 97 | // Configure HSE | ||
| 98 | let hse = match config.hse { | ||
| 99 | None => { | ||
| 100 | RCC.cr().modify(|w| w.set_hseon(false)); | ||
| 101 | None | ||
| 102 | } | ||
| 103 | Some(hse) => { | ||
| 104 | match hse.mode { | ||
| 105 | HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)), | ||
| 106 | HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)), | ||
| 107 | } | ||
| 108 | |||
| 109 | RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator)); | ||
| 110 | RCC.cr().modify(|w| w.set_hseon(true)); | ||
| 111 | while !RCC.cr().read().hserdy() {} | ||
| 112 | Some(hse.freq) | ||
| 113 | } | ||
| 114 | }; | ||
| 115 | |||
| 116 | // configure HSI48 | ||
| 117 | #[cfg(crs)] | ||
| 118 | let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); | ||
| 119 | #[cfg(not(crs))] | ||
| 120 | let hsi48: Option<Hertz> = None; | ||
| 121 | |||
| 122 | // Enable PLL | ||
| 123 | let pll = config.pll.map(|pll| { | ||
| 124 | let (src_val, src_freq) = match pll.src { | ||
| 125 | #[cfg(not(any(rcc_f0v1, rcc_f0v2)))] | ||
| 126 | PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), | ||
| 127 | #[cfg(any(rcc_f0v1, rcc_f0v2))] | ||
| 128 | PllSource::HSI => { | ||
| 129 | if pll.prediv != PllPreDiv::DIV2 { | ||
| 130 | panic!("if PLL source is HSI, PLL prediv must be 2."); | ||
| 131 | } | ||
| 132 | (Pllsrc::HSI_DIV2, unwrap!(hsi)) | ||
| 133 | } | ||
| 134 | PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), | ||
| 135 | #[cfg(rcc_f0v4)] | ||
| 136 | PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), | ||
| 137 | }; | ||
| 138 | let in_freq = src_freq / pll.prediv; | ||
| 139 | assert!(max::PLL_IN.contains(&in_freq)); | ||
| 140 | let out_freq = in_freq * pll.mul; | ||
| 141 | assert!(max::PLL_OUT.contains(&out_freq)); | ||
| 142 | |||
| 143 | RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); | ||
| 144 | RCC.cfgr().modify(|w| { | ||
| 145 | w.set_pllmul(pll.mul); | ||
| 146 | w.set_pllsrc(src_val); | ||
| 147 | }); | ||
| 148 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 149 | while !RCC.cr().read().pllrdy() {} | ||
| 150 | |||
| 151 | out_freq | ||
| 152 | }); | ||
| 153 | |||
| 154 | // Configure sysclk | ||
| 155 | let sys = match config.sys { | ||
| 156 | Sysclk::HSI => unwrap!(hsi), | ||
| 157 | Sysclk::HSE => unwrap!(hse), | ||
| 158 | Sysclk::PLL1_P => unwrap!(pll), | ||
| 159 | #[cfg(rcc_f0v4)] | ||
| 160 | Sysclk::HSI48 => unwrap!(hsi48), | ||
| 161 | #[allow(unreachable_patterns)] | ||
| 162 | _ => unreachable!(), | ||
| 163 | }; | ||
| 164 | |||
| 165 | let hclk = sys / config.ahb_pre; | ||
| 166 | let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); | ||
| 167 | |||
| 168 | assert!(max::HCLK.contains(&hclk)); | ||
| 169 | assert!(max::PCLK1.contains(&pclk1)); | ||
| 170 | |||
| 171 | // Set latency based on HCLK frquency | ||
| 172 | let latency = match hclk.0 { | ||
| 173 | ..=24_000_000 => Latency::WS0, | ||
| 174 | _ => Latency::WS1, | ||
| 175 | }; | ||
| 176 | FLASH.acr().modify(|w| { | ||
| 177 | w.set_latency(latency); | ||
| 178 | w.set_prftbe(true); | ||
| 179 | }); | ||
| 180 | |||
| 181 | // Set prescalers | ||
| 182 | // CFGR has been written before (PLL, PLL48) don't overwrite these settings | ||
| 183 | RCC.cfgr().modify(|w| { | ||
| 184 | w.set_ppre(config.apb1_pre); | ||
| 185 | w.set_hpre(config.ahb_pre); | ||
| 186 | }); | ||
| 187 | |||
| 188 | // Wait for the new prescalers to kick in | ||
| 189 | // "The clocks are divided with the new prescaler factor from | ||
| 190 | // 1 to 16 AHB cycles after write" | ||
| 191 | cortex_m::asm::delay(16); | ||
| 192 | |||
| 193 | // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings | ||
| 194 | RCC.cfgr().modify(|w| w.set_sw(config.sys)); | ||
| 195 | while RCC.cfgr().read().sws() != config.sys {} | ||
| 196 | |||
| 197 | let rtc = config.ls.init(); | ||
| 198 | |||
| 199 | set_clocks!( | ||
| 200 | hsi: hsi, | ||
| 201 | hse: hse, | ||
| 202 | pll1_p: pll, | ||
| 203 | sys: Some(sys), | ||
| 204 | pclk1: Some(pclk1), | ||
| 205 | pclk2: Some(pclk1), | ||
| 206 | pclk1_tim: Some(pclk1_tim), | ||
| 207 | pclk2_tim: Some(pclk1_tim), | ||
| 208 | hclk1: Some(hclk), | ||
| 209 | #[cfg(all(not(rcc_f37), adc3_common))] | ||
| 210 | adc34: Some(adc34), | ||
| 211 | #[cfg(stm32f334)] | ||
| 212 | hrtim: hrtim, | ||
| 213 | hsi48: hsi48, | ||
| 214 | rtc: rtc, | ||
| 215 | lse: None, | ||
| 216 | ); | ||
| 217 | } | ||
| 218 | |||
| 219 | mod max { | ||
| 220 | use core::ops::RangeInclusive; | ||
| 221 | |||
| 222 | use crate::time::Hertz; | ||
| 223 | |||
| 224 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(32_000_000); | ||
| 225 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(32_000_000); | ||
| 226 | |||
| 227 | pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000); | ||
| 228 | pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000); | ||
| 229 | |||
| 230 | pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(24_000_000); | ||
| 231 | pub(crate) const PLL_OUT: RangeInclusive<Hertz> = Hertz(16_000_000)..=Hertz(48_000_000); | ||
| 232 | } | ||
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f013.rs index 580aa389f..c2933186c 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f013.rs | |||
| @@ -1,9 +1,14 @@ | |||
| 1 | use crate::pac::flash::vals::Latency; | 1 | use crate::pac::flash::vals::Latency; |
| 2 | pub use crate::pac::rcc::vals::{ | 2 | #[cfg(stm32f1)] |
| 3 | Adcpres as AdcPllPrescaler, Hpre as AHBPrescaler, Pllmul as PllMul, Ppre as APBPrescaler, Prediv as PllPreDiv, | 3 | pub use crate::pac::rcc::vals::Adcpre as ADCPrescaler; |
| 4 | Sw as Sysclk, | 4 | #[cfg(stm32f3)] |
| 5 | }; | 5 | pub use crate::pac::rcc::vals::Adcpres as AdcPllPrescaler; |
| 6 | use crate::pac::rcc::vals::{Pllsrc, Usbpre}; | 6 | use crate::pac::rcc::vals::Pllsrc; |
| 7 | #[cfg(stm32f1)] | ||
| 8 | pub use crate::pac::rcc::vals::Pllxtpre as PllPreDiv; | ||
| 9 | #[cfg(any(stm32f0, stm32f3))] | ||
| 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}; | ||
| 7 | use crate::pac::{FLASH, RCC}; | 12 | use crate::pac::{FLASH, RCC}; |
| 8 | use crate::time::Hertz; | 13 | use crate::time::Hertz; |
| 9 | 14 | ||
| @@ -30,6 +35,8 @@ pub struct Hse { | |||
| 30 | pub enum PllSource { | 35 | pub enum PllSource { |
| 31 | HSE, | 36 | HSE, |
| 32 | HSI, | 37 | HSI, |
| 38 | #[cfg(rcc_f0v4)] | ||
| 39 | HSI48, | ||
| 33 | } | 40 | } |
| 34 | 41 | ||
| 35 | #[derive(Clone, Copy)] | 42 | #[derive(Clone, Copy)] |
| @@ -38,19 +45,21 @@ pub struct Pll { | |||
| 38 | 45 | ||
| 39 | /// PLL pre-divider. | 46 | /// PLL pre-divider. |
| 40 | /// | 47 | /// |
| 41 | /// On some F3 chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. | 48 | /// On some chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. |
| 42 | pub prediv: PllPreDiv, | 49 | pub prediv: PllPreDiv, |
| 43 | 50 | ||
| 44 | /// PLL multiplication factor. | 51 | /// PLL multiplication factor. |
| 45 | pub mul: PllMul, | 52 | pub mul: PllMul, |
| 46 | } | 53 | } |
| 47 | 54 | ||
| 55 | #[cfg(all(stm32f3, not(rcc_f37)))] | ||
| 48 | #[derive(Clone, Copy)] | 56 | #[derive(Clone, Copy)] |
| 49 | pub enum AdcClockSource { | 57 | pub enum AdcClockSource { |
| 50 | Pll(AdcPllPrescaler), | 58 | Pll(AdcPllPrescaler), |
| 51 | Hclk(AdcHclkPrescaler), | 59 | Hclk(AdcHclkPrescaler), |
| 52 | } | 60 | } |
| 53 | 61 | ||
| 62 | #[cfg(all(stm32f3, not(rcc_f37)))] | ||
| 54 | #[derive(Clone, Copy, PartialEq, Eq)] | 63 | #[derive(Clone, Copy, PartialEq, Eq)] |
| 55 | pub enum AdcHclkPrescaler { | 64 | pub enum AdcHclkPrescaler { |
| 56 | Div1, | 65 | Div1, |
| @@ -58,6 +67,7 @@ pub enum AdcHclkPrescaler { | |||
| 58 | Div4, | 67 | Div4, |
| 59 | } | 68 | } |
| 60 | 69 | ||
| 70 | #[cfg(stm32f334)] | ||
| 61 | #[derive(Clone, Copy, PartialEq, Eq)] | 71 | #[derive(Clone, Copy, PartialEq, Eq)] |
| 62 | pub enum HrtimClockSource { | 72 | pub enum HrtimClockSource { |
| 63 | BusClk, | 73 | BusClk, |
| @@ -69,17 +79,23 @@ pub enum HrtimClockSource { | |||
| 69 | pub struct Config { | 79 | pub struct Config { |
| 70 | pub hsi: bool, | 80 | pub hsi: bool, |
| 71 | pub hse: Option<Hse>, | 81 | pub hse: Option<Hse>, |
| 82 | #[cfg(crs)] | ||
| 83 | pub hsi48: Option<super::Hsi48Config>, | ||
| 72 | pub sys: Sysclk, | 84 | pub sys: Sysclk, |
| 73 | 85 | ||
| 74 | pub pll: Option<Pll>, | 86 | pub pll: Option<Pll>, |
| 75 | 87 | ||
| 76 | pub ahb_pre: AHBPrescaler, | 88 | pub ahb_pre: AHBPrescaler, |
| 77 | pub apb1_pre: APBPrescaler, | 89 | pub apb1_pre: APBPrescaler, |
| 90 | #[cfg(not(stm32f0))] | ||
| 78 | pub apb2_pre: APBPrescaler, | 91 | pub apb2_pre: APBPrescaler, |
| 79 | 92 | ||
| 80 | #[cfg(not(rcc_f37))] | 93 | #[cfg(stm32f1)] |
| 94 | pub adc_pre: ADCPrescaler, | ||
| 95 | |||
| 96 | #[cfg(all(stm32f3, not(rcc_f37)))] | ||
| 81 | pub adc: AdcClockSource, | 97 | pub adc: AdcClockSource, |
| 82 | #[cfg(all(not(rcc_f37), adc3_common))] | 98 | #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] |
| 83 | pub adc34: AdcClockSource, | 99 | pub adc34: AdcClockSource, |
| 84 | #[cfg(stm32f334)] | 100 | #[cfg(stm32f334)] |
| 85 | pub hrtim: HrtimClockSource, | 101 | pub hrtim: HrtimClockSource, |
| @@ -92,16 +108,24 @@ impl Default for Config { | |||
| 92 | Self { | 108 | Self { |
| 93 | hsi: true, | 109 | hsi: true, |
| 94 | hse: None, | 110 | hse: None, |
| 111 | #[cfg(crs)] | ||
| 112 | hsi48: Some(Default::default()), | ||
| 95 | sys: Sysclk::HSI, | 113 | sys: Sysclk::HSI, |
| 96 | pll: None, | 114 | pll: None, |
| 97 | ahb_pre: AHBPrescaler::DIV1, | 115 | ahb_pre: AHBPrescaler::DIV1, |
| 98 | apb1_pre: APBPrescaler::DIV1, | 116 | apb1_pre: APBPrescaler::DIV1, |
| 117 | #[cfg(not(stm32f0))] | ||
| 99 | apb2_pre: APBPrescaler::DIV1, | 118 | apb2_pre: APBPrescaler::DIV1, |
| 100 | ls: Default::default(), | 119 | ls: Default::default(), |
| 101 | 120 | ||
| 102 | #[cfg(not(rcc_f37))] | 121 | #[cfg(stm32f1)] |
| 122 | // ensure ADC is not out of range by default even if APB2 is maxxed out (36mhz) | ||
| 123 | adc_pre: ADCPrescaler::DIV6, | ||
| 124 | |||
| 125 | |||
| 126 | #[cfg(all(stm32f3, not(rcc_f37)))] | ||
| 103 | adc: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), | 127 | adc: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), |
| 104 | #[cfg(all(not(rcc_f37), adc3_common))] | 128 | #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] |
| 105 | adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), | 129 | adc34: AdcClockSource::Hclk(AdcHclkPrescaler::Div1), |
| 106 | #[cfg(stm32f334)] | 130 | #[cfg(stm32f334)] |
| 107 | hrtim: HrtimClockSource::BusClk, | 131 | hrtim: HrtimClockSource::BusClk, |
| @@ -143,13 +167,18 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 143 | } | 167 | } |
| 144 | }; | 168 | }; |
| 145 | 169 | ||
| 170 | // configure HSI48 | ||
| 171 | #[cfg(crs)] | ||
| 172 | let hsi48 = config.hsi48.map(|config| super::init_hsi48(config)); | ||
| 173 | #[cfg(not(crs))] | ||
| 174 | let hsi48: Option<Hertz> = None; | ||
| 175 | |||
| 146 | // Enable PLL | 176 | // Enable PLL |
| 147 | // RM0316: "Reserved, must be kept at reset value." | ||
| 148 | let pll = config.pll.map(|pll| { | 177 | let pll = config.pll.map(|pll| { |
| 149 | let (src_val, src_freq) = match pll.src { | 178 | let (src_val, src_freq) = match pll.src { |
| 150 | #[cfg(rcc_f3v3)] | 179 | #[cfg(any(rcc_f0v3, rcc_f0v4, rcc_f3v3))] |
| 151 | PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), | 180 | PllSource::HSI => (Pllsrc::HSI_DIV_PREDIV, unwrap!(hsi)), |
| 152 | #[cfg(not(rcc_f3v3))] | 181 | #[cfg(not(any(rcc_f0v3, rcc_f0v4, rcc_f3v3)))] |
| 153 | PllSource::HSI => { | 182 | PllSource::HSI => { |
| 154 | if pll.prediv != PllPreDiv::DIV2 { | 183 | if pll.prediv != PllPreDiv::DIV2 { |
| 155 | panic!("if PLL source is HSI, PLL prediv must be 2."); | 184 | panic!("if PLL source is HSI, PLL prediv must be 2."); |
| @@ -157,16 +186,21 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 157 | (Pllsrc::HSI_DIV2, unwrap!(hsi)) | 186 | (Pllsrc::HSI_DIV2, unwrap!(hsi)) |
| 158 | } | 187 | } |
| 159 | PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), | 188 | PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), |
| 189 | #[cfg(rcc_f0v4)] | ||
| 190 | PllSource::HSI48 => (Pllsrc::HSI48_DIV_PREDIV, unwrap!(hsi48)), | ||
| 160 | }; | 191 | }; |
| 161 | let in_freq = src_freq / pll.prediv; | 192 | let in_freq = src_freq / pll.prediv; |
| 162 | assert!(max::PLL_IN.contains(&in_freq)); | 193 | assert!(max::PLL_IN.contains(&in_freq)); |
| 163 | let out_freq = in_freq * pll.mul; | 194 | let out_freq = in_freq * pll.mul; |
| 164 | assert!(max::PLL_OUT.contains(&out_freq)); | 195 | assert!(max::PLL_OUT.contains(&out_freq)); |
| 165 | 196 | ||
| 197 | #[cfg(not(stm32f1))] | ||
| 166 | RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); | 198 | RCC.cfgr2().modify(|w| w.set_prediv(pll.prediv)); |
| 167 | RCC.cfgr().modify(|w| { | 199 | RCC.cfgr().modify(|w| { |
| 168 | w.set_pllmul(pll.mul); | 200 | w.set_pllmul(pll.mul); |
| 169 | w.set_pllsrc(src_val); | 201 | w.set_pllsrc(src_val); |
| 202 | #[cfg(stm32f1)] | ||
| 203 | w.set_pllxtpre(pll.prediv); | ||
| 170 | }); | 204 | }); |
| 171 | RCC.cr().modify(|w| w.set_pllon(true)); | 205 | RCC.cr().modify(|w| w.set_pllon(true)); |
| 172 | while !RCC.cr().read().pllrdy() {} | 206 | while !RCC.cr().read().pllrdy() {} |
| @@ -174,17 +208,16 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 174 | out_freq | 208 | out_freq |
| 175 | }); | 209 | }); |
| 176 | 210 | ||
| 211 | #[cfg(any(rcc_f1, rcc_f1cl, stm32f3))] | ||
| 177 | let usb = match pll { | 212 | let usb = match pll { |
| 178 | Some(Hertz(72_000_000)) => { | 213 | Some(Hertz(72_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1_5), |
| 179 | RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1_5)); | 214 | Some(Hertz(48_000_000)) => Some(crate::pac::rcc::vals::Usbpre::DIV1), |
| 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, | 215 | _ => None, |
| 187 | }; | 216 | } |
| 217 | .map(|usbpre| { | ||
| 218 | RCC.cfgr().modify(|w| w.set_usbpre(usbpre)); | ||
| 219 | Hertz(48_000_000) | ||
| 220 | }); | ||
| 188 | 221 | ||
| 189 | // Configure sysclk | 222 | // Configure sysclk |
| 190 | let sys = match config.sys { | 223 | let sys = match config.sys { |
| @@ -196,13 +229,28 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 196 | 229 | ||
| 197 | let hclk = sys / config.ahb_pre; | 230 | let hclk = sys / config.ahb_pre; |
| 198 | let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); | 231 | let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); |
| 232 | #[cfg(not(stm32f0))] | ||
| 199 | let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre); | 233 | let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre); |
| 234 | #[cfg(stm32f0)] | ||
| 235 | let (pclk2, pclk2_tim) = (pclk1, pclk1_tim); | ||
| 200 | 236 | ||
| 201 | assert!(max::HCLK.contains(&hclk)); | 237 | assert!(max::HCLK.contains(&hclk)); |
| 202 | assert!(max::PCLK1.contains(&pclk1)); | 238 | assert!(max::PCLK1.contains(&pclk1)); |
| 239 | #[cfg(not(stm32f0))] | ||
| 203 | assert!(max::PCLK2.contains(&pclk2)); | 240 | assert!(max::PCLK2.contains(&pclk2)); |
| 204 | 241 | ||
| 242 | #[cfg(stm32f1)] | ||
| 243 | let adc = pclk2 / config.adc_pre; | ||
| 244 | #[cfg(stm32f1)] | ||
| 245 | assert!(max::ADC.contains(&adc)); | ||
| 246 | |||
| 205 | // Set latency based on HCLK frquency | 247 | // Set latency based on HCLK frquency |
| 248 | #[cfg(stm32f0)] | ||
| 249 | let latency = match hclk.0 { | ||
| 250 | ..=24_000_000 => Latency::WS0, | ||
| 251 | _ => Latency::WS1, | ||
| 252 | }; | ||
| 253 | #[cfg(any(stm32f1, stm32f3))] | ||
| 206 | let latency = match hclk.0 { | 254 | let latency = match hclk.0 { |
| 207 | ..=24_000_000 => Latency::WS0, | 255 | ..=24_000_000 => Latency::WS0, |
| 208 | ..=48_000_000 => Latency::WS1, | 256 | ..=48_000_000 => Latency::WS1, |
| @@ -213,18 +261,28 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 213 | // RM0316: "The prefetch buffer must be kept on when using a prescaler | 261 | // 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 | 262 | // 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" | 263 | // used when there is a prescaler different from 1 on the AHB clock" |
| 264 | #[cfg(stm32f3)] | ||
| 216 | if config.ahb_pre != AHBPrescaler::DIV1 { | 265 | if config.ahb_pre != AHBPrescaler::DIV1 { |
| 217 | w.set_hlfcya(false); | 266 | w.set_hlfcya(false); |
| 218 | w.set_prftbe(true); | 267 | w.set_prftbe(true); |
| 219 | } | 268 | } |
| 269 | #[cfg(not(stm32f3))] | ||
| 270 | w.set_prftbe(true); | ||
| 220 | }); | 271 | }); |
| 221 | 272 | ||
| 222 | // Set prescalers | 273 | // Set prescalers |
| 223 | // CFGR has been written before (PLL, PLL48) don't overwrite these settings | 274 | // CFGR has been written before (PLL, PLL48) don't overwrite these settings |
| 224 | RCC.cfgr().modify(|w| { | 275 | RCC.cfgr().modify(|w: &mut stm32_metapac::rcc::regs::Cfgr| { |
| 225 | w.set_ppre1(config.apb1_pre); | 276 | #[cfg(not(stm32f0))] |
| 226 | w.set_ppre2(config.apb2_pre); | 277 | { |
| 278 | w.set_ppre1(config.apb1_pre); | ||
| 279 | w.set_ppre2(config.apb2_pre); | ||
| 280 | } | ||
| 281 | #[cfg(stm32f0)] | ||
| 282 | w.set_ppre(config.apb1_pre); | ||
| 227 | w.set_hpre(config.ahb_pre); | 283 | w.set_hpre(config.ahb_pre); |
| 284 | #[cfg(stm32f1)] | ||
| 285 | w.set_adcpre(config.adc_pre); | ||
| 228 | }); | 286 | }); |
| 229 | 287 | ||
| 230 | // Wait for the new prescalers to kick in | 288 | // Wait for the new prescalers to kick in |
| @@ -238,10 +296,10 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 238 | 296 | ||
| 239 | let rtc = config.ls.init(); | 297 | let rtc = config.ls.init(); |
| 240 | 298 | ||
| 241 | #[cfg(not(rcc_f37))] | 299 | #[cfg(all(stm32f3, not(rcc_f37)))] |
| 242 | use crate::pac::adccommon::vals::Ckmode; | 300 | use crate::pac::adccommon::vals::Ckmode; |
| 243 | 301 | ||
| 244 | #[cfg(not(rcc_f37))] | 302 | #[cfg(all(stm32f3, not(rcc_f37)))] |
| 245 | let adc = match config.adc { | 303 | let adc = match config.adc { |
| 246 | AdcClockSource::Pll(adcpres) => { | 304 | AdcClockSource::Pll(adcpres) => { |
| 247 | RCC.cfgr2().modify(|w| w.set_adc12pres(adcpres)); | 305 | RCC.cfgr2().modify(|w| w.set_adc12pres(adcpres)); |
| @@ -265,7 +323,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 265 | } | 323 | } |
| 266 | }; | 324 | }; |
| 267 | 325 | ||
| 268 | #[cfg(all(not(rcc_f37), adc3_common))] | 326 | #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] |
| 269 | let adc34 = match config.adc34 { | 327 | let adc34 = match config.adc34 { |
| 270 | AdcClockSource::Pll(adcpres) => { | 328 | AdcClockSource::Pll(adcpres) => { |
| 271 | RCC.cfgr2().modify(|w| w.set_adc34pres(adcpres)); | 329 | RCC.cfgr2().modify(|w| w.set_adc34pres(adcpres)); |
| @@ -316,18 +374,63 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 316 | pclk1_tim: Some(pclk1_tim), | 374 | pclk1_tim: Some(pclk1_tim), |
| 317 | pclk2_tim: Some(pclk2_tim), | 375 | pclk2_tim: Some(pclk2_tim), |
| 318 | hclk1: Some(hclk), | 376 | hclk1: Some(hclk), |
| 319 | #[cfg(not(rcc_f37))] | 377 | #[cfg(all(stm32f3, not(rcc_f37)))] |
| 320 | adc: Some(adc), | 378 | adc: Some(adc), |
| 321 | #[cfg(all(not(rcc_f37), adc3_common))] | 379 | #[cfg(all(stm32f3, not(rcc_f37), adc3_common))] |
| 322 | adc34: Some(adc34), | 380 | adc34: Some(adc34), |
| 323 | #[cfg(stm32f334)] | 381 | #[cfg(stm32f334)] |
| 324 | hrtim: hrtim, | 382 | hrtim: hrtim, |
| 325 | rtc: rtc, | 383 | rtc: rtc, |
| 384 | hsi48: hsi48, | ||
| 385 | #[cfg(any(rcc_f1, rcc_f1cl, stm32f3))] | ||
| 326 | usb: usb, | 386 | usb: usb, |
| 327 | lse: None, | 387 | lse: None, |
| 328 | ); | 388 | ); |
| 329 | } | 389 | } |
| 330 | 390 | ||
| 391 | #[cfg(stm32f0)] | ||
| 392 | mod max { | ||
| 393 | use core::ops::RangeInclusive; | ||
| 394 | |||
| 395 | use crate::time::Hertz; | ||
| 396 | |||
| 397 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(32_000_000); | ||
| 398 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(32_000_000); | ||
| 399 | |||
| 400 | pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000); | ||
| 401 | pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(48_000_000); | ||
| 402 | |||
| 403 | pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(24_000_000); | ||
| 404 | pub(crate) const PLL_OUT: RangeInclusive<Hertz> = Hertz(16_000_000)..=Hertz(48_000_000); | ||
| 405 | } | ||
| 406 | |||
| 407 | #[cfg(stm32f1)] | ||
| 408 | mod max { | ||
| 409 | use core::ops::RangeInclusive; | ||
| 410 | |||
| 411 | use crate::time::Hertz; | ||
| 412 | |||
| 413 | #[cfg(not(rcc_f1cl))] | ||
| 414 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(16_000_000); | ||
| 415 | #[cfg(not(rcc_f1cl))] | ||
| 416 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(25_000_000); | ||
| 417 | |||
| 418 | #[cfg(rcc_f1cl)] | ||
| 419 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(3_000_000)..=Hertz(25_000_000); | ||
| 420 | #[cfg(rcc_f1cl)] | ||
| 421 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(50_000_000); | ||
| 422 | |||
| 423 | pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000); | ||
| 424 | pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(36_000_000); | ||
| 425 | pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000); | ||
| 426 | |||
| 427 | pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(25_000_000); | ||
| 428 | pub(crate) const PLL_OUT: RangeInclusive<Hertz> = Hertz(16_000_000)..=Hertz(72_000_000); | ||
| 429 | |||
| 430 | pub(crate) const ADC: RangeInclusive<Hertz> = Hertz(0)..=Hertz(14_000_000); | ||
| 431 | } | ||
| 432 | |||
| 433 | #[cfg(stm32f3)] | ||
| 331 | mod max { | 434 | mod max { |
| 332 | use core::ops::RangeInclusive; | 435 | use core::ops::RangeInclusive; |
| 333 | 436 | ||
diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs deleted file mode 100644 index 9fdd4c11c..000000000 --- a/embassy-stm32/src/rcc/f1.rs +++ /dev/null | |||
| @@ -1,257 +0,0 @@ | |||
| 1 | use crate::pac::flash::vals::Latency; | ||
| 2 | use crate::pac::rcc::vals::Pllsrc; | ||
| 3 | #[cfg(any(rcc_f1, rcc_f1cl))] | ||
| 4 | use crate::pac::rcc::vals::Usbpre; | ||
| 5 | pub use crate::pac::rcc::vals::{ | ||
| 6 | Adcpre as ADCPrescaler, Hpre as AHBPrescaler, Pllmul as PllMul, Pllxtpre as PllPreDiv, Ppre as APBPrescaler, | ||
| 7 | Sw as Sysclk, | ||
| 8 | }; | ||
| 9 | use crate::pac::{FLASH, RCC}; | ||
| 10 | use crate::time::Hertz; | ||
| 11 | |||
| 12 | /// HSI speed | ||
| 13 | pub const HSI_FREQ: Hertz = Hertz(8_000_000); | ||
| 14 | |||
| 15 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 16 | pub enum HseMode { | ||
| 17 | /// crystal/ceramic oscillator (HSEBYP=0) | ||
| 18 | Oscillator, | ||
| 19 | /// external analog clock (low swing) (HSEBYP=1) | ||
| 20 | Bypass, | ||
| 21 | } | ||
| 22 | |||
| 23 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 24 | pub struct Hse { | ||
| 25 | /// HSE frequency. | ||
| 26 | pub freq: Hertz, | ||
| 27 | /// HSE mode. | ||
| 28 | pub mode: HseMode, | ||
| 29 | } | ||
| 30 | |||
| 31 | #[derive(Clone, Copy, Eq, PartialEq)] | ||
| 32 | pub enum PllSource { | ||
| 33 | HSE, | ||
| 34 | HSI, | ||
| 35 | } | ||
| 36 | |||
| 37 | #[derive(Clone, Copy)] | ||
| 38 | pub struct Pll { | ||
| 39 | pub src: PllSource, | ||
| 40 | |||
| 41 | /// PLL pre-divider. | ||
| 42 | /// | ||
| 43 | /// On some F3 chips, this must be 2 if `src == HSI`. Init will panic if this is not the case. | ||
| 44 | pub prediv: PllPreDiv, | ||
| 45 | |||
| 46 | /// PLL multiplication factor. | ||
| 47 | pub mul: PllMul, | ||
| 48 | } | ||
| 49 | |||
| 50 | /// Clocks configutation | ||
| 51 | #[non_exhaustive] | ||
| 52 | pub struct Config { | ||
| 53 | pub hsi: bool, | ||
| 54 | pub hse: Option<Hse>, | ||
| 55 | pub sys: Sysclk, | ||
| 56 | |||
| 57 | pub pll: Option<Pll>, | ||
| 58 | |||
| 59 | pub ahb_pre: AHBPrescaler, | ||
| 60 | pub apb1_pre: APBPrescaler, | ||
| 61 | pub apb2_pre: APBPrescaler, | ||
| 62 | |||
| 63 | pub adc_pre: ADCPrescaler, | ||
| 64 | |||
| 65 | pub ls: super::LsConfig, | ||
| 66 | } | ||
| 67 | |||
| 68 | impl Default for Config { | ||
| 69 | fn default() -> Self { | ||
| 70 | Self { | ||
| 71 | hsi: true, | ||
| 72 | hse: None, | ||
| 73 | sys: Sysclk::HSI, | ||
| 74 | pll: None, | ||
| 75 | ahb_pre: AHBPrescaler::DIV1, | ||
| 76 | apb1_pre: APBPrescaler::DIV1, | ||
| 77 | apb2_pre: APBPrescaler::DIV1, | ||
| 78 | ls: Default::default(), | ||
| 79 | |||
| 80 | // ensure ADC is not out of range by default even if APB2 is maxxed out (36mhz) | ||
| 81 | adc_pre: ADCPrescaler::DIV6, | ||
| 82 | } | ||
| 83 | } | ||
| 84 | } | ||
| 85 | |||
| 86 | /// Initialize and Set the clock frequencies | ||
| 87 | pub(crate) unsafe fn init(config: Config) { | ||
| 88 | // Configure HSI | ||
| 89 | let hsi = match config.hsi { | ||
| 90 | false => { | ||
| 91 | RCC.cr().modify(|w| w.set_hsion(false)); | ||
| 92 | None | ||
| 93 | } | ||
| 94 | true => { | ||
| 95 | RCC.cr().modify(|w| w.set_hsion(true)); | ||
| 96 | while !RCC.cr().read().hsirdy() {} | ||
| 97 | Some(HSI_FREQ) | ||
| 98 | } | ||
| 99 | }; | ||
| 100 | |||
| 101 | // Configure HSE | ||
| 102 | let hse = match config.hse { | ||
| 103 | None => { | ||
| 104 | RCC.cr().modify(|w| w.set_hseon(false)); | ||
| 105 | None | ||
| 106 | } | ||
| 107 | Some(hse) => { | ||
| 108 | match hse.mode { | ||
| 109 | HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)), | ||
| 110 | HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)), | ||
| 111 | } | ||
| 112 | |||
| 113 | RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator)); | ||
| 114 | RCC.cr().modify(|w| w.set_hseon(true)); | ||
| 115 | while !RCC.cr().read().hserdy() {} | ||
| 116 | Some(hse.freq) | ||
| 117 | } | ||
| 118 | }; | ||
| 119 | |||
| 120 | // Enable PLL | ||
| 121 | let pll = config.pll.map(|pll| { | ||
| 122 | let (src_val, src_freq) = match pll.src { | ||
| 123 | PllSource::HSI => { | ||
| 124 | if pll.prediv != PllPreDiv::DIV2 { | ||
| 125 | panic!("if PLL source is HSI, PLL prediv must be 2."); | ||
| 126 | } | ||
| 127 | (Pllsrc::HSI_DIV2, unwrap!(hsi)) | ||
| 128 | } | ||
| 129 | PllSource::HSE => (Pllsrc::HSE_DIV_PREDIV, unwrap!(hse)), | ||
| 130 | }; | ||
| 131 | let in_freq = src_freq / pll.prediv; | ||
| 132 | assert!(max::PLL_IN.contains(&in_freq)); | ||
| 133 | let out_freq = in_freq * pll.mul; | ||
| 134 | assert!(max::PLL_OUT.contains(&out_freq)); | ||
| 135 | |||
| 136 | RCC.cfgr().modify(|w| { | ||
| 137 | w.set_pllmul(pll.mul); | ||
| 138 | w.set_pllsrc(src_val); | ||
| 139 | w.set_pllxtpre(pll.prediv); | ||
| 140 | }); | ||
| 141 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 142 | while !RCC.cr().read().pllrdy() {} | ||
| 143 | |||
| 144 | out_freq | ||
| 145 | }); | ||
| 146 | |||
| 147 | #[cfg(any(rcc_f1, rcc_f1cl))] | ||
| 148 | let usb = match pll { | ||
| 149 | Some(Hertz(72_000_000)) => { | ||
| 150 | RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1_5)); | ||
| 151 | Some(Hertz(48_000_000)) | ||
| 152 | } | ||
| 153 | Some(Hertz(48_000_000)) => { | ||
| 154 | RCC.cfgr().modify(|w| w.set_usbpre(Usbpre::DIV1)); | ||
| 155 | Some(Hertz(48_000_000)) | ||
| 156 | } | ||
| 157 | _ => None, | ||
| 158 | }; | ||
| 159 | |||
| 160 | // Configure sysclk | ||
| 161 | let sys = match config.sys { | ||
| 162 | Sysclk::HSI => unwrap!(hsi), | ||
| 163 | Sysclk::HSE => unwrap!(hse), | ||
| 164 | Sysclk::PLL1_P => unwrap!(pll), | ||
| 165 | _ => unreachable!(), | ||
| 166 | }; | ||
| 167 | |||
| 168 | let hclk = sys / config.ahb_pre; | ||
| 169 | let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); | ||
| 170 | let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre); | ||
| 171 | |||
| 172 | assert!(max::HCLK.contains(&hclk)); | ||
| 173 | assert!(max::PCLK1.contains(&pclk1)); | ||
| 174 | assert!(max::PCLK2.contains(&pclk2)); | ||
| 175 | |||
| 176 | let adc = pclk2 / config.adc_pre; | ||
| 177 | assert!(max::ADC.contains(&adc)); | ||
| 178 | |||
| 179 | // Set latency based on HCLK frquency | ||
| 180 | let latency = match hclk.0 { | ||
| 181 | ..=24_000_000 => Latency::WS0, | ||
| 182 | ..=48_000_000 => Latency::WS1, | ||
| 183 | _ => Latency::WS2, | ||
| 184 | }; | ||
| 185 | FLASH.acr().modify(|w| { | ||
| 186 | w.set_latency(latency); | ||
| 187 | // RM0316: "The prefetch buffer must be kept on when using a prescaler | ||
| 188 | // different from 1 on the AHB clock.", "Half-cycle access cannot be | ||
| 189 | // used when there is a prescaler different from 1 on the AHB clock" | ||
| 190 | if config.ahb_pre != AHBPrescaler::DIV1 { | ||
| 191 | w.set_hlfcya(false); | ||
| 192 | w.set_prftbe(true); | ||
| 193 | } | ||
| 194 | }); | ||
| 195 | |||
| 196 | // Set prescalers | ||
| 197 | // CFGR has been written before (PLL, PLL48) don't overwrite these settings | ||
| 198 | RCC.cfgr().modify(|w| { | ||
| 199 | w.set_ppre1(config.apb1_pre); | ||
| 200 | w.set_ppre2(config.apb2_pre); | ||
| 201 | w.set_hpre(config.ahb_pre); | ||
| 202 | w.set_adcpre(config.adc_pre); | ||
| 203 | }); | ||
| 204 | |||
| 205 | // Wait for the new prescalers to kick in | ||
| 206 | // "The clocks are divided with the new prescaler factor from | ||
| 207 | // 1 to 16 AHB cycles after write" | ||
| 208 | cortex_m::asm::delay(16); | ||
| 209 | |||
| 210 | // CFGR has been written before (PLL, PLL48, clock divider) don't overwrite these settings | ||
| 211 | RCC.cfgr().modify(|w| w.set_sw(config.sys)); | ||
| 212 | while RCC.cfgr().read().sws() != config.sys {} | ||
| 213 | |||
| 214 | let rtc = config.ls.init(); | ||
| 215 | |||
| 216 | set_clocks!( | ||
| 217 | hsi: hsi, | ||
| 218 | hse: hse, | ||
| 219 | pll1_p: pll, | ||
| 220 | sys: Some(sys), | ||
| 221 | pclk1: Some(pclk1), | ||
| 222 | pclk2: Some(pclk2), | ||
| 223 | pclk1_tim: Some(pclk1_tim), | ||
| 224 | pclk2_tim: Some(pclk2_tim), | ||
| 225 | hclk1: Some(hclk), | ||
| 226 | adc: Some(adc), | ||
| 227 | rtc: rtc, | ||
| 228 | #[cfg(any(rcc_f1, rcc_f1cl))] | ||
| 229 | usb: usb, | ||
| 230 | lse: None, | ||
| 231 | ); | ||
| 232 | } | ||
| 233 | |||
| 234 | mod max { | ||
| 235 | use core::ops::RangeInclusive; | ||
| 236 | |||
| 237 | use crate::time::Hertz; | ||
| 238 | |||
| 239 | #[cfg(not(rcc_f1cl))] | ||
| 240 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(16_000_000); | ||
| 241 | #[cfg(not(rcc_f1cl))] | ||
| 242 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(25_000_000); | ||
| 243 | |||
| 244 | #[cfg(rcc_f1cl)] | ||
| 245 | pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(3_000_000)..=Hertz(25_000_000); | ||
| 246 | #[cfg(rcc_f1cl)] | ||
| 247 | pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(50_000_000); | ||
| 248 | |||
| 249 | pub(crate) const HCLK: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000); | ||
| 250 | pub(crate) const PCLK1: RangeInclusive<Hertz> = Hertz(0)..=Hertz(36_000_000); | ||
| 251 | pub(crate) const PCLK2: RangeInclusive<Hertz> = Hertz(0)..=Hertz(72_000_000); | ||
| 252 | |||
| 253 | pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(25_000_000); | ||
| 254 | pub(crate) const PLL_OUT: RangeInclusive<Hertz> = Hertz(16_000_000)..=Hertz(72_000_000); | ||
| 255 | |||
| 256 | pub(crate) const ADC: RangeInclusive<Hertz> = Hertz(0)..=Hertz(14_000_000); | ||
| 257 | } | ||
diff --git a/embassy-stm32/src/rcc/f.rs b/embassy-stm32/src/rcc/f247.rs index e306d478d..e306d478d 100644 --- a/embassy-stm32/src/rcc/f.rs +++ b/embassy-stm32/src/rcc/f247.rs | |||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index b7eca0615..0f3467151 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -18,10 +18,8 @@ mod hsi48; | |||
| 18 | #[cfg(crs)] | 18 | #[cfg(crs)] |
| 19 | pub use hsi48::*; | 19 | pub use hsi48::*; |
| 20 | 20 | ||
| 21 | #[cfg_attr(stm32f0, path = "f0.rs")] | 21 | #[cfg_attr(any(stm32f0, stm32f1, stm32f3), path = "f013.rs")] |
| 22 | #[cfg_attr(stm32f1, path = "f1.rs")] | 22 | #[cfg_attr(any(stm32f2, stm32f4, stm32f7), path = "f247.rs")] |
| 23 | #[cfg_attr(stm32f3, path = "f3.rs")] | ||
| 24 | #[cfg_attr(any(stm32f2, stm32f4, stm32f7), path = "f.rs")] | ||
| 25 | #[cfg_attr(stm32c0, path = "c0.rs")] | 23 | #[cfg_attr(stm32c0, path = "c0.rs")] |
| 26 | #[cfg_attr(stm32g0, path = "g0.rs")] | 24 | #[cfg_attr(stm32g0, path = "g0.rs")] |
| 27 | #[cfg_attr(stm32g4, path = "g4.rs")] | 25 | #[cfg_attr(stm32g4, path = "g4.rs")] |
