diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-10-09 02:48:22 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-10-09 02:48:22 +0200 |
| commit | 6186fe08070c5f497d72586640db287193b41894 (patch) | |
| tree | aaef02d5344086bde66725a853851546961520fa | |
| parent | c4cff0b79bc54634db9d0fa24a24add49b7ec7fe (diff) | |
stm32/rcc: use PLL enums from PAC.
47 files changed, 599 insertions, 1383 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 18010fb9b..70e8f2e29 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -59,12 +59,11 @@ sdio-host = "0.5.0" | |||
| 59 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } | 59 | embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } |
| 60 | critical-section = "1.1" | 60 | critical-section = "1.1" |
| 61 | atomic-polyfill = "1.0.1" | 61 | atomic-polyfill = "1.0.1" |
| 62 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eecd80c34d4a3035be31404857e6c6e115376f41" } | 62 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026" } |
| 63 | vcell = "0.1.3" | 63 | vcell = "0.1.3" |
| 64 | bxcan = "0.7.0" | 64 | bxcan = "0.7.0" |
| 65 | nb = "1.0.0" | 65 | nb = "1.0.0" |
| 66 | stm32-fmc = "0.3.0" | 66 | stm32-fmc = "0.3.0" |
| 67 | seq-macro = "0.3.0" | ||
| 68 | cfg-if = "1.0.0" | 67 | cfg-if = "1.0.0" |
| 69 | embedded-io = { version = "0.6.0" } | 68 | embedded-io = { version = "0.6.0" } |
| 70 | embedded-io-async = { version = "0.6.0", optional = true } | 69 | embedded-io-async = { version = "0.6.0", optional = true } |
| @@ -78,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] } | |||
| 78 | [build-dependencies] | 77 | [build-dependencies] |
| 79 | proc-macro2 = "1.0.36" | 78 | proc-macro2 = "1.0.36" |
| 80 | quote = "1.0.15" | 79 | quote = "1.0.15" |
| 81 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eecd80c34d4a3035be31404857e6c6e115376f41", default-features = false, features = ["metadata"]} | 80 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e89b8cfc30e480036aaf502f34c874ee42d68026", default-features = false, features = ["metadata"]} |
| 82 | 81 | ||
| 83 | 82 | ||
| 84 | [features] | 83 | [features] |
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 3f85d9e61..643f1b6e9 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -894,6 +894,105 @@ fn main() { | |||
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | // ======== | 896 | // ======== |
| 897 | // Generate Div/Mul impls for RCC prescalers/dividers/multipliers. | ||
| 898 | let rcc_registers = METADATA | ||
| 899 | .peripherals | ||
| 900 | .iter() | ||
| 901 | .filter_map(|p| p.registers.as_ref()) | ||
| 902 | .find(|r| r.kind == "rcc") | ||
| 903 | .unwrap() | ||
| 904 | .ir; | ||
| 905 | |||
| 906 | for e in rcc_registers.enums { | ||
| 907 | fn is_rcc_name(e: &str) -> bool { | ||
| 908 | match e { | ||
| 909 | "Pllp" | "Pllq" | "Pllr" | "Pllm" | "Plln" => true, | ||
| 910 | "Timpre" | "Pllrclkpre" => false, | ||
| 911 | e if e.ends_with("pre") || e.ends_with("div") || e.ends_with("mul") => true, | ||
| 912 | _ => false, | ||
| 913 | } | ||
| 914 | } | ||
| 915 | |||
| 916 | #[derive(Copy, Clone, Debug)] | ||
| 917 | struct Frac { | ||
| 918 | num: u32, | ||
| 919 | denom: u32, | ||
| 920 | } | ||
| 921 | |||
| 922 | impl Frac { | ||
| 923 | fn simplify(self) -> Self { | ||
| 924 | let d = gcd(self.num, self.denom); | ||
| 925 | Self { | ||
| 926 | num: self.num / d, | ||
| 927 | denom: self.denom / d, | ||
| 928 | } | ||
| 929 | } | ||
| 930 | } | ||
| 931 | |||
| 932 | fn gcd(a: u32, b: u32) -> u32 { | ||
| 933 | if b == 0 { | ||
| 934 | return a; | ||
| 935 | } | ||
| 936 | gcd(b, a % b) | ||
| 937 | } | ||
| 938 | |||
| 939 | fn parse_num(n: &str) -> Result<Frac, ()> { | ||
| 940 | for prefix in ["DIV", "MUL"] { | ||
| 941 | if let Some(n) = n.strip_prefix(prefix) { | ||
| 942 | let exponent = n.find('_').map(|e| n.len() - 1 - e).unwrap_or(0) as u32; | ||
| 943 | let mantissa = n.replace('_', "").parse().map_err(|_| ())?; | ||
| 944 | let f = Frac { | ||
| 945 | num: mantissa, | ||
| 946 | denom: 10u32.pow(exponent), | ||
| 947 | }; | ||
| 948 | return Ok(f.simplify()); | ||
| 949 | } | ||
| 950 | } | ||
| 951 | Err(()) | ||
| 952 | } | ||
| 953 | |||
| 954 | if is_rcc_name(e.name) { | ||
| 955 | let enum_name = format_ident!("{}", e.name); | ||
| 956 | let mut muls = Vec::new(); | ||
| 957 | let mut divs = Vec::new(); | ||
| 958 | for v in e.variants { | ||
| 959 | let Ok(val) = parse_num(v.name) else { | ||
| 960 | panic!("could not parse mul/div. enum={} variant={}", e.name, v.name) | ||
| 961 | }; | ||
| 962 | let variant_name = format_ident!("{}", v.name); | ||
| 963 | let variant = quote!(crate::pac::rcc::vals::#enum_name::#variant_name); | ||
| 964 | let num = val.num; | ||
| 965 | let denom = val.denom; | ||
| 966 | muls.push(quote!(#variant => self * #num / #denom,)); | ||
| 967 | divs.push(quote!(#variant => self * #denom / #num,)); | ||
| 968 | } | ||
| 969 | |||
| 970 | g.extend(quote! { | ||
| 971 | impl core::ops::Div<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz { | ||
| 972 | type Output = crate::time::Hertz; | ||
| 973 | fn div(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { | ||
| 974 | match rhs { | ||
| 975 | #(#divs)* | ||
| 976 | #[allow(unreachable_patterns)] | ||
| 977 | _ => unreachable!(), | ||
| 978 | } | ||
| 979 | } | ||
| 980 | } | ||
| 981 | impl core::ops::Mul<crate::pac::rcc::vals::#enum_name> for crate::time::Hertz { | ||
| 982 | type Output = crate::time::Hertz; | ||
| 983 | fn mul(self, rhs: crate::pac::rcc::vals::#enum_name) -> Self::Output { | ||
| 984 | match rhs { | ||
| 985 | #(#muls)* | ||
| 986 | #[allow(unreachable_patterns)] | ||
| 987 | _ => unreachable!(), | ||
| 988 | } | ||
| 989 | } | ||
| 990 | } | ||
| 991 | }); | ||
| 992 | } | ||
| 993 | } | ||
| 994 | |||
| 995 | // ======== | ||
| 897 | // Write foreach_foo! macrotables | 996 | // Write foreach_foo! macrotables |
| 898 | 997 | ||
| 899 | let mut flash_regions_table: Vec<Vec<String>> = Vec::new(); | 998 | let mut flash_regions_table: Vec<Vec<String>> = Vec::new(); |
diff --git a/embassy-stm32/src/rcc/bus.rs b/embassy-stm32/src/rcc/bus.rs deleted file mode 100644 index 495cf7fe1..000000000 --- a/embassy-stm32/src/rcc/bus.rs +++ /dev/null | |||
| @@ -1,56 +0,0 @@ | |||
| 1 | use core::ops::Div; | ||
| 2 | |||
| 3 | #[allow(unused_imports)] | ||
| 4 | use crate::pac::rcc; | ||
| 5 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; | ||
| 6 | use crate::time::Hertz; | ||
| 7 | |||
| 8 | impl Div<AHBPrescaler> for Hertz { | ||
| 9 | type Output = Hertz; | ||
| 10 | |||
| 11 | fn div(self, rhs: AHBPrescaler) -> Self::Output { | ||
| 12 | let divisor = match rhs { | ||
| 13 | AHBPrescaler::DIV1 => 1, | ||
| 14 | AHBPrescaler::DIV2 => 2, | ||
| 15 | #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] | ||
| 16 | AHBPrescaler::DIV3 => 3, | ||
| 17 | AHBPrescaler::DIV4 => 4, | ||
| 18 | #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] | ||
| 19 | AHBPrescaler::DIV5 => 5, | ||
| 20 | #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] | ||
| 21 | AHBPrescaler::DIV6 => 6, | ||
| 22 | AHBPrescaler::DIV8 => 8, | ||
| 23 | #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] | ||
| 24 | AHBPrescaler::DIV10 => 10, | ||
| 25 | AHBPrescaler::DIV16 => 16, | ||
| 26 | #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] | ||
| 27 | AHBPrescaler::DIV32 => 32, | ||
| 28 | #[cfg(not(rcc_wba))] | ||
| 29 | AHBPrescaler::DIV64 => 64, | ||
| 30 | #[cfg(not(rcc_wba))] | ||
| 31 | AHBPrescaler::DIV128 => 128, | ||
| 32 | #[cfg(not(rcc_wba))] | ||
| 33 | AHBPrescaler::DIV256 => 256, | ||
| 34 | #[cfg(not(rcc_wba))] | ||
| 35 | AHBPrescaler::DIV512 => 512, | ||
| 36 | _ => unreachable!(), | ||
| 37 | }; | ||
| 38 | Hertz(self.0 / divisor) | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | impl Div<APBPrescaler> for Hertz { | ||
| 43 | type Output = Hertz; | ||
| 44 | |||
| 45 | fn div(self, rhs: APBPrescaler) -> Self::Output { | ||
| 46 | let divisor = match rhs { | ||
| 47 | APBPrescaler::DIV1 => 1, | ||
| 48 | APBPrescaler::DIV2 => 2, | ||
| 49 | APBPrescaler::DIV4 => 4, | ||
| 50 | APBPrescaler::DIV8 => 8, | ||
| 51 | APBPrescaler::DIV16 => 16, | ||
| 52 | _ => unreachable!(), | ||
| 53 | }; | ||
| 54 | Hertz(self.0 / divisor) | ||
| 55 | } | ||
| 56 | } | ||
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index 8f45e7c0f..efa56de7b 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | ||
| 2 | use crate::pac::flash::vals::Latency; | 1 | use crate::pac::flash::vals::Latency; |
| 2 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; | ||
| 3 | use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; | 3 | use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; |
| 4 | use crate::pac::{FLASH, RCC}; | 4 | use crate::pac::{FLASH, RCC}; |
| 5 | use crate::rcc::{set_freqs, Clocks}; | 5 | use crate::rcc::{set_freqs, Clocks}; |
diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index 44de5bf19..07b816bf5 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | use core::convert::TryFrom; | ||
| 2 | use core::ops::{Div, Mul}; | ||
| 3 | |||
| 4 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | ||
| 5 | use crate::pac::flash::vals::Latency; | 1 | use crate::pac::flash::vals::Latency; |
| 6 | use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw}; | 2 | use crate::pac::rcc::vals::Sw; |
| 3 | pub use crate::pac::rcc::vals::{ | ||
| 4 | Hpre as AHBPrescaler, Pllm as PLLPreDiv, Plln as PLLMul, Pllp as PLLPDiv, Pllq as PLLQDiv, Pllsrc as PLLSrc, | ||
| 5 | Ppre as APBPrescaler, | ||
| 6 | }; | ||
| 7 | use crate::pac::{FLASH, RCC}; | 7 | use crate::pac::{FLASH, RCC}; |
| 8 | use crate::rcc::bd::BackupDomain; | 8 | use crate::rcc::bd::BackupDomain; |
| 9 | use crate::rcc::{set_freqs, Clocks}; | 9 | use crate::rcc::{set_freqs, Clocks}; |
| @@ -43,17 +43,17 @@ pub enum HSESrc { | |||
| 43 | pub struct PLLConfig { | 43 | pub struct PLLConfig { |
| 44 | pub pre_div: PLLPreDiv, | 44 | pub pre_div: PLLPreDiv, |
| 45 | pub mul: PLLMul, | 45 | pub mul: PLLMul, |
| 46 | pub main_div: PLLMainDiv, | 46 | pub p_div: PLLPDiv, |
| 47 | pub pll48_div: PLL48Div, | 47 | pub q_div: PLLQDiv, |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | impl Default for PLLConfig { | 50 | impl Default for PLLConfig { |
| 51 | fn default() -> Self { | 51 | fn default() -> Self { |
| 52 | PLLConfig { | 52 | PLLConfig { |
| 53 | pre_div: PLLPreDiv(16), | 53 | pre_div: PLLPreDiv::DIV16, |
| 54 | mul: PLLMul(192), | 54 | mul: PLLMul::MUL192, |
| 55 | main_div: PLLMainDiv::Div2, | 55 | p_div: PLLPDiv::DIV2, |
| 56 | pll48_div: PLL48Div(4), | 56 | q_div: PLLQDiv::DIV4, |
| 57 | } | 57 | } |
| 58 | } | 58 | } |
| 59 | } | 59 | } |
| @@ -61,9 +61,9 @@ impl Default for PLLConfig { | |||
| 61 | impl PLLConfig { | 61 | impl PLLConfig { |
| 62 | pub fn clocks(&self, src_freq: Hertz) -> PLLClocks { | 62 | pub fn clocks(&self, src_freq: Hertz) -> PLLClocks { |
| 63 | let in_freq = src_freq / self.pre_div; | 63 | let in_freq = src_freq / self.pre_div; |
| 64 | let vco_freq = Hertz((src_freq.0 as u64 * self.mul.0 as u64 / self.pre_div.0 as u64) as u32); | 64 | let vco_freq = src_freq / self.pre_div * self.mul; |
| 65 | let main_freq = vco_freq / self.main_div; | 65 | let main_freq = vco_freq / self.p_div; |
| 66 | let pll48_freq = vco_freq / self.pll48_div; | 66 | let pll48_freq = vco_freq / self.q_div; |
| 67 | PLLClocks { | 67 | PLLClocks { |
| 68 | in_freq, | 68 | in_freq, |
| 69 | vco_freq, | 69 | vco_freq, |
| @@ -72,129 +72,6 @@ impl PLLConfig { | |||
| 72 | } | 72 | } |
| 73 | } | 73 | } |
| 74 | } | 74 | } |
| 75 | |||
| 76 | /// Clock source for both main PLL and PLLI2S | ||
| 77 | #[derive(Clone, Copy, PartialEq)] | ||
| 78 | pub enum PLLSrc { | ||
| 79 | HSE, | ||
| 80 | HSI, | ||
| 81 | } | ||
| 82 | |||
| 83 | impl Into<Pllsrc> for PLLSrc { | ||
| 84 | fn into(self) -> Pllsrc { | ||
| 85 | match self { | ||
| 86 | PLLSrc::HSE => Pllsrc::HSE, | ||
| 87 | PLLSrc::HSI => Pllsrc::HSI, | ||
| 88 | } | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Division factor for both main PLL and PLLI2S | ||
| 93 | #[derive(Clone, Copy, PartialEq)] | ||
| 94 | #[repr(transparent)] | ||
| 95 | pub struct PLLPreDiv(u8); | ||
| 96 | |||
| 97 | impl TryFrom<u8> for PLLPreDiv { | ||
| 98 | type Error = &'static str; | ||
| 99 | |||
| 100 | fn try_from(value: u8) -> Result<Self, Self::Error> { | ||
| 101 | match value { | ||
| 102 | 2..=63 => Ok(PLLPreDiv(value)), | ||
| 103 | _ => Err("PLLPreDiv must be within range 2..=63"), | ||
| 104 | } | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | impl Div<PLLPreDiv> for Hertz { | ||
| 109 | type Output = Hertz; | ||
| 110 | |||
| 111 | fn div(self, rhs: PLLPreDiv) -> Self::Output { | ||
| 112 | Hertz(self.0 / u32::from(rhs.0)) | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | /// Multiplication factor for main PLL | ||
| 117 | #[derive(Clone, Copy, PartialEq)] | ||
| 118 | #[repr(transparent)] | ||
| 119 | pub struct PLLMul(u16); | ||
| 120 | |||
| 121 | impl Mul<PLLMul> for Hertz { | ||
| 122 | type Output = Hertz; | ||
| 123 | |||
| 124 | fn mul(self, rhs: PLLMul) -> Self::Output { | ||
| 125 | Hertz(self.0 * u32::from(rhs.0)) | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | impl TryFrom<u16> for PLLMul { | ||
| 130 | type Error = &'static str; | ||
| 131 | |||
| 132 | fn try_from(value: u16) -> Result<Self, Self::Error> { | ||
| 133 | match value { | ||
| 134 | 192..=432 => Ok(PLLMul(value)), | ||
| 135 | _ => Err("PLLMul must be within range 192..=432"), | ||
| 136 | } | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | /// PLL division factor for the main system clock | ||
| 141 | #[derive(Clone, Copy, PartialEq)] | ||
| 142 | pub enum PLLMainDiv { | ||
| 143 | Div2, | ||
| 144 | Div4, | ||
| 145 | Div6, | ||
| 146 | Div8, | ||
| 147 | } | ||
| 148 | |||
| 149 | impl Into<Pllp> for PLLMainDiv { | ||
| 150 | fn into(self) -> Pllp { | ||
| 151 | match self { | ||
| 152 | PLLMainDiv::Div2 => Pllp::DIV2, | ||
| 153 | PLLMainDiv::Div4 => Pllp::DIV4, | ||
| 154 | PLLMainDiv::Div6 => Pllp::DIV6, | ||
| 155 | PLLMainDiv::Div8 => Pllp::DIV8, | ||
| 156 | } | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | impl Div<PLLMainDiv> for Hertz { | ||
| 161 | type Output = Hertz; | ||
| 162 | |||
| 163 | fn div(self, rhs: PLLMainDiv) -> Self::Output { | ||
| 164 | let divisor = match rhs { | ||
| 165 | PLLMainDiv::Div2 => 2, | ||
| 166 | PLLMainDiv::Div4 => 4, | ||
| 167 | PLLMainDiv::Div6 => 6, | ||
| 168 | PLLMainDiv::Div8 => 8, | ||
| 169 | }; | ||
| 170 | Hertz(self.0 / divisor) | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | /// PLL division factor for USB OTG FS / SDIO / RNG | ||
| 175 | #[derive(Clone, Copy, PartialEq)] | ||
| 176 | #[repr(transparent)] | ||
| 177 | pub struct PLL48Div(u8); | ||
| 178 | |||
| 179 | impl Div<PLL48Div> for Hertz { | ||
| 180 | type Output = Hertz; | ||
| 181 | |||
| 182 | fn div(self, rhs: PLL48Div) -> Self::Output { | ||
| 183 | Hertz(self.0 / u32::from(rhs.0)) | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | impl TryFrom<u8> for PLL48Div { | ||
| 188 | type Error = &'static str; | ||
| 189 | |||
| 190 | fn try_from(value: u8) -> Result<Self, Self::Error> { | ||
| 191 | match value { | ||
| 192 | 2..=15 => Ok(PLL48Div(value)), | ||
| 193 | _ => Err("PLL48Div must be within range 2..=15"), | ||
| 194 | } | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | #[derive(Clone, Copy, PartialEq)] | 75 | #[derive(Clone, Copy, PartialEq)] |
| 199 | pub struct PLLClocks { | 76 | pub struct PLLClocks { |
| 200 | pub in_freq: Hertz, | 77 | pub in_freq: Hertz, |
| @@ -367,11 +244,11 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 367 | assert!(pll_clocks.pll48_freq <= Hertz(48_000_000)); | 244 | assert!(pll_clocks.pll48_freq <= Hertz(48_000_000)); |
| 368 | 245 | ||
| 369 | RCC.pllcfgr().write(|w| { | 246 | RCC.pllcfgr().write(|w| { |
| 370 | w.set_pllsrc(config.pll_mux.into()); | 247 | w.set_pllsrc(config.pll_mux); |
| 371 | w.set_pllm(config.pll.pre_div.0); | 248 | w.set_pllm(config.pll.pre_div); |
| 372 | w.set_plln(config.pll.mul.0); | 249 | w.set_plln(config.pll.mul); |
| 373 | w.set_pllp(config.pll.main_div.into()); | 250 | w.set_pllp(config.pll.p_div); |
| 374 | w.set_pllq(config.pll.pll48_div.0); | 251 | w.set_pllq(config.pll.q_div); |
| 375 | }); | 252 | }); |
| 376 | 253 | ||
| 377 | let (sys_clk, sw) = match config.mux { | 254 | let (sys_clk, sw) = match config.mux { |
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index ad106ce38..754a0d570 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs | |||
| @@ -1,3 +1,5 @@ | |||
| 1 | use stm32_metapac::rcc::vals::{Pllm, Plln, Pllq, Pllr}; | ||
| 2 | |||
| 1 | use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; | 3 | use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; |
| 2 | use crate::pac::{FLASH, PWR, RCC}; | 4 | use crate::pac::{FLASH, PWR, RCC}; |
| 3 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; | 5 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; |
| @@ -170,12 +172,12 @@ fn setup_pll( | |||
| 170 | let real_pll48clk = vco_in * plln / pllq; | 172 | let real_pll48clk = vco_in * plln / pllq; |
| 171 | 173 | ||
| 172 | RCC.pllcfgr().modify(|w| { | 174 | RCC.pllcfgr().modify(|w| { |
| 173 | w.set_pllm(pllm as u8); | 175 | w.set_pllm(Pllm::from_bits(pllm as u8)); |
| 174 | w.set_plln(plln as u16); | 176 | w.set_plln(Plln::from_bits(plln as u16)); |
| 175 | w.set_pllp(Pllp::from_bits(pllp as u8)); | 177 | w.set_pllp(Pllp::from_bits(pllp as u8)); |
| 176 | w.set_pllq(pllq as u8); | 178 | w.set_pllq(Pllq::from_bits(pllq as u8)); |
| 177 | w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); | 179 | w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); |
| 178 | w.set_pllr(0); | 180 | w.set_pllr(Pllr::from_bits(0)); |
| 179 | }); | 181 | }); |
| 180 | 182 | ||
| 181 | let real_pllsysclk = vco_in * plln / sysclk_div; | 183 | let real_pllsysclk = vco_in * plln / sysclk_div; |
diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs index f32559e26..565f6aa9f 100644 --- a/embassy-stm32/src/rcc/f7.rs +++ b/embassy-stm32/src/rcc/f7.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | use crate::pac::pwr::vals::Vos; | 1 | use crate::pac::pwr::vals::Vos; |
| 2 | use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; | 2 | use crate::pac::rcc::vals::{Hpre, Pllm, Plln, Pllp, Pllq, Pllsrc, Ppre, Sw}; |
| 3 | use crate::pac::{FLASH, PWR, RCC}; | 3 | use crate::pac::{FLASH, PWR, RCC}; |
| 4 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; | 4 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; |
| 5 | use crate::rcc::{set_freqs, Clocks}; | 5 | use crate::rcc::{set_freqs, Clocks}; |
| @@ -29,8 +29,6 @@ pub struct Config { | |||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults { | 31 | fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults { |
| 32 | use crate::pac::rcc::vals::{Pllp, Pllsrc}; | ||
| 33 | |||
| 34 | let sysclk = pllsysclk.unwrap_or(pllsrcclk); | 32 | let sysclk = pllsysclk.unwrap_or(pllsrcclk); |
| 35 | if pllsysclk.is_none() && !pll48clk { | 33 | if pllsysclk.is_none() && !pll48clk { |
| 36 | RCC.pllcfgr().modify(|w| w.set_pllsrc(Pllsrc::from_bits(use_hse as u8))); | 34 | RCC.pllcfgr().modify(|w| w.set_pllsrc(Pllsrc::from_bits(use_hse as u8))); |
| @@ -84,10 +82,10 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bo | |||
| 84 | let real_pll48clk = vco_in * plln / pllq; | 82 | let real_pll48clk = vco_in * plln / pllq; |
| 85 | 83 | ||
| 86 | RCC.pllcfgr().modify(|w| { | 84 | RCC.pllcfgr().modify(|w| { |
| 87 | w.set_pllm(pllm as u8); | 85 | w.set_pllm(Pllm::from_bits(pllm as u8)); |
| 88 | w.set_plln(plln as u16); | 86 | w.set_plln(Plln::from_bits(plln as u16)); |
| 89 | w.set_pllp(Pllp::from_bits(pllp as u8)); | 87 | w.set_pllp(Pllp::from_bits(pllp as u8)); |
| 90 | w.set_pllq(pllq as u8); | 88 | w.set_pllq(Pllq::from_bits(pllq as u8)); |
| 91 | w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); | 89 | w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); |
| 92 | }); | 90 | }); |
| 93 | 91 | ||
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 7f0a2c7fb..5ac409113 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | ||
| 2 | use crate::pac::flash::vals::Latency; | 1 | use crate::pac::flash::vals::Latency; |
| 3 | use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw}; | 2 | use crate::pac::rcc::vals::{self, Hsidiv, Sw}; |
| 3 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Ppre as APBPrescaler}; | ||
| 4 | use crate::pac::{FLASH, PWR, RCC}; | 4 | use crate::pac::{FLASH, PWR, RCC}; |
| 5 | use crate::rcc::{set_freqs, Clocks}; | 5 | use crate::rcc::{set_freqs, Clocks}; |
| 6 | use crate::time::Hertz; | 6 | use crate::time::Hertz; |
| @@ -60,15 +60,15 @@ pub struct PllConfig { | |||
| 60 | /// The initial divisor of that clock signal | 60 | /// The initial divisor of that clock signal |
| 61 | pub m: Pllm, | 61 | pub m: Pllm, |
| 62 | /// The PLL VCO multiplier, which must be in the range `8..=86`. | 62 | /// The PLL VCO multiplier, which must be in the range `8..=86`. |
| 63 | pub n: u8, | 63 | pub n: Plln, |
| 64 | /// The final divisor for `PLLRCLK` output which drives the system clock | 64 | /// The final divisor for `PLLRCLK` output which drives the system clock |
| 65 | pub r: Pllr, | 65 | pub r: Pllr, |
| 66 | 66 | ||
| 67 | /// The divisor for the `PLLQCLK` output, if desired | 67 | /// The divisor for the `PLLQCLK` output, if desired |
| 68 | pub q: Option<Pllr>, | 68 | pub q: Option<Pllq>, |
| 69 | 69 | ||
| 70 | /// The divisor for the `PLLPCLK` output, if desired | 70 | /// The divisor for the `PLLPCLK` output, if desired |
| 71 | pub p: Option<Pllr>, | 71 | pub p: Option<Pllp>, |
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | impl Default for PllConfig { | 74 | impl Default for PllConfig { |
| @@ -77,9 +77,9 @@ impl Default for PllConfig { | |||
| 77 | // HSI16 / 1 * 8 / 2 = 64 MHz | 77 | // HSI16 / 1 * 8 / 2 = 64 MHz |
| 78 | PllConfig { | 78 | PllConfig { |
| 79 | source: PllSrc::HSI16, | 79 | source: PllSrc::HSI16, |
| 80 | m: Pllm::Div1, | 80 | m: Pllm::DIV1, |
| 81 | n: 8, | 81 | n: Plln::MUL8, |
| 82 | r: Pllr::Div2, | 82 | r: Pllr::DIV2, |
| 83 | q: None, | 83 | q: None, |
| 84 | p: None, | 84 | p: None, |
| 85 | } | 85 | } |
| @@ -92,87 +92,6 @@ pub enum PllSrc { | |||
| 92 | HSE(Hertz), | 92 | HSE(Hertz), |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | #[derive(Clone, Copy)] | ||
| 96 | pub enum Pllm { | ||
| 97 | Div1, | ||
| 98 | Div2, | ||
| 99 | Div3, | ||
| 100 | Div4, | ||
| 101 | Div5, | ||
| 102 | Div6, | ||
| 103 | Div7, | ||
| 104 | Div8, | ||
| 105 | } | ||
| 106 | |||
| 107 | impl From<Pllm> for u8 { | ||
| 108 | fn from(v: Pllm) -> Self { | ||
| 109 | match v { | ||
| 110 | Pllm::Div1 => 0b000, | ||
| 111 | Pllm::Div2 => 0b001, | ||
| 112 | Pllm::Div3 => 0b010, | ||
| 113 | Pllm::Div4 => 0b011, | ||
| 114 | Pllm::Div5 => 0b100, | ||
| 115 | Pllm::Div6 => 0b101, | ||
| 116 | Pllm::Div7 => 0b110, | ||
| 117 | Pllm::Div8 => 0b111, | ||
| 118 | } | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | impl From<Pllm> for u32 { | ||
| 123 | fn from(v: Pllm) -> Self { | ||
| 124 | match v { | ||
| 125 | Pllm::Div1 => 1, | ||
| 126 | Pllm::Div2 => 2, | ||
| 127 | Pllm::Div3 => 3, | ||
| 128 | Pllm::Div4 => 4, | ||
| 129 | Pllm::Div5 => 5, | ||
| 130 | Pllm::Div6 => 6, | ||
| 131 | Pllm::Div7 => 7, | ||
| 132 | Pllm::Div8 => 8, | ||
| 133 | } | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | #[derive(Clone, Copy)] | ||
| 138 | pub enum Pllr { | ||
| 139 | Div2, | ||
| 140 | Div3, | ||
| 141 | Div4, | ||
| 142 | Div5, | ||
| 143 | Div6, | ||
| 144 | Div7, | ||
| 145 | Div8, | ||
| 146 | } | ||
| 147 | |||
| 148 | impl From<Pllr> for u8 { | ||
| 149 | fn from(v: Pllr) -> Self { | ||
| 150 | match v { | ||
| 151 | Pllr::Div2 => 0b000, | ||
| 152 | Pllr::Div3 => 0b001, | ||
| 153 | Pllr::Div4 => 0b010, | ||
| 154 | Pllr::Div5 => 0b011, | ||
| 155 | Pllr::Div6 => 0b101, | ||
| 156 | Pllr::Div7 => 0b110, | ||
| 157 | Pllr::Div8 => 0b111, | ||
| 158 | } | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | impl From<Pllr> for u32 { | ||
| 163 | fn from(v: Pllr) -> Self { | ||
| 164 | match v { | ||
| 165 | Pllr::Div2 => 2, | ||
| 166 | Pllr::Div3 => 3, | ||
| 167 | Pllr::Div4 => 4, | ||
| 168 | Pllr::Div5 => 5, | ||
| 169 | Pllr::Div6 => 6, | ||
| 170 | Pllr::Div7 => 7, | ||
| 171 | Pllr::Div8 => 8, | ||
| 172 | } | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 176 | /// Clocks configutation | 95 | /// Clocks configutation |
| 177 | pub struct Config { | 96 | pub struct Config { |
| 178 | pub mux: ClockSrc, | 97 | pub mux: ClockSrc, |
| @@ -194,29 +113,28 @@ impl Default for Config { | |||
| 194 | } | 113 | } |
| 195 | 114 | ||
| 196 | impl PllConfig { | 115 | impl PllConfig { |
| 197 | pub(crate) fn init(self) -> u32 { | 116 | pub(crate) fn init(self) -> Hertz { |
| 198 | assert!(self.n >= 8 && self.n <= 86); | ||
| 199 | let (src, input_freq) = match self.source { | 117 | let (src, input_freq) = match self.source { |
| 200 | PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ.0), | 118 | PllSrc::HSI16 => (vals::Pllsrc::HSI16, HSI_FREQ), |
| 201 | PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq.0), | 119 | PllSrc::HSE(freq) => (vals::Pllsrc::HSE, freq), |
| 202 | }; | 120 | }; |
| 203 | 121 | ||
| 204 | let m_freq = input_freq / u32::from(self.m); | 122 | let m_freq = input_freq / self.m; |
| 205 | // RM0454 § 5.4.4: | 123 | // RM0454 § 5.4.4: |
| 206 | // > Caution: The software must set these bits so that the PLL input frequency after the | 124 | // > Caution: The software must set these bits so that the PLL input frequency after the |
| 207 | // > /M divider is between 2.66 and 16 MHz. | 125 | // > /M divider is between 2.66 and 16 MHz. |
| 208 | debug_assert!(m_freq >= 2_660_000 && m_freq <= 16_000_000); | 126 | debug_assert!(m_freq.0 >= 2_660_000 && m_freq.0 <= 16_000_000); |
| 209 | 127 | ||
| 210 | let n_freq = m_freq * self.n as u32; | 128 | let n_freq = m_freq * self.n as u32; |
| 211 | // RM0454 § 5.4.4: | 129 | // RM0454 § 5.4.4: |
| 212 | // > Caution: The software must set these bits so that the VCO output frequency is between | 130 | // > Caution: The software must set these bits so that the VCO output frequency is between |
| 213 | // > 64 and 344 MHz. | 131 | // > 64 and 344 MHz. |
| 214 | debug_assert!(n_freq >= 64_000_000 && n_freq <= 344_000_000); | 132 | debug_assert!(n_freq.0 >= 64_000_000 && n_freq.0 <= 344_000_000); |
| 215 | 133 | ||
| 216 | let r_freq = n_freq / u32::from(self.r); | 134 | let r_freq = n_freq / self.r; |
| 217 | // RM0454 § 5.4.4: | 135 | // RM0454 § 5.4.4: |
| 218 | // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock. | 136 | // > Caution: The software must set this bitfield so as not to exceed 64 MHz on this clock. |
| 219 | debug_assert!(r_freq <= 64_000_000); | 137 | debug_assert!(r_freq.0 <= 64_000_000); |
| 220 | 138 | ||
| 221 | // RM0454 § 5.2.3: | 139 | // RM0454 § 5.2.3: |
| 222 | // > To modify the PLL configuration, proceed as follows: | 140 | // > To modify the PLL configuration, proceed as follows: |
| @@ -239,25 +157,16 @@ impl PllConfig { | |||
| 239 | } | 157 | } |
| 240 | } | 158 | } |
| 241 | 159 | ||
| 242 | // Configure PLLSYSCFGR | 160 | // Configure PLLCFGR |
| 243 | RCC.pllsyscfgr().modify(|w| { | 161 | RCC.pllcfgr().modify(|w| { |
| 244 | w.set_pllr(u8::from(self.r)); | 162 | w.set_pllr(self.r); |
| 245 | w.set_pllren(false); | 163 | w.set_pllren(false); |
| 246 | 164 | w.set_pllq(self.q.unwrap_or(Pllq::DIV2)); | |
| 247 | if let Some(q) = self.q { | ||
| 248 | w.set_pllq(u8::from(q)); | ||
| 249 | } | ||
| 250 | w.set_pllqen(false); | 165 | w.set_pllqen(false); |
| 251 | 166 | w.set_pllp(self.p.unwrap_or(Pllp::DIV2)); | |
| 252 | if let Some(p) = self.p { | ||
| 253 | w.set_pllp(u8::from(p)); | ||
| 254 | } | ||
| 255 | w.set_pllpen(false); | 167 | w.set_pllpen(false); |
| 256 | |||
| 257 | w.set_plln(self.n); | 168 | w.set_plln(self.n); |
| 258 | 169 | w.set_pllm(self.m); | |
| 259 | w.set_pllm(self.m as u8); | ||
| 260 | |||
| 261 | w.set_pllsrc(src) | 170 | w.set_pllsrc(src) |
| 262 | }); | 171 | }); |
| 263 | 172 | ||
| @@ -269,7 +178,7 @@ impl PllConfig { | |||
| 269 | 178 | ||
| 270 | // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL | 179 | // > 5. Enable the desired PLL outputs by configuring PLLPEN, PLLQEN, and PLLREN in PLL |
| 271 | // > configuration register (RCC_PLLCFGR). | 180 | // > configuration register (RCC_PLLCFGR). |
| 272 | RCC.pllsyscfgr().modify(|w| { | 181 | RCC.pllcfgr().modify(|w| { |
| 273 | // We'll use R for system clock, so enable that unconditionally | 182 | // We'll use R for system clock, so enable that unconditionally |
| 274 | w.set_pllren(true); | 183 | w.set_pllren(true); |
| 275 | 184 | ||
| @@ -293,14 +202,14 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 293 | }); | 202 | }); |
| 294 | while !RCC.cr().read().hsirdy() {} | 203 | while !RCC.cr().read().hsirdy() {} |
| 295 | 204 | ||
| 296 | (HSI_FREQ.0 >> div.to_bits(), Sw::HSI) | 205 | (HSI_FREQ / div, Sw::HSI) |
| 297 | } | 206 | } |
| 298 | ClockSrc::HSE(freq) => { | 207 | ClockSrc::HSE(freq) => { |
| 299 | // Enable HSE | 208 | // Enable HSE |
| 300 | RCC.cr().write(|w| w.set_hseon(true)); | 209 | RCC.cr().write(|w| w.set_hseon(true)); |
| 301 | while !RCC.cr().read().hserdy() {} | 210 | while !RCC.cr().read().hserdy() {} |
| 302 | 211 | ||
| 303 | (freq.0, Sw::HSE) | 212 | (freq, Sw::HSE) |
| 304 | } | 213 | } |
| 305 | ClockSrc::PLL(pll) => { | 214 | ClockSrc::PLL(pll) => { |
| 306 | let freq = pll.init(); | 215 | let freq = pll.init(); |
| @@ -310,15 +219,15 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 310 | // Enable LSI | 219 | // Enable LSI |
| 311 | RCC.csr().write(|w| w.set_lsion(true)); | 220 | RCC.csr().write(|w| w.set_lsion(true)); |
| 312 | while !RCC.csr().read().lsirdy() {} | 221 | while !RCC.csr().read().lsirdy() {} |
| 313 | (LSI_FREQ.0, Sw::LSI) | 222 | (LSI_FREQ, Sw::LSI) |
| 314 | } | 223 | } |
| 315 | }; | 224 | }; |
| 316 | 225 | ||
| 317 | // Determine the flash latency implied by the target clock speed | 226 | // Determine the flash latency implied by the target clock speed |
| 318 | // RM0454 § 3.3.4: | 227 | // RM0454 § 3.3.4: |
| 319 | let target_flash_latency = if sys_clk <= 24_000_000 { | 228 | let target_flash_latency = if sys_clk.0 <= 24_000_000 { |
| 320 | Latency::WS0 | 229 | Latency::WS0 |
| 321 | } else if sys_clk <= 48_000_000 { | 230 | } else if sys_clk.0 <= 48_000_000 { |
| 322 | Latency::WS1 | 231 | Latency::WS1 |
| 323 | } else { | 232 | } else { |
| 324 | Latency::WS2 | 233 | Latency::WS2 |
| @@ -374,27 +283,25 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 374 | FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); | 283 | FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); |
| 375 | } | 284 | } |
| 376 | 285 | ||
| 377 | let ahb_freq = Hertz(sys_clk) / config.ahb_pre; | 286 | let ahb_freq = sys_clk / config.ahb_pre; |
| 378 | 287 | ||
| 379 | let (apb_freq, apb_tim_freq) = match config.apb_pre { | 288 | let (apb_freq, apb_tim_freq) = match config.apb_pre { |
| 380 | APBPrescaler::DIV1 => (ahb_freq.0, ahb_freq.0), | 289 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 381 | pre => { | 290 | pre => { |
| 382 | let pre: Ppre = pre.into(); | 291 | let freq = ahb_freq / pre; |
| 383 | let pre: u8 = 1 << (pre.to_bits() - 3); | 292 | (freq, freq * 2u32) |
| 384 | let freq = ahb_freq.0 / pre as u32; | ||
| 385 | (freq, freq * 2) | ||
| 386 | } | 293 | } |
| 387 | }; | 294 | }; |
| 388 | 295 | ||
| 389 | if config.low_power_run { | 296 | if config.low_power_run { |
| 390 | assert!(sys_clk <= 2_000_000); | 297 | assert!(sys_clk.0 <= 2_000_000); |
| 391 | PWR.cr1().modify(|w| w.set_lpr(true)); | 298 | PWR.cr1().modify(|w| w.set_lpr(true)); |
| 392 | } | 299 | } |
| 393 | 300 | ||
| 394 | set_freqs(Clocks { | 301 | set_freqs(Clocks { |
| 395 | sys: Hertz(sys_clk), | 302 | sys: sys_clk, |
| 396 | ahb1: ahb_freq, | 303 | ahb1: ahb_freq, |
| 397 | apb1: Hertz(apb_freq), | 304 | apb1: apb_freq, |
| 398 | apb1_tim: Hertz(apb_tim_freq), | 305 | apb1_tim: apb_tim_freq, |
| 399 | }); | 306 | }); |
| 400 | } | 307 | } |
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 41bebc918..08ccc5fe9 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs | |||
| @@ -2,7 +2,9 @@ use stm32_metapac::flash::vals::Latency; | |||
| 2 | use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw}; | 2 | use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw}; |
| 3 | use stm32_metapac::FLASH; | 3 | use stm32_metapac::FLASH; |
| 4 | 4 | ||
| 5 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | 5 | pub use crate::pac::rcc::vals::{ |
| 6 | Hpre as AHBPrescaler, Pllm as PllM, Plln as PllN, Pllp as PllP, Pllq as PllQ, Pllr as PllR, Ppre as APBPrescaler, | ||
| 7 | }; | ||
| 6 | use crate::pac::{PWR, RCC}; | 8 | use crate::pac::{PWR, RCC}; |
| 7 | use crate::rcc::sealed::RccPeripheral; | 9 | use crate::rcc::sealed::RccPeripheral; |
| 8 | use crate::rcc::{set_freqs, Clocks}; | 10 | use crate::rcc::{set_freqs, Clocks}; |
| @@ -61,181 +63,6 @@ impl Into<Pllsrc> for PllSrc { | |||
| 61 | } | 63 | } |
| 62 | } | 64 | } |
| 63 | 65 | ||
| 64 | seq_macro::seq!(P in 2..=31 { | ||
| 65 | /// Output divider for the PLL P output. | ||
| 66 | #[derive(Clone, Copy)] | ||
| 67 | pub enum PllP { | ||
| 68 | // Note: If PLL P is set to 0 the PLLP bit controls the output division. There does not seem to | ||
| 69 | // a good reason to do this so the API does not support it. | ||
| 70 | // Div1 is invalid | ||
| 71 | #( | ||
| 72 | Div~P, | ||
| 73 | )* | ||
| 74 | } | ||
| 75 | |||
| 76 | impl From<PllP> for u8 { | ||
| 77 | /// Returns the register value for the P output divider. | ||
| 78 | fn from(val: PllP) -> u8 { | ||
| 79 | match val { | ||
| 80 | #( | ||
| 81 | PllP::Div~P => P, | ||
| 82 | )* | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | }); | ||
| 87 | |||
| 88 | impl PllP { | ||
| 89 | /// Returns the numeric value of the P output divider. | ||
| 90 | pub fn to_div(self) -> u32 { | ||
| 91 | let val: u8 = self.into(); | ||
| 92 | val as u32 | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | /// Output divider for the PLL Q output. | ||
| 97 | #[derive(Clone, Copy)] | ||
| 98 | pub enum PllQ { | ||
| 99 | Div2, | ||
| 100 | Div4, | ||
| 101 | Div6, | ||
| 102 | Div8, | ||
| 103 | } | ||
| 104 | |||
| 105 | impl PllQ { | ||
| 106 | /// Returns the numeric value of the Q output divider. | ||
| 107 | pub fn to_div(self) -> u32 { | ||
| 108 | let val: u8 = self.into(); | ||
| 109 | (val as u32 + 1) * 2 | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | impl From<PllQ> for u8 { | ||
| 114 | /// Returns the register value for the Q output divider. | ||
| 115 | fn from(val: PllQ) -> u8 { | ||
| 116 | match val { | ||
| 117 | PllQ::Div2 => 0b00, | ||
| 118 | PllQ::Div4 => 0b01, | ||
| 119 | PllQ::Div6 => 0b10, | ||
| 120 | PllQ::Div8 => 0b11, | ||
| 121 | } | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | /// Output divider for the PLL R output. | ||
| 126 | #[derive(Clone, Copy)] | ||
| 127 | pub enum PllR { | ||
| 128 | Div2, | ||
| 129 | Div4, | ||
| 130 | Div6, | ||
| 131 | Div8, | ||
| 132 | } | ||
| 133 | |||
| 134 | impl PllR { | ||
| 135 | /// Returns the numeric value of the R output divider. | ||
| 136 | pub fn to_div(self) -> u32 { | ||
| 137 | let val: u8 = self.into(); | ||
| 138 | (val as u32 + 1) * 2 | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | impl From<PllR> for u8 { | ||
| 143 | /// Returns the register value for the R output divider. | ||
| 144 | fn from(val: PllR) -> u8 { | ||
| 145 | match val { | ||
| 146 | PllR::Div2 => 0b00, | ||
| 147 | PllR::Div4 => 0b01, | ||
| 148 | PllR::Div6 => 0b10, | ||
| 149 | PllR::Div8 => 0b11, | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | seq_macro::seq!(N in 8..=127 { | ||
| 155 | /// Multiplication factor for the PLL VCO input clock. | ||
| 156 | #[derive(Clone, Copy)] | ||
| 157 | pub enum PllN { | ||
| 158 | #( | ||
| 159 | Mul~N, | ||
| 160 | )* | ||
| 161 | } | ||
| 162 | |||
| 163 | impl From<PllN> for u8 { | ||
| 164 | /// Returns the register value for the N multiplication factor. | ||
| 165 | fn from(val: PllN) -> u8 { | ||
| 166 | match val { | ||
| 167 | #( | ||
| 168 | PllN::Mul~N => N, | ||
| 169 | )* | ||
| 170 | } | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | impl PllN { | ||
| 175 | /// Returns the numeric value of the N multiplication factor. | ||
| 176 | pub fn to_mul(self) -> u32 { | ||
| 177 | match self { | ||
| 178 | #( | ||
| 179 | PllN::Mul~N => N, | ||
| 180 | )* | ||
| 181 | } | ||
| 182 | } | ||
| 183 | } | ||
| 184 | }); | ||
| 185 | |||
| 186 | /// PLL Pre-division. This must be set such that the PLL input is between 2.66 MHz and 16 MHz. | ||
| 187 | #[derive(Copy, Clone)] | ||
| 188 | pub enum PllM { | ||
| 189 | Div1, | ||
| 190 | Div2, | ||
| 191 | Div3, | ||
| 192 | Div4, | ||
| 193 | Div5, | ||
| 194 | Div6, | ||
| 195 | Div7, | ||
| 196 | Div8, | ||
| 197 | Div9, | ||
| 198 | Div10, | ||
| 199 | Div11, | ||
| 200 | Div12, | ||
| 201 | Div13, | ||
| 202 | Div14, | ||
| 203 | Div15, | ||
| 204 | Div16, | ||
| 205 | } | ||
| 206 | |||
| 207 | impl PllM { | ||
| 208 | /// Returns the numeric value of the M pre-division. | ||
| 209 | pub fn to_div(self) -> u32 { | ||
| 210 | let val: u8 = self.into(); | ||
| 211 | val as u32 + 1 | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | impl From<PllM> for u8 { | ||
| 216 | /// Returns the register value for the M pre-division. | ||
| 217 | fn from(val: PllM) -> u8 { | ||
| 218 | match val { | ||
| 219 | PllM::Div1 => 0b0000, | ||
| 220 | PllM::Div2 => 0b0001, | ||
| 221 | PllM::Div3 => 0b0010, | ||
| 222 | PllM::Div4 => 0b0011, | ||
| 223 | PllM::Div5 => 0b0100, | ||
| 224 | PllM::Div6 => 0b0101, | ||
| 225 | PllM::Div7 => 0b0110, | ||
| 226 | PllM::Div8 => 0b0111, | ||
| 227 | PllM::Div9 => 0b1000, | ||
| 228 | PllM::Div10 => 0b1001, | ||
| 229 | PllM::Div11 => 0b1010, | ||
| 230 | PllM::Div12 => 0b1011, | ||
| 231 | PllM::Div13 => 0b1100, | ||
| 232 | PllM::Div14 => 0b1101, | ||
| 233 | PllM::Div15 => 0b1110, | ||
| 234 | PllM::Div16 => 0b1111, | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | /// PLL Configuration | 66 | /// PLL Configuration |
| 240 | /// | 67 | /// |
| 241 | /// Use this struct to configure the PLL source, input frequency, multiplication factor, and output | 68 | /// Use this struct to configure the PLL source, input frequency, multiplication factor, and output |
| @@ -360,12 +187,12 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 360 | RCC.cr().write(|w| w.set_hsion(true)); | 187 | RCC.cr().write(|w| w.set_hsion(true)); |
| 361 | while !RCC.cr().read().hsirdy() {} | 188 | while !RCC.cr().read().hsirdy() {} |
| 362 | 189 | ||
| 363 | HSI_FREQ.0 | 190 | HSI_FREQ |
| 364 | } | 191 | } |
| 365 | PllSrc::HSE(freq) => { | 192 | PllSrc::HSE(freq) => { |
| 366 | RCC.cr().write(|w| w.set_hseon(true)); | 193 | RCC.cr().write(|w| w.set_hseon(true)); |
| 367 | while !RCC.cr().read().hserdy() {} | 194 | while !RCC.cr().read().hserdy() {} |
| 368 | freq.0 | 195 | freq |
| 369 | } | 196 | } |
| 370 | }; | 197 | }; |
| 371 | 198 | ||
| @@ -373,7 +200,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 373 | RCC.cr().modify(|w| w.set_pllon(false)); | 200 | RCC.cr().modify(|w| w.set_pllon(false)); |
| 374 | while RCC.cr().read().pllrdy() {} | 201 | while RCC.cr().read().pllrdy() {} |
| 375 | 202 | ||
| 376 | let internal_freq = src_freq / pll_config.prediv_m.to_div() * pll_config.mul_n.to_mul(); | 203 | let internal_freq = src_freq / pll_config.prediv_m * pll_config.mul_n; |
| 377 | 204 | ||
| 378 | RCC.pllcfgr().write(|w| { | 205 | RCC.pllcfgr().write(|w| { |
| 379 | w.set_plln(pll_config.mul_n.into()); | 206 | w.set_plln(pll_config.mul_n.into()); |
| @@ -383,26 +210,26 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 383 | 210 | ||
| 384 | let pll_p_freq = pll_config.div_p.map(|div_p| { | 211 | let pll_p_freq = pll_config.div_p.map(|div_p| { |
| 385 | RCC.pllcfgr().modify(|w| { | 212 | RCC.pllcfgr().modify(|w| { |
| 386 | w.set_pllpdiv(div_p.into()); | 213 | w.set_pllp(div_p); |
| 387 | w.set_pllpen(true); | 214 | w.set_pllpen(true); |
| 388 | }); | 215 | }); |
| 389 | Hertz(internal_freq / div_p.to_div()) | 216 | internal_freq / div_p |
| 390 | }); | 217 | }); |
| 391 | 218 | ||
| 392 | let pll_q_freq = pll_config.div_q.map(|div_q| { | 219 | let pll_q_freq = pll_config.div_q.map(|div_q| { |
| 393 | RCC.pllcfgr().modify(|w| { | 220 | RCC.pllcfgr().modify(|w| { |
| 394 | w.set_pllq(div_q.into()); | 221 | w.set_pllq(div_q); |
| 395 | w.set_pllqen(true); | 222 | w.set_pllqen(true); |
| 396 | }); | 223 | }); |
| 397 | Hertz(internal_freq / div_q.to_div()) | 224 | internal_freq / div_q |
| 398 | }); | 225 | }); |
| 399 | 226 | ||
| 400 | let pll_r_freq = pll_config.div_r.map(|div_r| { | 227 | let pll_r_freq = pll_config.div_r.map(|div_r| { |
| 401 | RCC.pllcfgr().modify(|w| { | 228 | RCC.pllcfgr().modify(|w| { |
| 402 | w.set_pllr(div_r.into()); | 229 | w.set_pllr(div_r); |
| 403 | w.set_pllren(true); | 230 | w.set_pllren(true); |
| 404 | }); | 231 | }); |
| 405 | Hertz(internal_freq / div_r.to_div()) | 232 | internal_freq / div_r |
| 406 | }); | 233 | }); |
| 407 | 234 | ||
| 408 | // Enable the PLL | 235 | // Enable the PLL |
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 5f9cc1c8b..a11fd4737 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs | |||
| @@ -6,8 +6,8 @@ use crate::pac::pwr::vals::Vos; | |||
| 6 | pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; | 6 | pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; |
| 7 | #[cfg(stm32h7)] | 7 | #[cfg(stm32h7)] |
| 8 | pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; | 8 | pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; |
| 9 | pub use crate::pac::rcc::vals::Ckpersel as PerClockSource; | ||
| 10 | use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; | 9 | use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; |
| 10 | pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul}; | ||
| 11 | use crate::pac::{FLASH, PWR, RCC}; | 11 | use crate::pac::{FLASH, PWR, RCC}; |
| 12 | #[cfg(stm32h7)] | 12 | #[cfg(stm32h7)] |
| 13 | use crate::rcc::bd::{BackupDomain, LseCfg, RtcClockSource}; | 13 | use crate::rcc::bd::{BackupDomain, LseCfg, RtcClockSource}; |
| @@ -34,7 +34,7 @@ const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=836_000_000; | |||
| 34 | #[cfg(any(pwr_h7rm0399, pwr_h7rm0433))] | 34 | #[cfg(any(pwr_h7rm0399, pwr_h7rm0433))] |
| 35 | const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=960_000_000; | 35 | const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=960_000_000; |
| 36 | 36 | ||
| 37 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | 37 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; |
| 38 | 38 | ||
| 39 | #[derive(Clone, Copy, Eq, PartialEq)] | 39 | #[derive(Clone, Copy, Eq, PartialEq)] |
| 40 | pub enum VoltageScale { | 40 | pub enum VoltageScale { |
| @@ -109,19 +109,19 @@ pub struct Pll { | |||
| 109 | #[cfg(stm32h5)] | 109 | #[cfg(stm32h5)] |
| 110 | pub source: PllSource, | 110 | pub source: PllSource, |
| 111 | 111 | ||
| 112 | /// PLL pre-divider (DIVM). Must be between 1 and 63. | 112 | /// PLL pre-divider (DIVM). |
| 113 | pub prediv: u8, | 113 | pub prediv: PllPreDiv, |
| 114 | 114 | ||
| 115 | /// PLL multiplication factor. Must be between 4 and 512. | 115 | /// PLL multiplication factor. |
| 116 | pub mul: u16, | 116 | pub mul: PllMul, |
| 117 | 117 | ||
| 118 | /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128. | 118 | /// PLL P division factor. If None, PLL P output is disabled. |
| 119 | /// On PLL1, it must be even (in particular, it cannot be 1.) | 119 | /// On PLL1, it must be even (in particular, it cannot be 1.) |
| 120 | pub divp: Option<u16>, | 120 | pub divp: Option<PllDiv>, |
| 121 | /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128. | 121 | /// PLL Q division factor. If None, PLL Q output is disabled. |
| 122 | pub divq: Option<u16>, | 122 | pub divq: Option<PllDiv>, |
| 123 | /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128. | 123 | /// PLL R division factor. If None, PLL R output is disabled. |
| 124 | pub divr: Option<u16>, | 124 | pub divr: Option<PllDiv>, |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz { | 127 | fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz { |
| @@ -604,9 +604,9 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { | |||
| 604 | 604 | ||
| 605 | // "To save power when PLL1 is not used, the value of PLL1M must be set to 0."" | 605 | // "To save power when PLL1 is not used, the value of PLL1M must be set to 0."" |
| 606 | #[cfg(stm32h7)] | 606 | #[cfg(stm32h7)] |
| 607 | RCC.pllckselr().write(|w| w.set_divm(num, 0)); | 607 | RCC.pllckselr().write(|w| w.set_divm(num, PllPreDiv::from_bits(0))); |
| 608 | #[cfg(stm32h5)] | 608 | #[cfg(stm32h5)] |
| 609 | RCC.pllcfgr(num).write(|w| w.set_divm(0)); | 609 | RCC.pllcfgr(num).write(|w| w.set_divm(PllPreDiv::from_bits(0))); |
| 610 | 610 | ||
| 611 | return PllOutput { | 611 | return PllOutput { |
| 612 | p: None, | 612 | p: None, |
| @@ -615,9 +615,6 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { | |||
| 615 | }; | 615 | }; |
| 616 | }; | 616 | }; |
| 617 | 617 | ||
| 618 | assert!(1 <= config.prediv && config.prediv <= 63); | ||
| 619 | assert!(4 <= config.mul && config.mul <= 512); | ||
| 620 | |||
| 621 | #[cfg(stm32h5)] | 618 | #[cfg(stm32h5)] |
| 622 | let source = config.source; | 619 | let source = config.source; |
| 623 | #[cfg(stm32h7)] | 620 | #[cfg(stm32h7)] |
| @@ -653,22 +650,16 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { | |||
| 653 | }; | 650 | }; |
| 654 | 651 | ||
| 655 | let p = config.divp.map(|div| { | 652 | let p = config.divp.map(|div| { |
| 656 | assert!(1 <= div && div <= 128); | ||
| 657 | if num == 0 { | 653 | if num == 0 { |
| 658 | // on PLL1, DIVP must be even. | 654 | // on PLL1, DIVP must be even. |
| 659 | assert!(div % 2 == 0); | 655 | // The enum value is 1 less than the divider, so check it's odd. |
| 656 | assert!(div.to_bits() % 2 == 1); | ||
| 660 | } | 657 | } |
| 661 | 658 | ||
| 662 | vco_clk / div | 659 | vco_clk / div |
| 663 | }); | 660 | }); |
| 664 | let q = config.divq.map(|div| { | 661 | let q = config.divq.map(|div| vco_clk / div); |
| 665 | assert!(1 <= div && div <= 128); | 662 | let r = config.divr.map(|div| vco_clk / div); |
| 666 | vco_clk / div | ||
| 667 | }); | ||
| 668 | let r = config.divr.map(|div| { | ||
| 669 | assert!(1 <= div && div <= 128); | ||
| 670 | vco_clk / div | ||
| 671 | }); | ||
| 672 | 663 | ||
| 673 | #[cfg(stm32h5)] | 664 | #[cfg(stm32h5)] |
| 674 | RCC.pllcfgr(num).write(|w| { | 665 | RCC.pllcfgr(num).write(|w| { |
| @@ -699,10 +690,10 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput { | |||
| 699 | } | 690 | } |
| 700 | 691 | ||
| 701 | RCC.plldivr(num).write(|w| { | 692 | RCC.plldivr(num).write(|w| { |
| 702 | w.set_plln(config.mul - 1); | 693 | w.set_plln(config.mul); |
| 703 | w.set_pllp((config.divp.unwrap_or(1) - 1) as u8); | 694 | w.set_pllp(config.divp.unwrap_or(PllDiv::DIV2)); |
| 704 | w.set_pllq((config.divq.unwrap_or(1) - 1) as u8); | 695 | w.set_pllq(config.divq.unwrap_or(PllDiv::DIV2)); |
| 705 | w.set_pllr((config.divr.unwrap_or(1) - 1) as u8); | 696 | w.set_pllr(config.divr.unwrap_or(PllDiv::DIV2)); |
| 706 | }); | 697 | }); |
| 707 | 698 | ||
| 708 | RCC.cr().modify(|w| w.set_pllon(num, true)); | 699 | RCC.cr().modify(|w| w.set_pllon(num, true)); |
diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs index 7358be31b..b42361268 100644 --- a/embassy-stm32/src/rcc/l0.rs +++ b/embassy-stm32/src/rcc/l0.rs | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | use super::bd::BackupDomain; | 1 | use super::bd::BackupDomain; |
| 2 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | ||
| 3 | use super::RtcClockSource; | 2 | use super::RtcClockSource; |
| 4 | pub use crate::pac::pwr::vals::Vos as VoltageScale; | 3 | pub use crate::pac::pwr::vals::Vos as VoltageScale; |
| 5 | use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; | 4 | use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; |
| 5 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; | ||
| 6 | #[cfg(crs)] | 6 | #[cfg(crs)] |
| 7 | use crate::pac::{crs, CRS, SYSCFG}; | 7 | use crate::pac::{crs, CRS, SYSCFG}; |
| 8 | use crate::pac::{FLASH, PWR, RCC}; | 8 | use crate::pac::{FLASH, PWR, RCC}; |
diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs index 90524fb37..e445a716e 100644 --- a/embassy-stm32/src/rcc/l1.rs +++ b/embassy-stm32/src/rcc/l1.rs | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | ||
| 2 | use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; | 1 | use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; |
| 2 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; | ||
| 3 | use crate::pac::{FLASH, RCC}; | 3 | use crate::pac::{FLASH, RCC}; |
| 4 | use crate::rcc::{set_freqs, Clocks}; | 4 | use crate::rcc::{set_freqs, Clocks}; |
| 5 | use crate::time::Hertz; | 5 | use crate::time::Hertz; |
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 2fbb9920e..0e35b42e8 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs | |||
| @@ -1,7 +1,9 @@ | |||
| 1 | use stm32_metapac::rcc::regs::Cfgr; | 1 | use crate::pac::rcc::regs::Cfgr; |
| 2 | 2 | pub use crate::pac::rcc::vals::{ | |
| 3 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | 3 | Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, |
| 4 | use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; | 4 | Pllr as PllRDiv, Ppre as APBPrescaler, |
| 5 | }; | ||
| 6 | use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; | ||
| 5 | use crate::pac::{FLASH, RCC}; | 7 | use crate::pac::{FLASH, RCC}; |
| 6 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; | 8 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; |
| 7 | use crate::rcc::{set_freqs, Clocks}; | 9 | use crate::rcc::{set_freqs, Clocks}; |
| @@ -17,62 +19,11 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); | |||
| 17 | #[derive(Clone, Copy)] | 19 | #[derive(Clone, Copy)] |
| 18 | pub enum ClockSrc { | 20 | pub enum ClockSrc { |
| 19 | MSI(MSIRange), | 21 | MSI(MSIRange), |
| 20 | PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>), | 22 | PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>), |
| 21 | HSE(Hertz), | 23 | HSE(Hertz), |
| 22 | HSI16, | 24 | HSI16, |
| 23 | } | 25 | } |
| 24 | 26 | ||
| 25 | /// MSI Clock Range | ||
| 26 | /// | ||
| 27 | /// These ranges control the frequency of the MSI. Internally, these ranges map | ||
| 28 | /// to the `MSIRANGE` bits in the `RCC_ICSCR` register. | ||
| 29 | #[derive(Clone, Copy)] | ||
| 30 | pub enum MSIRange { | ||
| 31 | /// Around 100 kHz | ||
| 32 | Range0, | ||
| 33 | /// Around 200 kHz | ||
| 34 | Range1, | ||
| 35 | /// Around 400 kHz | ||
| 36 | Range2, | ||
| 37 | /// Around 800 kHz | ||
| 38 | Range3, | ||
| 39 | /// Around 1 MHz | ||
| 40 | Range4, | ||
| 41 | /// Around 2 MHz | ||
| 42 | Range5, | ||
| 43 | /// Around 4 MHz (reset value) | ||
| 44 | Range6, | ||
| 45 | /// Around 8 MHz | ||
| 46 | Range7, | ||
| 47 | /// Around 16 MHz | ||
| 48 | Range8, | ||
| 49 | /// Around 24 MHz | ||
| 50 | Range9, | ||
| 51 | /// Around 32 MHz | ||
| 52 | Range10, | ||
| 53 | /// Around 48 MHz | ||
| 54 | Range11, | ||
| 55 | } | ||
| 56 | |||
| 57 | impl Default for MSIRange { | ||
| 58 | fn default() -> MSIRange { | ||
| 59 | MSIRange::Range6 | ||
| 60 | } | ||
| 61 | } | ||
| 62 | |||
| 63 | pub type PLL48Div = PLLClkDiv; | ||
| 64 | pub type PLLSAI1RDiv = PLLClkDiv; | ||
| 65 | pub type PLLSAI1QDiv = PLLClkDiv; | ||
| 66 | pub type PLLSAI1PDiv = PLLClkDiv; | ||
| 67 | |||
| 68 | /// PLL divider | ||
| 69 | #[derive(Clone, Copy)] | ||
| 70 | pub enum PLLDiv { | ||
| 71 | Div2, | ||
| 72 | Div3, | ||
| 73 | Div4, | ||
| 74 | } | ||
| 75 | |||
| 76 | /// PLL clock input source | 27 | /// PLL clock input source |
| 77 | #[derive(Clone, Copy)] | 28 | #[derive(Clone, Copy)] |
| 78 | pub enum PLLSource { | 29 | pub enum PLLSource { |
| @@ -81,95 +32,6 @@ pub enum PLLSource { | |||
| 81 | MSI(MSIRange), | 32 | MSI(MSIRange), |
| 82 | } | 33 | } |
| 83 | 34 | ||
| 84 | seq_macro::seq!(N in 8..=86 { | ||
| 85 | #[derive(Clone, Copy)] | ||
| 86 | pub enum PLLMul { | ||
| 87 | #( | ||
| 88 | Mul~N, | ||
| 89 | )* | ||
| 90 | } | ||
| 91 | |||
| 92 | impl From<PLLMul> for u8 { | ||
| 93 | fn from(val: PLLMul) -> u8 { | ||
| 94 | match val { | ||
| 95 | #( | ||
| 96 | PLLMul::Mul~N => N, | ||
| 97 | )* | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | impl PLLMul { | ||
| 103 | pub fn to_mul(self) -> u32 { | ||
| 104 | match self { | ||
| 105 | #( | ||
| 106 | PLLMul::Mul~N => N, | ||
| 107 | )* | ||
| 108 | } | ||
| 109 | } | ||
| 110 | } | ||
| 111 | }); | ||
| 112 | |||
| 113 | #[derive(Clone, Copy)] | ||
| 114 | pub enum PLLClkDiv { | ||
| 115 | Div2, | ||
| 116 | Div4, | ||
| 117 | Div6, | ||
| 118 | Div8, | ||
| 119 | } | ||
| 120 | |||
| 121 | impl PLLClkDiv { | ||
| 122 | pub fn to_div(self) -> u32 { | ||
| 123 | let val: u8 = self.into(); | ||
| 124 | (val as u32 + 1) * 2 | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | impl From<PLLClkDiv> for u8 { | ||
| 129 | fn from(val: PLLClkDiv) -> u8 { | ||
| 130 | match val { | ||
| 131 | PLLClkDiv::Div2 => 0b00, | ||
| 132 | PLLClkDiv::Div4 => 0b01, | ||
| 133 | PLLClkDiv::Div6 => 0b10, | ||
| 134 | PLLClkDiv::Div8 => 0b11, | ||
| 135 | } | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | #[derive(Clone, Copy)] | ||
| 140 | pub enum PLLSrcDiv { | ||
| 141 | Div1, | ||
| 142 | Div2, | ||
| 143 | Div3, | ||
| 144 | Div4, | ||
| 145 | Div5, | ||
| 146 | Div6, | ||
| 147 | Div7, | ||
| 148 | Div8, | ||
| 149 | } | ||
| 150 | |||
| 151 | impl PLLSrcDiv { | ||
| 152 | pub fn to_div(self) -> u32 { | ||
| 153 | let val: u8 = self.into(); | ||
| 154 | val as u32 + 1 | ||
| 155 | } | ||
| 156 | } | ||
| 157 | |||
| 158 | impl From<PLLSrcDiv> for u8 { | ||
| 159 | fn from(val: PLLSrcDiv) -> u8 { | ||
| 160 | match val { | ||
| 161 | PLLSrcDiv::Div1 => 0b000, | ||
| 162 | PLLSrcDiv::Div2 => 0b001, | ||
| 163 | PLLSrcDiv::Div3 => 0b010, | ||
| 164 | PLLSrcDiv::Div4 => 0b011, | ||
| 165 | PLLSrcDiv::Div5 => 0b100, | ||
| 166 | PLLSrcDiv::Div6 => 0b101, | ||
| 167 | PLLSrcDiv::Div7 => 0b110, | ||
| 168 | PLLSrcDiv::Div8 => 0b111, | ||
| 169 | } | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | impl From<PLLSource> for Pllsrc { | 35 | impl From<PLLSource> for Pllsrc { |
| 174 | fn from(val: PLLSource) -> Pllsrc { | 36 | fn from(val: PLLSource) -> Pllsrc { |
| 175 | match val { | 37 | match val { |
| @@ -180,57 +42,13 @@ impl From<PLLSource> for Pllsrc { | |||
| 180 | } | 42 | } |
| 181 | } | 43 | } |
| 182 | 44 | ||
| 183 | impl From<MSIRange> for Msirange { | ||
| 184 | fn from(val: MSIRange) -> Msirange { | ||
| 185 | match val { | ||
| 186 | MSIRange::Range0 => Msirange::RANGE100K, | ||
| 187 | MSIRange::Range1 => Msirange::RANGE200K, | ||
| 188 | MSIRange::Range2 => Msirange::RANGE400K, | ||
| 189 | MSIRange::Range3 => Msirange::RANGE800K, | ||
| 190 | MSIRange::Range4 => Msirange::RANGE1M, | ||
| 191 | MSIRange::Range5 => Msirange::RANGE2M, | ||
| 192 | MSIRange::Range6 => Msirange::RANGE4M, | ||
| 193 | MSIRange::Range7 => Msirange::RANGE8M, | ||
| 194 | MSIRange::Range8 => Msirange::RANGE16M, | ||
| 195 | MSIRange::Range9 => Msirange::RANGE24M, | ||
| 196 | MSIRange::Range10 => Msirange::RANGE32M, | ||
| 197 | MSIRange::Range11 => Msirange::RANGE48M, | ||
| 198 | } | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | impl From<MSIRange> for u32 { | ||
| 203 | fn from(val: MSIRange) -> u32 { | ||
| 204 | match val { | ||
| 205 | MSIRange::Range0 => 100_000, | ||
| 206 | MSIRange::Range1 => 200_000, | ||
| 207 | MSIRange::Range2 => 400_000, | ||
| 208 | MSIRange::Range3 => 800_000, | ||
| 209 | MSIRange::Range4 => 1_000_000, | ||
| 210 | MSIRange::Range5 => 2_000_000, | ||
| 211 | MSIRange::Range6 => 4_000_000, | ||
| 212 | MSIRange::Range7 => 8_000_000, | ||
| 213 | MSIRange::Range8 => 16_000_000, | ||
| 214 | MSIRange::Range9 => 24_000_000, | ||
| 215 | MSIRange::Range10 => 32_000_000, | ||
| 216 | MSIRange::Range11 => 48_000_000, | ||
| 217 | } | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | /// Clocks configutation | 45 | /// Clocks configutation |
| 222 | pub struct Config { | 46 | pub struct Config { |
| 223 | pub mux: ClockSrc, | 47 | pub mux: ClockSrc, |
| 224 | pub ahb_pre: AHBPrescaler, | 48 | pub ahb_pre: AHBPrescaler, |
| 225 | pub apb1_pre: APBPrescaler, | 49 | pub apb1_pre: APBPrescaler, |
| 226 | pub apb2_pre: APBPrescaler, | 50 | pub apb2_pre: APBPrescaler, |
| 227 | pub pllsai1: Option<( | 51 | pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>, |
| 228 | PLLMul, | ||
| 229 | PLLSrcDiv, | ||
| 230 | Option<PLLSAI1RDiv>, | ||
| 231 | Option<PLLSAI1QDiv>, | ||
| 232 | Option<PLLSAI1PDiv>, | ||
| 233 | )>, | ||
| 234 | #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] | 52 | #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] |
| 235 | pub hsi48: bool, | 53 | pub hsi48: bool, |
| 236 | pub rtc_mux: RtcClockSource, | 54 | pub rtc_mux: RtcClockSource, |
| @@ -242,7 +60,7 @@ impl Default for Config { | |||
| 242 | #[inline] | 60 | #[inline] |
| 243 | fn default() -> Config { | 61 | fn default() -> Config { |
| 244 | Config { | 62 | Config { |
| 245 | mux: ClockSrc::MSI(MSIRange::Range6), | 63 | mux: ClockSrc::MSI(MSIRange::RANGE4M), |
| 246 | ahb_pre: AHBPrescaler::DIV1, | 64 | ahb_pre: AHBPrescaler::DIV1, |
| 247 | apb1_pre: APBPrescaler::DIV1, | 65 | apb1_pre: APBPrescaler::DIV1, |
| 248 | apb2_pre: APBPrescaler::DIV1, | 66 | apb2_pre: APBPrescaler::DIV1, |
| @@ -262,7 +80,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 262 | // Turn on MSI and configure it to 4MHz. | 80 | // Turn on MSI and configure it to 4MHz. |
| 263 | RCC.cr().modify(|w| { | 81 | RCC.cr().modify(|w| { |
| 264 | w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. | 82 | w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. |
| 265 | w.set_msirange(MSIRange::default().into()); | 83 | w.set_msirange(MSIRange::RANGE4M); |
| 266 | w.set_msipllen(false); | 84 | w.set_msipllen(false); |
| 267 | w.set_msion(true) | 85 | w.set_msion(true) |
| 268 | }); | 86 | }); |
| @@ -298,40 +116,40 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 298 | while !RCC.cr().read().msirdy() {} | 116 | while !RCC.cr().read().msirdy() {} |
| 299 | 117 | ||
| 300 | // Enable as clock source for USB, RNG if running at 48 MHz | 118 | // Enable as clock source for USB, RNG if running at 48 MHz |
| 301 | if let MSIRange::Range11 = range { | 119 | if range == MSIRange::RANGE48M { |
| 302 | RCC.ccipr().modify(|w| { | 120 | RCC.ccipr().modify(|w| { |
| 303 | w.set_clk48sel(0b11); | 121 | w.set_clk48sel(0b11); |
| 304 | }); | 122 | }); |
| 305 | } | 123 | } |
| 306 | (range.into(), Sw::MSI) | 124 | (msirange_to_hertz(range), Sw::MSI) |
| 307 | } | 125 | } |
| 308 | ClockSrc::HSI16 => { | 126 | ClockSrc::HSI16 => { |
| 309 | // Enable HSI16 | 127 | // Enable HSI16 |
| 310 | RCC.cr().write(|w| w.set_hsion(true)); | 128 | RCC.cr().write(|w| w.set_hsion(true)); |
| 311 | while !RCC.cr().read().hsirdy() {} | 129 | while !RCC.cr().read().hsirdy() {} |
| 312 | 130 | ||
| 313 | (HSI_FREQ.0, Sw::HSI16) | 131 | (HSI_FREQ, Sw::HSI16) |
| 314 | } | 132 | } |
| 315 | ClockSrc::HSE(freq) => { | 133 | ClockSrc::HSE(freq) => { |
| 316 | // Enable HSE | 134 | // Enable HSE |
| 317 | RCC.cr().write(|w| w.set_hseon(true)); | 135 | RCC.cr().write(|w| w.set_hseon(true)); |
| 318 | while !RCC.cr().read().hserdy() {} | 136 | while !RCC.cr().read().hserdy() {} |
| 319 | 137 | ||
| 320 | (freq.0, Sw::HSE) | 138 | (freq, Sw::HSE) |
| 321 | } | 139 | } |
| 322 | ClockSrc::PLL(src, div, prediv, mul, pll48div) => { | 140 | ClockSrc::PLL(src, divr, prediv, mul, divq) => { |
| 323 | let src_freq = match src { | 141 | let src_freq = match src { |
| 324 | PLLSource::HSE(freq) => { | 142 | PLLSource::HSE(freq) => { |
| 325 | // Enable HSE | 143 | // Enable HSE |
| 326 | RCC.cr().write(|w| w.set_hseon(true)); | 144 | RCC.cr().write(|w| w.set_hseon(true)); |
| 327 | while !RCC.cr().read().hserdy() {} | 145 | while !RCC.cr().read().hserdy() {} |
| 328 | freq.0 | 146 | freq |
| 329 | } | 147 | } |
| 330 | PLLSource::HSI16 => { | 148 | PLLSource::HSI16 => { |
| 331 | // Enable HSI | 149 | // Enable HSI |
| 332 | RCC.cr().write(|w| w.set_hsion(true)); | 150 | RCC.cr().write(|w| w.set_hsion(true)); |
| 333 | while !RCC.cr().read().hsirdy() {} | 151 | while !RCC.cr().read().hsirdy() {} |
| 334 | HSI_FREQ.0 | 152 | HSI_FREQ |
| 335 | } | 153 | } |
| 336 | PLLSource::MSI(range) => { | 154 | PLLSource::MSI(range) => { |
| 337 | // Enable MSI | 155 | // Enable MSI |
| @@ -343,7 +161,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 343 | w.set_msion(true); | 161 | w.set_msion(true); |
| 344 | }); | 162 | }); |
| 345 | while !RCC.cr().read().msirdy() {} | 163 | while !RCC.cr().read().msirdy() {} |
| 346 | range.into() | 164 | |
| 165 | msirange_to_hertz(range) | ||
| 347 | } | 166 | } |
| 348 | }; | 167 | }; |
| 349 | 168 | ||
| @@ -351,28 +170,28 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 351 | RCC.cr().modify(|w| w.set_pllon(false)); | 170 | RCC.cr().modify(|w| w.set_pllon(false)); |
| 352 | while RCC.cr().read().pllrdy() {} | 171 | while RCC.cr().read().pllrdy() {} |
| 353 | 172 | ||
| 354 | let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div(); | 173 | let freq = src_freq / prediv * mul / divr; |
| 355 | 174 | ||
| 356 | #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))] | 175 | #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))] |
| 357 | assert!(freq <= 120_000_000); | 176 | assert!(freq.0 <= 120_000_000); |
| 358 | #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))] | 177 | #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))] |
| 359 | assert!(freq <= 80_000_000); | 178 | assert!(freq.0 <= 80_000_000); |
| 360 | 179 | ||
| 361 | RCC.pllcfgr().write(move |w| { | 180 | RCC.pllcfgr().write(move |w| { |
| 362 | w.set_plln(mul.into()); | 181 | w.set_plln(mul); |
| 363 | w.set_pllm(prediv.into()); | 182 | w.set_pllm(prediv); |
| 364 | w.set_pllr(div.into()); | 183 | w.set_pllr(divr); |
| 365 | if let Some(pll48div) = pll48div { | 184 | if let Some(divq) = divq { |
| 366 | w.set_pllq(pll48div.into()); | 185 | w.set_pllq(divq); |
| 367 | w.set_pllqen(true); | 186 | w.set_pllqen(true); |
| 368 | } | 187 | } |
| 369 | w.set_pllsrc(src.into()); | 188 | w.set_pllsrc(src.into()); |
| 370 | }); | 189 | }); |
| 371 | 190 | ||
| 372 | // Enable as clock source for USB, RNG if PLL48 divisor is provided | 191 | // Enable as clock source for USB, RNG if PLL48 divisor is provided |
| 373 | if let Some(pll48div) = pll48div { | 192 | if let Some(divq) = divq { |
| 374 | let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div(); | 193 | let freq = src_freq / prediv * mul / divq; |
| 375 | assert!(freq == 48_000_000); | 194 | assert!(freq.0 == 48_000_000); |
| 376 | RCC.ccipr().modify(|w| { | 195 | RCC.ccipr().modify(|w| { |
| 377 | w.set_clk48sel(0b10); | 196 | w.set_clk48sel(0b10); |
| 378 | }); | 197 | }); |
| @@ -380,25 +199,25 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 380 | 199 | ||
| 381 | if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { | 200 | if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { |
| 382 | RCC.pllsai1cfgr().write(move |w| { | 201 | RCC.pllsai1cfgr().write(move |w| { |
| 383 | w.set_pllsai1n(mul.into()); | 202 | w.set_plln(mul); |
| 384 | w.set_pllsai1m(prediv.into()); | 203 | w.set_pllm(prediv); |
| 385 | if let Some(r_div) = r_div { | 204 | if let Some(r_div) = r_div { |
| 386 | w.set_pllsai1r(r_div.into()); | 205 | w.set_pllr(r_div); |
| 387 | w.set_pllsai1ren(true); | 206 | w.set_pllren(true); |
| 388 | } | 207 | } |
| 389 | if let Some(q_div) = q_div { | 208 | if let Some(q_div) = q_div { |
| 390 | w.set_pllsai1q(q_div.into()); | 209 | w.set_pllq(q_div); |
| 391 | w.set_pllsai1qen(true); | 210 | w.set_pllqen(true); |
| 392 | let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div(); | 211 | let freq = src_freq / prediv * mul / q_div; |
| 393 | if freq == 48_000_000 { | 212 | if freq.0 == 48_000_000 { |
| 394 | RCC.ccipr().modify(|w| { | 213 | RCC.ccipr().modify(|w| { |
| 395 | w.set_clk48sel(0b1); | 214 | w.set_clk48sel(0b1); |
| 396 | }); | 215 | }); |
| 397 | } | 216 | } |
| 398 | } | 217 | } |
| 399 | if let Some(p_div) = p_div { | 218 | if let Some(p_div) = p_div { |
| 400 | w.set_pllsai1pdiv(p_div.into()); | 219 | w.set_pllp(p_div); |
| 401 | w.set_pllsai1pen(true); | 220 | w.set_pllpen(true); |
| 402 | } | 221 | } |
| 403 | }); | 222 | }); |
| 404 | 223 | ||
| @@ -425,17 +244,13 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 425 | 244 | ||
| 426 | // Set flash wait states | 245 | // Set flash wait states |
| 427 | FLASH.acr().modify(|w| { | 246 | FLASH.acr().modify(|w| { |
| 428 | w.set_latency(if sys_clk <= 16_000_000 { | 247 | w.set_latency(match sys_clk.0 { |
| 429 | 0b000 | 248 | 0..=16_000_000 => 0, |
| 430 | } else if sys_clk <= 32_000_000 { | 249 | 0..=32_000_000 => 1, |
| 431 | 0b001 | 250 | 0..=48_000_000 => 2, |
| 432 | } else if sys_clk <= 48_000_000 { | 251 | 0..=64_000_000 => 3, |
| 433 | 0b010 | 252 | _ => 4, |
| 434 | } else if sys_clk <= 64_000_000 { | 253 | }) |
| 435 | 0b011 | ||
| 436 | } else { | ||
| 437 | 0b100 | ||
| 438 | }); | ||
| 439 | }); | 254 | }); |
| 440 | 255 | ||
| 441 | RCC.cfgr().modify(|w| { | 256 | RCC.cfgr().modify(|w| { |
| @@ -445,43 +260,50 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 445 | w.set_ppre2(config.apb2_pre.into()); | 260 | w.set_ppre2(config.apb2_pre.into()); |
| 446 | }); | 261 | }); |
| 447 | 262 | ||
| 448 | let ahb_freq: u32 = match config.ahb_pre { | 263 | let ahb_freq = sys_clk / config.ahb_pre; |
| 449 | AHBPrescaler::DIV1 => sys_clk, | ||
| 450 | pre => { | ||
| 451 | let pre: Hpre = pre.into(); | ||
| 452 | let pre = 1 << (pre.to_bits() as u32 - 7); | ||
| 453 | sys_clk / pre | ||
| 454 | } | ||
| 455 | }; | ||
| 456 | 264 | ||
| 457 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { | 265 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { |
| 458 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 266 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 459 | pre => { | 267 | pre => { |
| 460 | let pre: Ppre = pre.into(); | 268 | let freq = ahb_freq / pre; |
| 461 | let pre: u8 = 1 << (pre.to_bits() - 3); | 269 | (freq, freq * 2u32) |
| 462 | let freq = ahb_freq / pre as u32; | ||
| 463 | (freq, freq * 2) | ||
| 464 | } | 270 | } |
| 465 | }; | 271 | }; |
| 466 | 272 | ||
| 467 | let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { | 273 | let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { |
| 468 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 274 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 469 | pre => { | 275 | pre => { |
| 470 | let pre: Ppre = pre.into(); | 276 | let freq = ahb_freq / pre; |
| 471 | let pre: u8 = 1 << (pre.to_bits() - 3); | 277 | (freq, freq * 2u32) |
| 472 | let freq = ahb_freq / pre as u32; | ||
| 473 | (freq, freq * 2) | ||
| 474 | } | 278 | } |
| 475 | }; | 279 | }; |
| 476 | 280 | ||
| 477 | set_freqs(Clocks { | 281 | set_freqs(Clocks { |
| 478 | sys: Hertz(sys_clk), | 282 | sys: sys_clk, |
| 479 | ahb1: Hertz(ahb_freq), | 283 | ahb1: ahb_freq, |
| 480 | ahb2: Hertz(ahb_freq), | 284 | ahb2: ahb_freq, |
| 481 | ahb3: Hertz(ahb_freq), | 285 | ahb3: ahb_freq, |
| 482 | apb1: Hertz(apb1_freq), | 286 | apb1: apb1_freq, |
| 483 | apb2: Hertz(apb2_freq), | 287 | apb2: apb2_freq, |
| 484 | apb1_tim: Hertz(apb1_tim_freq), | 288 | apb1_tim: apb1_tim_freq, |
| 485 | apb2_tim: Hertz(apb2_tim_freq), | 289 | apb2_tim: apb2_tim_freq, |
| 486 | }); | 290 | }); |
| 487 | } | 291 | } |
| 292 | |||
| 293 | fn msirange_to_hertz(range: Msirange) -> Hertz { | ||
| 294 | match range { | ||
| 295 | MSIRange::RANGE100K => Hertz(100_000), | ||
| 296 | MSIRange::RANGE200K => Hertz(200_000), | ||
| 297 | MSIRange::RANGE400K => Hertz(400_000), | ||
| 298 | MSIRange::RANGE800K => Hertz(800_000), | ||
| 299 | MSIRange::RANGE1M => Hertz(1_000_000), | ||
| 300 | MSIRange::RANGE2M => Hertz(2_000_000), | ||
| 301 | MSIRange::RANGE4M => Hertz(4_000_000), | ||
| 302 | MSIRange::RANGE8M => Hertz(8_000_000), | ||
| 303 | MSIRange::RANGE16M => Hertz(16_000_000), | ||
| 304 | MSIRange::RANGE24M => Hertz(24_000_000), | ||
| 305 | MSIRange::RANGE32M => Hertz(32_000_000), | ||
| 306 | MSIRange::RANGE48M => Hertz(48_000_000), | ||
| 307 | _ => unreachable!(), | ||
| 308 | } | ||
| 309 | } | ||
diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index 652bdcb7b..d9b3ee282 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs | |||
| @@ -1,8 +1,11 @@ | |||
| 1 | use stm32_metapac::PWR; | 1 | use crate::pac::rcc::regs::Cfgr; |
| 2 | 2 | pub use crate::pac::rcc::vals::{ | |
| 3 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | 3 | Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, |
| 4 | use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; | 4 | Pllr as PllRDiv, Ppre as APBPrescaler, |
| 5 | use crate::pac::{FLASH, RCC}; | 5 | }; |
| 6 | use crate::pac::rcc::vals::{Msirange, Pllsrc, Sw}; | ||
| 7 | use crate::pac::{FLASH, PWR, RCC}; | ||
| 8 | use crate::rcc::bd::RtcClockSource; | ||
| 6 | use crate::rcc::{set_freqs, Clocks}; | 9 | use crate::rcc::{set_freqs, Clocks}; |
| 7 | use crate::time::Hertz; | 10 | use crate::time::Hertz; |
| 8 | 11 | ||
| @@ -16,62 +19,11 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); | |||
| 16 | #[derive(Clone, Copy)] | 19 | #[derive(Clone, Copy)] |
| 17 | pub enum ClockSrc { | 20 | pub enum ClockSrc { |
| 18 | MSI(MSIRange), | 21 | MSI(MSIRange), |
| 19 | PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>), | 22 | PLL(PLLSource, PllRDiv, PllPreDiv, PllMul, Option<PllQDiv>), |
| 20 | HSE(Hertz), | 23 | HSE(Hertz), |
| 21 | HSI16, | 24 | HSI16, |
| 22 | } | 25 | } |
| 23 | 26 | ||
| 24 | /// MSI Clock Range | ||
| 25 | /// | ||
| 26 | /// These ranges control the frequency of the MSI. Internally, these ranges map | ||
| 27 | /// to the `MSIRANGE` bits in the `RCC_ICSCR` register. | ||
| 28 | #[derive(Clone, Copy)] | ||
| 29 | pub enum MSIRange { | ||
| 30 | /// Around 100 kHz | ||
| 31 | Range0, | ||
| 32 | /// Around 200 kHz | ||
| 33 | Range1, | ||
| 34 | /// Around 400 kHz | ||
| 35 | Range2, | ||
| 36 | /// Around 800 kHz | ||
| 37 | Range3, | ||
| 38 | /// Around 1 MHz | ||
| 39 | Range4, | ||
| 40 | /// Around 2 MHz | ||
| 41 | Range5, | ||
| 42 | /// Around 4 MHz (reset value) | ||
| 43 | Range6, | ||
| 44 | /// Around 8 MHz | ||
| 45 | Range7, | ||
| 46 | /// Around 16 MHz | ||
| 47 | Range8, | ||
| 48 | /// Around 24 MHz | ||
| 49 | Range9, | ||
| 50 | /// Around 32 MHz | ||
| 51 | Range10, | ||
| 52 | /// Around 48 MHz | ||
| 53 | Range11, | ||
| 54 | } | ||
| 55 | |||
| 56 | impl Default for MSIRange { | ||
| 57 | fn default() -> MSIRange { | ||
| 58 | MSIRange::Range6 | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | pub type PLL48Div = PLLClkDiv; | ||
| 63 | pub type PLLSAI1RDiv = PLLClkDiv; | ||
| 64 | pub type PLLSAI1QDiv = PLLClkDiv; | ||
| 65 | pub type PLLSAI1PDiv = PLLClkDiv; | ||
| 66 | |||
| 67 | /// PLL divider | ||
| 68 | #[derive(Clone, Copy)] | ||
| 69 | pub enum PLLDiv { | ||
| 70 | Div2, | ||
| 71 | Div3, | ||
| 72 | Div4, | ||
| 73 | } | ||
| 74 | |||
| 75 | /// PLL clock input source | 27 | /// PLL clock input source |
| 76 | #[derive(Clone, Copy)] | 28 | #[derive(Clone, Copy)] |
| 77 | pub enum PLLSource { | 29 | pub enum PLLSource { |
| @@ -80,95 +32,6 @@ pub enum PLLSource { | |||
| 80 | MSI(MSIRange), | 32 | MSI(MSIRange), |
| 81 | } | 33 | } |
| 82 | 34 | ||
| 83 | seq_macro::seq!(N in 8..=86 { | ||
| 84 | #[derive(Clone, Copy)] | ||
| 85 | pub enum PLLMul { | ||
| 86 | #( | ||
| 87 | Mul~N, | ||
| 88 | )* | ||
| 89 | } | ||
| 90 | |||
| 91 | impl From<PLLMul> for u8 { | ||
| 92 | fn from(val: PLLMul) -> u8 { | ||
| 93 | match val { | ||
| 94 | #( | ||
| 95 | PLLMul::Mul~N => N, | ||
| 96 | )* | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | impl PLLMul { | ||
| 102 | pub fn to_mul(self) -> u32 { | ||
| 103 | match self { | ||
| 104 | #( | ||
| 105 | PLLMul::Mul~N => N, | ||
| 106 | )* | ||
| 107 | } | ||
| 108 | } | ||
| 109 | } | ||
| 110 | }); | ||
| 111 | |||
| 112 | #[derive(Clone, Copy)] | ||
| 113 | pub enum PLLClkDiv { | ||
| 114 | Div2, | ||
| 115 | Div4, | ||
| 116 | Div6, | ||
| 117 | Div8, | ||
| 118 | } | ||
| 119 | |||
| 120 | impl PLLClkDiv { | ||
| 121 | pub fn to_div(self) -> u32 { | ||
| 122 | let val: u8 = self.into(); | ||
| 123 | (val as u32 + 1) * 2 | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | impl From<PLLClkDiv> for u8 { | ||
| 128 | fn from(val: PLLClkDiv) -> u8 { | ||
| 129 | match val { | ||
| 130 | PLLClkDiv::Div2 => 0b00, | ||
| 131 | PLLClkDiv::Div4 => 0b01, | ||
| 132 | PLLClkDiv::Div6 => 0b10, | ||
| 133 | PLLClkDiv::Div8 => 0b11, | ||
| 134 | } | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | #[derive(Clone, Copy)] | ||
| 139 | pub enum PLLSrcDiv { | ||
| 140 | Div1, | ||
| 141 | Div2, | ||
| 142 | Div3, | ||
| 143 | Div4, | ||
| 144 | Div5, | ||
| 145 | Div6, | ||
| 146 | Div7, | ||
| 147 | Div8, | ||
| 148 | } | ||
| 149 | |||
| 150 | impl PLLSrcDiv { | ||
| 151 | pub fn to_div(self) -> u32 { | ||
| 152 | let val: u8 = self.into(); | ||
| 153 | val as u32 + 1 | ||
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | impl From<PLLSrcDiv> for u8 { | ||
| 158 | fn from(val: PLLSrcDiv) -> u8 { | ||
| 159 | match val { | ||
| 160 | PLLSrcDiv::Div1 => 0b000, | ||
| 161 | PLLSrcDiv::Div2 => 0b001, | ||
| 162 | PLLSrcDiv::Div3 => 0b010, | ||
| 163 | PLLSrcDiv::Div4 => 0b011, | ||
| 164 | PLLSrcDiv::Div5 => 0b100, | ||
| 165 | PLLSrcDiv::Div6 => 0b101, | ||
| 166 | PLLSrcDiv::Div7 => 0b110, | ||
| 167 | PLLSrcDiv::Div8 => 0b111, | ||
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | impl From<PLLSource> for Pllsrc { | 35 | impl From<PLLSource> for Pllsrc { |
| 173 | fn from(val: PLLSource) -> Pllsrc { | 36 | fn from(val: PLLSource) -> Pllsrc { |
| 174 | match val { | 37 | match val { |
| @@ -179,75 +42,59 @@ impl From<PLLSource> for Pllsrc { | |||
| 179 | } | 42 | } |
| 180 | } | 43 | } |
| 181 | 44 | ||
| 182 | impl From<MSIRange> for Msirange { | ||
| 183 | fn from(val: MSIRange) -> Msirange { | ||
| 184 | match val { | ||
| 185 | MSIRange::Range0 => Msirange::RANGE100K, | ||
| 186 | MSIRange::Range1 => Msirange::RANGE200K, | ||
| 187 | MSIRange::Range2 => Msirange::RANGE400K, | ||
| 188 | MSIRange::Range3 => Msirange::RANGE800K, | ||
| 189 | MSIRange::Range4 => Msirange::RANGE1M, | ||
| 190 | MSIRange::Range5 => Msirange::RANGE2M, | ||
| 191 | MSIRange::Range6 => Msirange::RANGE4M, | ||
| 192 | MSIRange::Range7 => Msirange::RANGE8M, | ||
| 193 | MSIRange::Range8 => Msirange::RANGE16M, | ||
| 194 | MSIRange::Range9 => Msirange::RANGE24M, | ||
| 195 | MSIRange::Range10 => Msirange::RANGE32M, | ||
| 196 | MSIRange::Range11 => Msirange::RANGE48M, | ||
| 197 | } | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | impl From<MSIRange> for u32 { | ||
| 202 | fn from(val: MSIRange) -> u32 { | ||
| 203 | match val { | ||
| 204 | MSIRange::Range0 => 100_000, | ||
| 205 | MSIRange::Range1 => 200_000, | ||
| 206 | MSIRange::Range2 => 400_000, | ||
| 207 | MSIRange::Range3 => 800_000, | ||
| 208 | MSIRange::Range4 => 1_000_000, | ||
| 209 | MSIRange::Range5 => 2_000_000, | ||
| 210 | MSIRange::Range6 => 4_000_000, | ||
| 211 | MSIRange::Range7 => 8_000_000, | ||
| 212 | MSIRange::Range8 => 16_000_000, | ||
| 213 | MSIRange::Range9 => 24_000_000, | ||
| 214 | MSIRange::Range10 => 32_000_000, | ||
| 215 | MSIRange::Range11 => 48_000_000, | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | /// Clocks configutation | 45 | /// Clocks configutation |
| 221 | pub struct Config { | 46 | pub struct Config { |
| 222 | pub mux: ClockSrc, | 47 | pub mux: ClockSrc, |
| 223 | pub ahb_pre: AHBPrescaler, | 48 | pub ahb_pre: AHBPrescaler, |
| 224 | pub apb1_pre: APBPrescaler, | 49 | pub apb1_pre: APBPrescaler, |
| 225 | pub apb2_pre: APBPrescaler, | 50 | pub apb2_pre: APBPrescaler, |
| 226 | pub pllsai1: Option<( | 51 | pub pllsai1: Option<(PllMul, PllPreDiv, Option<PllRDiv>, Option<PllQDiv>, Option<PllPDiv>)>, |
| 227 | PLLMul, | ||
| 228 | PLLSrcDiv, | ||
| 229 | Option<PLLSAI1RDiv>, | ||
| 230 | Option<PLLSAI1QDiv>, | ||
| 231 | Option<PLLSAI1PDiv>, | ||
| 232 | )>, | ||
| 233 | pub hsi48: bool, | 52 | pub hsi48: bool, |
| 53 | pub rtc_mux: RtcClockSource, | ||
| 54 | pub lse: Option<Hertz>, | ||
| 55 | pub lsi: bool, | ||
| 234 | } | 56 | } |
| 235 | 57 | ||
| 236 | impl Default for Config { | 58 | impl Default for Config { |
| 237 | #[inline] | 59 | #[inline] |
| 238 | fn default() -> Config { | 60 | fn default() -> Config { |
| 239 | Config { | 61 | Config { |
| 240 | mux: ClockSrc::MSI(MSIRange::Range6), | 62 | mux: ClockSrc::MSI(MSIRange::RANGE4M), |
| 241 | ahb_pre: AHBPrescaler::DIV1, | 63 | ahb_pre: AHBPrescaler::DIV1, |
| 242 | apb1_pre: APBPrescaler::DIV1, | 64 | apb1_pre: APBPrescaler::DIV1, |
| 243 | apb2_pre: APBPrescaler::DIV1, | 65 | apb2_pre: APBPrescaler::DIV1, |
| 244 | pllsai1: None, | 66 | pllsai1: None, |
| 245 | hsi48: false, | 67 | hsi48: false, |
| 68 | rtc_mux: RtcClockSource::LSI, | ||
| 69 | lsi: true, | ||
| 70 | lse: None, | ||
| 246 | } | 71 | } |
| 247 | } | 72 | } |
| 248 | } | 73 | } |
| 249 | 74 | ||
| 250 | pub(crate) unsafe fn init(config: Config) { | 75 | pub(crate) unsafe fn init(config: Config) { |
| 76 | // Switch to MSI to prevent problems with PLL configuration. | ||
| 77 | if !RCC.cr().read().msion() { | ||
| 78 | // Turn on MSI and configure it to 4MHz. | ||
| 79 | RCC.cr().modify(|w| { | ||
| 80 | w.set_msirgsel(true); // MSI Range is provided by MSIRANGE[3:0]. | ||
| 81 | w.set_msirange(MSIRange::RANGE4M); | ||
| 82 | w.set_msipllen(false); | ||
| 83 | w.set_msion(true) | ||
| 84 | }); | ||
| 85 | |||
| 86 | // Wait until MSI is running | ||
| 87 | while !RCC.cr().read().msirdy() {} | ||
| 88 | } | ||
| 89 | if RCC.cfgr().read().sws() != Sw::MSI { | ||
| 90 | // Set MSI as a clock source, reset prescalers. | ||
| 91 | RCC.cfgr().write_value(Cfgr::default()); | ||
| 92 | // Wait for clock switch status bits to change. | ||
| 93 | while RCC.cfgr().read().sws() != Sw::MSI {} | ||
| 94 | } | ||
| 95 | |||
| 96 | //BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default())); | ||
| 97 | |||
| 251 | PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0)); | 98 | PWR.cr1().modify(|w| w.set_vos(stm32_metapac::pwr::vals::Vos::RANGE0)); |
| 252 | let (sys_clk, sw) = match config.mux { | 99 | let (sys_clk, sw) = match config.mux { |
| 253 | ClockSrc::MSI(range) => { | 100 | ClockSrc::MSI(range) => { |
| @@ -255,47 +102,53 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 255 | RCC.cr().write(|w| { | 102 | RCC.cr().write(|w| { |
| 256 | let bits: Msirange = range.into(); | 103 | let bits: Msirange = range.into(); |
| 257 | w.set_msirange(bits); | 104 | w.set_msirange(bits); |
| 258 | w.set_msipllen(false); | ||
| 259 | w.set_msirgsel(true); | 105 | w.set_msirgsel(true); |
| 260 | w.set_msion(true); | 106 | w.set_msion(true); |
| 107 | |||
| 108 | if config.rtc_mux == RtcClockSource::LSE { | ||
| 109 | // If LSE is enabled, enable calibration of MSI | ||
| 110 | w.set_msipllen(true); | ||
| 111 | } else { | ||
| 112 | w.set_msipllen(false); | ||
| 113 | } | ||
| 261 | }); | 114 | }); |
| 262 | while !RCC.cr().read().msirdy() {} | 115 | while !RCC.cr().read().msirdy() {} |
| 263 | 116 | ||
| 264 | // Enable as clock source for USB, RNG if running at 48 MHz | 117 | // Enable as clock source for USB, RNG if running at 48 MHz |
| 265 | if let MSIRange::Range11 = range { | 118 | if range == MSIRange::RANGE48M { |
| 266 | RCC.ccipr1().modify(|w| { | 119 | RCC.ccipr1().modify(|w| { |
| 267 | w.set_clk48msel(0b11); | 120 | w.set_clk48msel(0b11); |
| 268 | }); | 121 | }); |
| 269 | } | 122 | } |
| 270 | (range.into(), Sw::MSI) | 123 | (msirange_to_hertz(range), Sw::MSI) |
| 271 | } | 124 | } |
| 272 | ClockSrc::HSI16 => { | 125 | ClockSrc::HSI16 => { |
| 273 | // Enable HSI16 | 126 | // Enable HSI16 |
| 274 | RCC.cr().write(|w| w.set_hsion(true)); | 127 | RCC.cr().write(|w| w.set_hsion(true)); |
| 275 | while !RCC.cr().read().hsirdy() {} | 128 | while !RCC.cr().read().hsirdy() {} |
| 276 | 129 | ||
| 277 | (HSI_FREQ.0, Sw::HSI16) | 130 | (HSI_FREQ, Sw::HSI16) |
| 278 | } | 131 | } |
| 279 | ClockSrc::HSE(freq) => { | 132 | ClockSrc::HSE(freq) => { |
| 280 | // Enable HSE | 133 | // Enable HSE |
| 281 | RCC.cr().write(|w| w.set_hseon(true)); | 134 | RCC.cr().write(|w| w.set_hseon(true)); |
| 282 | while !RCC.cr().read().hserdy() {} | 135 | while !RCC.cr().read().hserdy() {} |
| 283 | 136 | ||
| 284 | (freq.0, Sw::HSE) | 137 | (freq, Sw::HSE) |
| 285 | } | 138 | } |
| 286 | ClockSrc::PLL(src, div, prediv, mul, pll48div) => { | 139 | ClockSrc::PLL(src, divr, prediv, mul, divq) => { |
| 287 | let src_freq = match src { | 140 | let src_freq = match src { |
| 288 | PLLSource::HSE(freq) => { | 141 | PLLSource::HSE(freq) => { |
| 289 | // Enable HSE | 142 | // Enable HSE |
| 290 | RCC.cr().write(|w| w.set_hseon(true)); | 143 | RCC.cr().write(|w| w.set_hseon(true)); |
| 291 | while !RCC.cr().read().hserdy() {} | 144 | while !RCC.cr().read().hserdy() {} |
| 292 | freq.0 | 145 | freq |
| 293 | } | 146 | } |
| 294 | PLLSource::HSI16 => { | 147 | PLLSource::HSI16 => { |
| 295 | // Enable HSI | 148 | // Enable HSI |
| 296 | RCC.cr().write(|w| w.set_hsion(true)); | 149 | RCC.cr().write(|w| w.set_hsion(true)); |
| 297 | while !RCC.cr().read().hsirdy() {} | 150 | while !RCC.cr().read().hsirdy() {} |
| 298 | HSI_FREQ.0 | 151 | HSI_FREQ |
| 299 | } | 152 | } |
| 300 | PLLSource::MSI(range) => { | 153 | PLLSource::MSI(range) => { |
| 301 | // Enable MSI | 154 | // Enable MSI |
| @@ -307,7 +160,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 307 | w.set_msion(true); | 160 | w.set_msion(true); |
| 308 | }); | 161 | }); |
| 309 | while !RCC.cr().read().msirdy() {} | 162 | while !RCC.cr().read().msirdy() {} |
| 310 | range.into() | 163 | |
| 164 | msirange_to_hertz(range) | ||
| 311 | } | 165 | } |
| 312 | }; | 166 | }; |
| 313 | 167 | ||
| @@ -315,23 +169,23 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 315 | RCC.cr().modify(|w| w.set_pllon(false)); | 169 | RCC.cr().modify(|w| w.set_pllon(false)); |
| 316 | while RCC.cr().read().pllrdy() {} | 170 | while RCC.cr().read().pllrdy() {} |
| 317 | 171 | ||
| 318 | let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div(); | 172 | let freq = src_freq / prediv * mul / divr; |
| 319 | 173 | ||
| 320 | RCC.pllcfgr().write(move |w| { | 174 | RCC.pllcfgr().write(move |w| { |
| 321 | w.set_plln(mul.into()); | 175 | w.set_plln(mul); |
| 322 | w.set_pllm(prediv.into()); | 176 | w.set_pllm(prediv); |
| 323 | w.set_pllr(div.into()); | 177 | w.set_pllr(divr); |
| 324 | if let Some(pll48div) = pll48div { | 178 | if let Some(divq) = divq { |
| 325 | w.set_pllq(pll48div.into()); | 179 | w.set_pllq(divq); |
| 326 | w.set_pllqen(true); | 180 | w.set_pllqen(true); |
| 327 | } | 181 | } |
| 328 | w.set_pllsrc(src.into()); | 182 | w.set_pllsrc(src.into()); |
| 329 | }); | 183 | }); |
| 330 | 184 | ||
| 331 | // Enable as clock source for USB, RNG if PLL48 divisor is provided | 185 | // Enable as clock source for USB, RNG if PLL48 divisor is provided |
| 332 | if let Some(pll48div) = pll48div { | 186 | if let Some(divq) = divq { |
| 333 | let freq = (src_freq / prediv.to_div() * mul.to_mul()) / pll48div.to_div(); | 187 | let freq = src_freq / prediv * mul / divq; |
| 334 | assert!(freq == 48_000_000); | 188 | assert!(freq.0 == 48_000_000); |
| 335 | RCC.ccipr1().modify(|w| { | 189 | RCC.ccipr1().modify(|w| { |
| 336 | w.set_clk48msel(0b10); | 190 | w.set_clk48msel(0b10); |
| 337 | }); | 191 | }); |
| @@ -339,25 +193,25 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 339 | 193 | ||
| 340 | if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { | 194 | if let Some((mul, prediv, r_div, q_div, p_div)) = config.pllsai1 { |
| 341 | RCC.pllsai1cfgr().write(move |w| { | 195 | RCC.pllsai1cfgr().write(move |w| { |
| 342 | w.set_pllsai1n(mul.into()); | 196 | w.set_plln(mul); |
| 343 | w.set_pllsai1m(prediv.into()); | 197 | w.set_pllm(prediv); |
| 344 | if let Some(r_div) = r_div { | 198 | if let Some(r_div) = r_div { |
| 345 | w.set_pllsai1r(r_div.into()); | 199 | w.set_pllr(r_div); |
| 346 | w.set_pllsai1ren(true); | 200 | w.set_pllren(true); |
| 347 | } | 201 | } |
| 348 | if let Some(q_div) = q_div { | 202 | if let Some(q_div) = q_div { |
| 349 | w.set_pllsai1q(q_div.into()); | 203 | w.set_pllq(q_div); |
| 350 | w.set_pllsai1qen(true); | 204 | w.set_pllqen(true); |
| 351 | let freq = (src_freq / prediv.to_div() * mul.to_mul()) / q_div.to_div(); | 205 | let freq = src_freq / prediv * mul / q_div; |
| 352 | if freq == 48_000_000 { | 206 | if freq.0 == 48_000_000 { |
| 353 | RCC.ccipr1().modify(|w| { | 207 | RCC.ccipr1().modify(|w| { |
| 354 | w.set_clk48msel(0b1); | 208 | w.set_clk48msel(0b1); |
| 355 | }); | 209 | }); |
| 356 | } | 210 | } |
| 357 | } | 211 | } |
| 358 | if let Some(p_div) = p_div { | 212 | if let Some(p_div) = p_div { |
| 359 | w.set_pllsai1pdiv(p_div.into()); | 213 | w.set_pllp(p_div); |
| 360 | w.set_pllsai1pen(true); | 214 | w.set_pllpen(true); |
| 361 | } | 215 | } |
| 362 | }); | 216 | }); |
| 363 | 217 | ||
| @@ -384,7 +238,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 384 | // Set flash wait states | 238 | // Set flash wait states |
| 385 | // VCORE Range 0 (performance), others TODO | 239 | // VCORE Range 0 (performance), others TODO |
| 386 | FLASH.acr().modify(|w| { | 240 | FLASH.acr().modify(|w| { |
| 387 | w.set_latency(match sys_clk { | 241 | w.set_latency(match sys_clk.0 { |
| 388 | 0..=20_000_000 => 0, | 242 | 0..=20_000_000 => 0, |
| 389 | 0..=40_000_000 => 1, | 243 | 0..=40_000_000 => 1, |
| 390 | 0..=60_000_000 => 2, | 244 | 0..=60_000_000 => 2, |
| @@ -401,43 +255,50 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 401 | w.set_ppre2(config.apb2_pre.into()); | 255 | w.set_ppre2(config.apb2_pre.into()); |
| 402 | }); | 256 | }); |
| 403 | 257 | ||
| 404 | let ahb_freq: u32 = match config.ahb_pre { | 258 | let ahb_freq = sys_clk / config.ahb_pre; |
| 405 | AHBPrescaler::DIV1 => sys_clk, | ||
| 406 | pre => { | ||
| 407 | let pre: Hpre = pre.into(); | ||
| 408 | let pre = 1 << (pre.to_bits() as u32 - 7); | ||
| 409 | sys_clk / pre | ||
| 410 | } | ||
| 411 | }; | ||
| 412 | 259 | ||
| 413 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { | 260 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { |
| 414 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 261 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 415 | pre => { | 262 | pre => { |
| 416 | let pre: Ppre = pre.into(); | 263 | let freq = ahb_freq / pre; |
| 417 | let pre: u8 = 1 << (pre.to_bits() - 3); | 264 | (freq, freq * 2u32) |
| 418 | let freq = ahb_freq / pre as u32; | ||
| 419 | (freq, freq * 2) | ||
| 420 | } | 265 | } |
| 421 | }; | 266 | }; |
| 422 | 267 | ||
| 423 | let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { | 268 | let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { |
| 424 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 269 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 425 | pre => { | 270 | pre => { |
| 426 | let pre: Ppre = pre.into(); | 271 | let freq = ahb_freq / pre; |
| 427 | let pre: u8 = 1 << (pre.to_bits() - 3); | 272 | (freq, freq * 2u32) |
| 428 | let freq = ahb_freq / pre as u32; | ||
| 429 | (freq, freq * 2) | ||
| 430 | } | 273 | } |
| 431 | }; | 274 | }; |
| 432 | 275 | ||
| 433 | set_freqs(Clocks { | 276 | set_freqs(Clocks { |
| 434 | sys: Hertz(sys_clk), | 277 | sys: sys_clk, |
| 435 | ahb1: Hertz(ahb_freq), | 278 | ahb1: ahb_freq, |
| 436 | ahb2: Hertz(ahb_freq), | 279 | ahb2: ahb_freq, |
| 437 | ahb3: Hertz(ahb_freq), | 280 | ahb3: ahb_freq, |
| 438 | apb1: Hertz(apb1_freq), | 281 | apb1: apb1_freq, |
| 439 | apb2: Hertz(apb2_freq), | 282 | apb2: apb2_freq, |
| 440 | apb1_tim: Hertz(apb1_tim_freq), | 283 | apb1_tim: apb1_tim_freq, |
| 441 | apb2_tim: Hertz(apb2_tim_freq), | 284 | apb2_tim: apb2_tim_freq, |
| 442 | }); | 285 | }); |
| 443 | } | 286 | } |
| 287 | |||
| 288 | fn msirange_to_hertz(range: Msirange) -> Hertz { | ||
| 289 | match range { | ||
| 290 | MSIRange::RANGE100K => Hertz(100_000), | ||
| 291 | MSIRange::RANGE200K => Hertz(200_000), | ||
| 292 | MSIRange::RANGE400K => Hertz(400_000), | ||
| 293 | MSIRange::RANGE800K => Hertz(800_000), | ||
| 294 | MSIRange::RANGE1M => Hertz(1_000_000), | ||
| 295 | MSIRange::RANGE2M => Hertz(2_000_000), | ||
| 296 | MSIRange::RANGE4M => Hertz(4_000_000), | ||
| 297 | MSIRange::RANGE8M => Hertz(8_000_000), | ||
| 298 | MSIRange::RANGE16M => Hertz(16_000_000), | ||
| 299 | MSIRange::RANGE24M => Hertz(24_000_000), | ||
| 300 | MSIRange::RANGE32M => Hertz(32_000_000), | ||
| 301 | MSIRange::RANGE48M => Hertz(48_000_000), | ||
| 302 | _ => unreachable!(), | ||
| 303 | } | ||
| 304 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index a32990890..52dc386b4 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -6,7 +6,6 @@ pub use crate::rcc::bd::RtcClockSource; | |||
| 6 | use crate::time::Hertz; | 6 | use crate::time::Hertz; |
| 7 | 7 | ||
| 8 | pub(crate) mod bd; | 8 | pub(crate) mod bd; |
| 9 | mod bus; | ||
| 10 | mod mco; | 9 | mod mco; |
| 11 | pub use mco::*; | 10 | pub use mco::*; |
| 12 | 11 | ||
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 14b8577df..d8fb17301 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllmboost, Pllrge, Pllsrc, Sw}; | 1 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Msirange, Plldiv, Pllm, Plln, Ppre as APBPrescaler}; |
| 2 | 2 | use crate::pac::rcc::vals::{Msirgsel, Pllmboost, Pllrge, Pllsrc, Sw}; | |
| 3 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | ||
| 4 | use crate::pac::{FLASH, PWR, RCC}; | 3 | use crate::pac::{FLASH, PWR, RCC}; |
| 5 | use crate::rcc::{set_freqs, Clocks}; | 4 | use crate::rcc::{set_freqs, Clocks}; |
| 6 | use crate::time::Hertz; | 5 | use crate::time::Hertz; |
| @@ -16,7 +15,7 @@ pub use crate::pac::pwr::vals::Vos as VoltageScale; | |||
| 16 | #[derive(Copy, Clone)] | 15 | #[derive(Copy, Clone)] |
| 17 | pub enum ClockSrc { | 16 | pub enum ClockSrc { |
| 18 | /// Use an internal medium speed oscillator (MSIS) as the system clock. | 17 | /// Use an internal medium speed oscillator (MSIS) as the system clock. |
| 19 | MSI(MSIRange), | 18 | MSI(Msirange), |
| 20 | /// Use the external high speed clock as the system clock. | 19 | /// Use the external high speed clock as the system clock. |
| 21 | /// | 20 | /// |
| 22 | /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must | 21 | /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must |
| @@ -31,29 +30,29 @@ pub enum ClockSrc { | |||
| 31 | impl Default for ClockSrc { | 30 | impl Default for ClockSrc { |
| 32 | fn default() -> Self { | 31 | fn default() -> Self { |
| 33 | // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9 | 32 | // The default system clock source is MSIS @ 4 MHz, per RM0456 § 11.4.9 |
| 34 | ClockSrc::MSI(MSIRange::Range4mhz) | 33 | ClockSrc::MSI(Msirange::RANGE_4MHZ) |
| 35 | } | 34 | } |
| 36 | } | 35 | } |
| 37 | 36 | ||
| 38 | #[derive(Clone, Copy, Debug)] | 37 | #[derive(Clone, Copy)] |
| 39 | pub struct PllConfig { | 38 | pub struct PllConfig { |
| 40 | /// The clock source for the PLL. | 39 | /// The clock source for the PLL. |
| 41 | pub source: PllSrc, | 40 | pub source: PllSrc, |
| 42 | /// The PLL prescaler. | 41 | /// The PLL prescaler. |
| 43 | /// | 42 | /// |
| 44 | /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. | 43 | /// The clock speed of the `source` divided by `m` must be between 4 and 16 MHz. |
| 45 | pub m: PllM, | 44 | pub m: Pllm, |
| 46 | /// The PLL multiplier. | 45 | /// The PLL multiplier. |
| 47 | /// | 46 | /// |
| 48 | /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 | 47 | /// The multiplied clock – `source` divided by `m` times `n` – must be between 128 and 544 |
| 49 | /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. | 48 | /// MHz. The upper limit may be lower depending on the `Config { voltage_range }`. |
| 50 | pub n: PllN, | 49 | pub n: Plln, |
| 51 | /// The divider for the R output. | 50 | /// The divider for the R output. |
| 52 | /// | 51 | /// |
| 53 | /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` | 52 | /// When used to drive the system clock, `source` divided by `m` times `n` divided by `r` |
| 54 | /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default | 53 | /// must not exceed 160 MHz. System clocks above 55 MHz require a non-default |
| 55 | /// `Config { voltage_range }`. | 54 | /// `Config { voltage_range }`. |
| 56 | pub r: PllClkDiv, | 55 | pub r: Plldiv, |
| 57 | } | 56 | } |
| 58 | 57 | ||
| 59 | impl PllConfig { | 58 | impl PllConfig { |
| @@ -61,27 +60,27 @@ impl PllConfig { | |||
| 61 | pub const fn hsi16_160mhz() -> Self { | 60 | pub const fn hsi16_160mhz() -> Self { |
| 62 | PllConfig { | 61 | PllConfig { |
| 63 | source: PllSrc::HSI16, | 62 | source: PllSrc::HSI16, |
| 64 | m: PllM::NotDivided, | 63 | m: Pllm::DIV1, |
| 65 | n: PllN::Mul10, | 64 | n: Plln::MUL10, |
| 66 | r: PllClkDiv::NotDivided, | 65 | r: Plldiv::DIV1, |
| 67 | } | 66 | } |
| 68 | } | 67 | } |
| 69 | 68 | ||
| 70 | /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz | 69 | /// A configuration for MSIS @ 48 MHz / 3 * 10 / 1 = 160 MHz |
| 71 | pub const fn msis_160mhz() -> Self { | 70 | pub const fn msis_160mhz() -> Self { |
| 72 | PllConfig { | 71 | PllConfig { |
| 73 | source: PllSrc::MSIS(MSIRange::Range48mhz), | 72 | source: PllSrc::MSIS(Msirange::RANGE_48MHZ), |
| 74 | m: PllM::Div3, | 73 | m: Pllm::DIV3, |
| 75 | n: PllN::Mul10, | 74 | n: Plln::MUL10, |
| 76 | r: PllClkDiv::NotDivided, | 75 | r: Plldiv::DIV1, |
| 77 | } | 76 | } |
| 78 | } | 77 | } |
| 79 | } | 78 | } |
| 80 | 79 | ||
| 81 | #[derive(Clone, Copy, Debug)] | 80 | #[derive(Clone, Copy)] |
| 82 | pub enum PllSrc { | 81 | pub enum PllSrc { |
| 83 | /// Use an internal medium speed oscillator as the PLL source. | 82 | /// Use an internal medium speed oscillator as the PLL source. |
| 84 | MSIS(MSIRange), | 83 | MSIS(Msirange), |
| 85 | /// Use the external high speed clock as the system PLL source. | 84 | /// Use the external high speed clock as the system PLL source. |
| 86 | /// | 85 | /// |
| 87 | /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must | 86 | /// HSE clocks faster than 25 MHz require at least `VoltageScale::RANGE3`, and HSE clocks must |
| @@ -101,75 +100,6 @@ impl Into<Pllsrc> for PllSrc { | |||
| 101 | } | 100 | } |
| 102 | } | 101 | } |
| 103 | 102 | ||
| 104 | seq_macro::seq!(N in 2..=128 { | ||
| 105 | #[derive(Copy, Clone, Debug)] | ||
| 106 | pub enum PllClkDiv { | ||
| 107 | NotDivided = 1, | ||
| 108 | #( | ||
| 109 | Div~N = N, | ||
| 110 | )* | ||
| 111 | } | ||
| 112 | |||
| 113 | impl PllClkDiv { | ||
| 114 | fn to_div(&self) -> u8 { | ||
| 115 | match self { | ||
| 116 | PllClkDiv::NotDivided => 0, | ||
| 117 | #( | ||
| 118 | PllClkDiv::Div~N => N - 1, | ||
| 119 | )* | ||
| 120 | } | ||
| 121 | } | ||
| 122 | } | ||
| 123 | }); | ||
| 124 | |||
| 125 | seq_macro::seq!(N in 4..=512 { | ||
| 126 | #[derive(Copy, Clone, Debug)] | ||
| 127 | pub enum PllN { | ||
| 128 | NotMultiplied = 1, | ||
| 129 | #( | ||
| 130 | Mul~N = N, | ||
| 131 | )* | ||
| 132 | } | ||
| 133 | |||
| 134 | impl PllN { | ||
| 135 | fn to_mul(&self) -> u16 { | ||
| 136 | match self { | ||
| 137 | PllN::NotMultiplied => 0, | ||
| 138 | #( | ||
| 139 | PllN::Mul~N => N - 1, | ||
| 140 | )* | ||
| 141 | } | ||
| 142 | } | ||
| 143 | } | ||
| 144 | }); | ||
| 145 | |||
| 146 | // Pre-division | ||
| 147 | #[derive(Copy, Clone, Debug)] | ||
| 148 | pub enum PllM { | ||
| 149 | NotDivided = 0b0000, | ||
| 150 | Div2 = 0b0001, | ||
| 151 | Div3 = 0b0010, | ||
| 152 | Div4 = 0b0011, | ||
| 153 | Div5 = 0b0100, | ||
| 154 | Div6 = 0b0101, | ||
| 155 | Div7 = 0b0110, | ||
| 156 | Div8 = 0b0111, | ||
| 157 | Div9 = 0b1000, | ||
| 158 | Div10 = 0b1001, | ||
| 159 | Div11 = 0b1010, | ||
| 160 | Div12 = 0b1011, | ||
| 161 | Div13 = 0b1100, | ||
| 162 | Div14 = 0b1101, | ||
| 163 | Div15 = 0b1110, | ||
| 164 | Div16 = 0b1111, | ||
| 165 | } | ||
| 166 | |||
| 167 | impl Into<Pllm> for PllM { | ||
| 168 | fn into(self) -> Pllm { | ||
| 169 | Pllm::from_bits(self as u8) | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | impl Into<Sw> for ClockSrc { | 103 | impl Into<Sw> for ClockSrc { |
| 174 | fn into(self) -> Sw { | 104 | fn into(self) -> Sw { |
| 175 | match self { | 105 | match self { |
| @@ -181,56 +111,6 @@ impl Into<Sw> for ClockSrc { | |||
| 181 | } | 111 | } |
| 182 | } | 112 | } |
| 183 | 113 | ||
| 184 | #[derive(Debug, Copy, Clone)] | ||
| 185 | pub enum MSIRange { | ||
| 186 | /// The 48 MHz MSI speed is unavailable in `VoltageScale::RANGE4`. | ||
| 187 | Range48mhz = 48_000_000, | ||
| 188 | Range24mhz = 24_000_000, | ||
| 189 | Range16mhz = 16_000_000, | ||
| 190 | Range12mhz = 12_000_000, | ||
| 191 | Range4mhz = 4_000_000, | ||
| 192 | Range2mhz = 2_000_000, | ||
| 193 | Range1_33mhz = 1_330_000, | ||
| 194 | Range1mhz = 1_000_000, | ||
| 195 | Range3_072mhz = 3_072_000, | ||
| 196 | Range1_536mhz = 1_536_000, | ||
| 197 | Range1_024mhz = 1_024_000, | ||
| 198 | Range768khz = 768_000, | ||
| 199 | Range400khz = 400_000, | ||
| 200 | Range200khz = 200_000, | ||
| 201 | Range133khz = 133_000, | ||
| 202 | Range100khz = 100_000, | ||
| 203 | } | ||
| 204 | |||
| 205 | impl Into<u32> for MSIRange { | ||
| 206 | fn into(self) -> u32 { | ||
| 207 | self as u32 | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | impl Into<Msirange> for MSIRange { | ||
| 212 | fn into(self) -> Msirange { | ||
| 213 | match self { | ||
| 214 | MSIRange::Range48mhz => Msirange::RANGE_48MHZ, | ||
| 215 | MSIRange::Range24mhz => Msirange::RANGE_24MHZ, | ||
| 216 | MSIRange::Range16mhz => Msirange::RANGE_16MHZ, | ||
| 217 | MSIRange::Range12mhz => Msirange::RANGE_12MHZ, | ||
| 218 | MSIRange::Range4mhz => Msirange::RANGE_4MHZ, | ||
| 219 | MSIRange::Range2mhz => Msirange::RANGE_2MHZ, | ||
| 220 | MSIRange::Range1_33mhz => Msirange::RANGE_1_33MHZ, | ||
| 221 | MSIRange::Range1mhz => Msirange::RANGE_1MHZ, | ||
| 222 | MSIRange::Range3_072mhz => Msirange::RANGE_3_072MHZ, | ||
| 223 | MSIRange::Range1_536mhz => Msirange::RANGE_1_536MHZ, | ||
| 224 | MSIRange::Range1_024mhz => Msirange::RANGE_1_024MHZ, | ||
| 225 | MSIRange::Range768khz => Msirange::RANGE_768KHZ, | ||
| 226 | MSIRange::Range400khz => Msirange::RANGE_400KHZ, | ||
| 227 | MSIRange::Range200khz => Msirange::RANGE_200KHZ, | ||
| 228 | MSIRange::Range133khz => Msirange::RANGE_133KHZ, | ||
| 229 | MSIRange::Range100khz => Msirange::RANGE_100KHZ, | ||
| 230 | } | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | #[derive(Copy, Clone)] | 114 | #[derive(Copy, Clone)] |
| 235 | pub struct Config { | 115 | pub struct Config { |
| 236 | pub mux: ClockSrc, | 116 | pub mux: ClockSrc, |
| @@ -273,11 +153,11 @@ impl Config { | |||
| 273 | frequency | 153 | frequency |
| 274 | } | 154 | } |
| 275 | 155 | ||
| 276 | unsafe fn init_msis(&self, range: MSIRange) -> Hertz { | 156 | unsafe fn init_msis(&self, range: Msirange) -> Hertz { |
| 277 | // Check MSI output per RM0456 § 11.4.10 | 157 | // Check MSI output per RM0456 § 11.4.10 |
| 278 | match self.voltage_range { | 158 | match self.voltage_range { |
| 279 | VoltageScale::RANGE4 => { | 159 | VoltageScale::RANGE4 => { |
| 280 | assert!(range as u32 <= 24_000_000); | 160 | assert!(msirange_to_hertz(range).0 <= 24_000_000); |
| 281 | } | 161 | } |
| 282 | _ => {} | 162 | _ => {} |
| 283 | } | 163 | } |
| @@ -291,8 +171,7 @@ impl Config { | |||
| 291 | } | 171 | } |
| 292 | 172 | ||
| 293 | RCC.icscr1().modify(|w| { | 173 | RCC.icscr1().modify(|w| { |
| 294 | let bits: Msirange = range.into(); | 174 | w.set_msisrange(range); |
| 295 | w.set_msisrange(bits); | ||
| 296 | w.set_msirgsel(Msirgsel::RCC_ICSCR1); | 175 | w.set_msirgsel(Msirgsel::RCC_ICSCR1); |
| 297 | }); | 176 | }); |
| 298 | RCC.cr().write(|w| { | 177 | RCC.cr().write(|w| { |
| @@ -300,7 +179,7 @@ impl Config { | |||
| 300 | w.set_msison(true); | 179 | w.set_msison(true); |
| 301 | }); | 180 | }); |
| 302 | while !RCC.cr().read().msisrdy() {} | 181 | while !RCC.cr().read().msisrdy() {} |
| 303 | Hertz(range as u32) | 182 | msirange_to_hertz(range) |
| 304 | } | 183 | } |
| 305 | } | 184 | } |
| 306 | 185 | ||
| @@ -344,14 +223,14 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 344 | }; | 223 | }; |
| 345 | 224 | ||
| 346 | // Calculate the reference clock, which is the source divided by m | 225 | // Calculate the reference clock, which is the source divided by m |
| 347 | let reference_clk = source_clk / (pll.m as u8 as u32 + 1); | 226 | let reference_clk = source_clk / pll.m; |
| 348 | 227 | ||
| 349 | // Check limits per RM0456 § 11.4.6 | 228 | // Check limits per RM0456 § 11.4.6 |
| 350 | assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16)); | 229 | assert!(Hertz::mhz(4) <= reference_clk && reference_clk <= Hertz::mhz(16)); |
| 351 | 230 | ||
| 352 | // Calculate the PLL1 VCO clock and PLL1 R output clock | 231 | // Calculate the PLL1 VCO clock and PLL1 R output clock |
| 353 | let pll1_clk = reference_clk * (pll.n as u8 as u32); | 232 | let pll1_clk = reference_clk * pll.n; |
| 354 | let pll1r_clk = pll1_clk / (pll.r as u8 as u32); | 233 | let pll1r_clk = pll1_clk / pll.r; |
| 355 | 234 | ||
| 356 | // Check system clock per RM0456 § 11.4.9 | 235 | // Check system clock per RM0456 § 11.4.9 |
| 357 | assert!(pll1r_clk <= Hertz::mhz(160)); | 236 | assert!(pll1r_clk <= Hertz::mhz(160)); |
| @@ -387,11 +266,11 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 387 | Pllmboost::DIV2 | 266 | Pllmboost::DIV2 |
| 388 | } else { | 267 | } else { |
| 389 | // Bypass, giving EPOD 4-16 MHz | 268 | // Bypass, giving EPOD 4-16 MHz |
| 390 | Pllmboost::BYPASS | 269 | Pllmboost::DIV1 |
| 391 | } | 270 | } |
| 392 | } else { | 271 | } else { |
| 393 | // Nothing to do | 272 | // Nothing to do |
| 394 | Pllmboost::BYPASS | 273 | Pllmboost::DIV1 |
| 395 | }; | 274 | }; |
| 396 | 275 | ||
| 397 | // Disable the PLL, and wait for it to disable | 276 | // Disable the PLL, and wait for it to disable |
| @@ -402,7 +281,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 402 | RCC.pll1cfgr().write(|w| { | 281 | RCC.pll1cfgr().write(|w| { |
| 403 | // Configure PLL1 source and prescaler | 282 | // Configure PLL1 source and prescaler |
| 404 | w.set_pllsrc(pll.source.into()); | 283 | w.set_pllsrc(pll.source.into()); |
| 405 | w.set_pllm(pll.m.into()); | 284 | w.set_pllm(pll.m); |
| 406 | 285 | ||
| 407 | // Configure PLL1 input frequncy range | 286 | // Configure PLL1 input frequncy range |
| 408 | let input_range = if reference_clk <= Hertz::mhz(8) { | 287 | let input_range = if reference_clk <= Hertz::mhz(8) { |
| @@ -422,9 +301,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 422 | // Configure the PLL divisors | 301 | // Configure the PLL divisors |
| 423 | RCC.pll1divr().modify(|w| { | 302 | RCC.pll1divr().modify(|w| { |
| 424 | // Set the VCO multiplier | 303 | // Set the VCO multiplier |
| 425 | w.set_plln(pll.n.to_mul()); | 304 | w.set_plln(pll.n); |
| 426 | // Set the R output divisor | 305 | // Set the R output divisor |
| 427 | w.set_pllr(pll.r.to_div()); | 306 | w.set_pllr(pll.r); |
| 428 | }); | 307 | }); |
| 429 | 308 | ||
| 430 | // Do we need the EPOD booster to reach the target clock speed per § 10.5.4? | 309 | // Do we need the EPOD booster to reach the target clock speed per § 10.5.4? |
| @@ -442,8 +321,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 442 | 321 | ||
| 443 | pll1r_clk | 322 | pll1r_clk |
| 444 | } | 323 | } |
| 445 | } | 324 | }; |
| 446 | .0; | ||
| 447 | 325 | ||
| 448 | if config.hsi48 { | 326 | if config.hsi48 { |
| 449 | RCC.cr().modify(|w| w.set_hsi48on(true)); | 327 | RCC.cr().modify(|w| w.set_hsi48on(true)); |
| @@ -455,13 +333,13 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 455 | let wait_states = match config.voltage_range { | 333 | let wait_states = match config.voltage_range { |
| 456 | // VOS 1 range VCORE 1.26V - 1.40V | 334 | // VOS 1 range VCORE 1.26V - 1.40V |
| 457 | VoltageScale::RANGE1 => { | 335 | VoltageScale::RANGE1 => { |
| 458 | if sys_clk < 32_000_000 { | 336 | if sys_clk.0 < 32_000_000 { |
| 459 | 0 | 337 | 0 |
| 460 | } else if sys_clk < 64_000_000 { | 338 | } else if sys_clk.0 < 64_000_000 { |
| 461 | 1 | 339 | 1 |
| 462 | } else if sys_clk < 96_000_000 { | 340 | } else if sys_clk.0 < 96_000_000 { |
| 463 | 2 | 341 | 2 |
| 464 | } else if sys_clk < 128_000_000 { | 342 | } else if sys_clk.0 < 128_000_000 { |
| 465 | 3 | 343 | 3 |
| 466 | } else { | 344 | } else { |
| 467 | 4 | 345 | 4 |
| @@ -469,11 +347,11 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 469 | } | 347 | } |
| 470 | // VOS 2 range VCORE 1.15V - 1.26V | 348 | // VOS 2 range VCORE 1.15V - 1.26V |
| 471 | VoltageScale::RANGE2 => { | 349 | VoltageScale::RANGE2 => { |
| 472 | if sys_clk < 30_000_000 { | 350 | if sys_clk.0 < 30_000_000 { |
| 473 | 0 | 351 | 0 |
| 474 | } else if sys_clk < 60_000_000 { | 352 | } else if sys_clk.0 < 60_000_000 { |
| 475 | 1 | 353 | 1 |
| 476 | } else if sys_clk < 90_000_000 { | 354 | } else if sys_clk.0 < 90_000_000 { |
| 477 | 2 | 355 | 2 |
| 478 | } else { | 356 | } else { |
| 479 | 3 | 357 | 3 |
| @@ -481,9 +359,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 481 | } | 359 | } |
| 482 | // VOS 3 range VCORE 1.05V - 1.15V | 360 | // VOS 3 range VCORE 1.05V - 1.15V |
| 483 | VoltageScale::RANGE3 => { | 361 | VoltageScale::RANGE3 => { |
| 484 | if sys_clk < 24_000_000 { | 362 | if sys_clk.0 < 24_000_000 { |
| 485 | 0 | 363 | 0 |
| 486 | } else if sys_clk < 48_000_000 { | 364 | } else if sys_clk.0 < 48_000_000 { |
| 487 | 1 | 365 | 1 |
| 488 | } else { | 366 | } else { |
| 489 | 2 | 367 | 2 |
| @@ -491,7 +369,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 491 | } | 369 | } |
| 492 | // VOS 4 range VCORE 0.95V - 1.05V | 370 | // VOS 4 range VCORE 0.95V - 1.05V |
| 493 | VoltageScale::RANGE4 => { | 371 | VoltageScale::RANGE4 => { |
| 494 | if sys_clk < 12_000_000 { | 372 | if sys_clk.0 < 12_000_000 { |
| 495 | 0 | 373 | 0 |
| 496 | } else { | 374 | } else { |
| 497 | 1 | 375 | 1 |
| @@ -522,62 +400,70 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 522 | 400 | ||
| 523 | // Configure the bus prescalers | 401 | // Configure the bus prescalers |
| 524 | RCC.cfgr2().modify(|w| { | 402 | RCC.cfgr2().modify(|w| { |
| 525 | w.set_hpre(config.ahb_pre.into()); | 403 | w.set_hpre(config.ahb_pre); |
| 526 | w.set_ppre1(config.apb1_pre.into()); | 404 | w.set_ppre1(config.apb1_pre); |
| 527 | w.set_ppre2(config.apb2_pre.into()); | 405 | w.set_ppre2(config.apb2_pre); |
| 528 | }); | 406 | }); |
| 529 | RCC.cfgr3().modify(|w| { | 407 | RCC.cfgr3().modify(|w| { |
| 530 | w.set_ppre3(config.apb3_pre.into()); | 408 | w.set_ppre3(config.apb3_pre); |
| 531 | }); | 409 | }); |
| 532 | 410 | ||
| 533 | let ahb_freq: u32 = match config.ahb_pre { | 411 | let ahb_freq = sys_clk / config.ahb_pre; |
| 534 | AHBPrescaler::DIV1 => sys_clk, | ||
| 535 | pre => { | ||
| 536 | let pre: u8 = pre.into(); | ||
| 537 | let pre = 1 << (pre as u32 - 7); | ||
| 538 | sys_clk / pre | ||
| 539 | } | ||
| 540 | }; | ||
| 541 | 412 | ||
| 542 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { | 413 | let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { |
| 543 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 414 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 544 | pre => { | 415 | pre => { |
| 545 | let pre: u8 = pre.into(); | 416 | let freq = ahb_freq / pre; |
| 546 | let pre: u8 = 1 << (pre - 3); | 417 | (freq, freq * 2u32) |
| 547 | let freq = ahb_freq / pre as u32; | ||
| 548 | (freq, freq * 2) | ||
| 549 | } | 418 | } |
| 550 | }; | 419 | }; |
| 551 | 420 | ||
| 552 | let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { | 421 | let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { |
| 553 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 422 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 554 | pre => { | 423 | pre => { |
| 555 | let pre: u8 = pre.into(); | 424 | let freq = ahb_freq / pre; |
| 556 | let pre: u8 = 1 << (pre - 3); | 425 | (freq, freq * 2u32) |
| 557 | let freq = ahb_freq / pre as u32; | ||
| 558 | (freq, freq * 2) | ||
| 559 | } | 426 | } |
| 560 | }; | 427 | }; |
| 561 | 428 | ||
| 562 | let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre { | 429 | let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre { |
| 563 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), | 430 | APBPrescaler::DIV1 => (ahb_freq, ahb_freq), |
| 564 | pre => { | 431 | pre => { |
| 565 | let pre: u8 = pre.into(); | 432 | let freq = ahb_freq / pre; |
| 566 | let pre: u8 = 1 << (pre - 3); | 433 | (freq, freq * 2u32) |
| 567 | let freq = ahb_freq / pre as u32; | ||
| 568 | (freq, freq * 2) | ||
| 569 | } | 434 | } |
| 570 | }; | 435 | }; |
| 571 | 436 | ||
| 572 | set_freqs(Clocks { | 437 | set_freqs(Clocks { |
| 573 | sys: Hertz(sys_clk), | 438 | sys: sys_clk, |
| 574 | ahb1: Hertz(ahb_freq), | 439 | ahb1: ahb_freq, |
| 575 | ahb2: Hertz(ahb_freq), | 440 | ahb2: ahb_freq, |
| 576 | ahb3: Hertz(ahb_freq), | 441 | ahb3: ahb_freq, |
| 577 | apb1: Hertz(apb1_freq), | 442 | apb1: apb1_freq, |
| 578 | apb2: Hertz(apb2_freq), | 443 | apb2: apb2_freq, |
| 579 | apb3: Hertz(apb3_freq), | 444 | apb3: apb3_freq, |
| 580 | apb1_tim: Hertz(apb1_tim_freq), | 445 | apb1_tim: apb1_tim_freq, |
| 581 | apb2_tim: Hertz(apb2_tim_freq), | 446 | apb2_tim: apb2_tim_freq, |
| 582 | }); | 447 | }); |
| 583 | } | 448 | } |
| 449 | |||
| 450 | fn msirange_to_hertz(range: Msirange) -> Hertz { | ||
| 451 | match range { | ||
| 452 | Msirange::RANGE_48MHZ => Hertz(48_000_000), | ||
| 453 | Msirange::RANGE_24MHZ => Hertz(24_000_000), | ||
| 454 | Msirange::RANGE_16MHZ => Hertz(16_000_000), | ||
| 455 | Msirange::RANGE_12MHZ => Hertz(12_000_000), | ||
| 456 | Msirange::RANGE_4MHZ => Hertz(4_000_000), | ||
| 457 | Msirange::RANGE_2MHZ => Hertz(2_000_000), | ||
| 458 | Msirange::RANGE_1_33MHZ => Hertz(1_330_000), | ||
| 459 | Msirange::RANGE_1MHZ => Hertz(1_000_000), | ||
| 460 | Msirange::RANGE_3_072MHZ => Hertz(3_072_000), | ||
| 461 | Msirange::RANGE_1_536MHZ => Hertz(1_536_000), | ||
| 462 | Msirange::RANGE_1_024MHZ => Hertz(1_024_000), | ||
| 463 | Msirange::RANGE_768KHZ => Hertz(768_000), | ||
| 464 | Msirange::RANGE_400KHZ => Hertz(400_000), | ||
| 465 | Msirange::RANGE_200KHZ => Hertz(200_000), | ||
| 466 | Msirange::RANGE_133KHZ => Hertz(133_000), | ||
| 467 | Msirange::RANGE_100KHZ => Hertz(100_000), | ||
| 468 | } | ||
| 469 | } | ||
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index ee45a342b..ee2a8ae10 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | 1 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; |
| 2 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; | 2 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; |
| 3 | use crate::rcc::Clocks; | 3 | use crate::rcc::Clocks; |
| 4 | use crate::time::{khz, mhz, Hertz}; | 4 | use crate::time::{khz, mhz, Hertz}; |
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 937f55503..7baedfcdb 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | pub use super::bus::{AHBPrescaler, APBPrescaler}; | ||
| 2 | pub use crate::pac::pwr::vals::Vos as VoltageScale; | 1 | pub use crate::pac::pwr::vals::Vos as VoltageScale; |
| 3 | use crate::pac::rcc::vals::Adcsel; | 2 | use crate::pac::rcc::vals::Adcsel; |
| 3 | pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler}; | ||
| 4 | use crate::pac::{FLASH, RCC}; | 4 | use crate::pac::{FLASH, RCC}; |
| 5 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; | 5 | use crate::rcc::bd::{BackupDomain, RtcClockSource}; |
| 6 | use crate::rcc::{set_freqs, Clocks}; | 6 | use crate::rcc::{set_freqs, Clocks}; |
diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs index 894937614..62aaa9800 100644 --- a/examples/stm32f2/src/bin/pll.rs +++ b/examples/stm32f2/src/bin/pll.rs | |||
| @@ -7,7 +7,7 @@ use core::convert::TryFrom; | |||
| 7 | use defmt::*; | 7 | use defmt::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::rcc::{ | 9 | use embassy_stm32::rcc::{ |
| 10 | APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLL48Div, PLLConfig, PLLMainDiv, PLLMul, PLLPreDiv, PLLSrc, | 10 | APBPrescaler, ClockSrc, HSEConfig, HSESrc, PLLConfig, PLLMul, PLLPDiv, PLLPreDiv, PLLQDiv, PLLSrc, |
| 11 | }; | 11 | }; |
| 12 | use embassy_stm32::time::Hertz; | 12 | use embassy_stm32::time::Hertz; |
| 13 | use embassy_stm32::Config; | 13 | use embassy_stm32::Config; |
| @@ -32,9 +32,9 @@ async fn main(_spawner: Spawner) { | |||
| 32 | // 1 MHz PLL input * 240 = 240 MHz PLL VCO | 32 | // 1 MHz PLL input * 240 = 240 MHz PLL VCO |
| 33 | mul: unwrap!(PLLMul::try_from(240)), | 33 | mul: unwrap!(PLLMul::try_from(240)), |
| 34 | // 240 MHz PLL VCO / 2 = 120 MHz main PLL output | 34 | // 240 MHz PLL VCO / 2 = 120 MHz main PLL output |
| 35 | main_div: PLLMainDiv::Div2, | 35 | p_div: PLLPDiv::DIV2, |
| 36 | // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output | 36 | // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output |
| 37 | pll48_div: unwrap!(PLL48Div::try_from(5)), | 37 | q_div: PLLQDiv::DIV5, |
| 38 | }; | 38 | }; |
| 39 | // System clock comes from PLL (= the 120 MHz main PLL output) | 39 | // System clock comes from PLL (= the 120 MHz main PLL output) |
| 40 | config.rcc.mux = ClockSrc::PLL; | 40 | config.rcc.mux = ClockSrc::PLL; |
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs index a792748bc..da9b18a0e 100644 --- a/examples/stm32g4/src/bin/adc.rs +++ b/examples/stm32g4/src/bin/adc.rs | |||
| @@ -16,12 +16,12 @@ async fn main(_spawner: Spawner) { | |||
| 16 | 16 | ||
| 17 | config.rcc.pll = Some(Pll { | 17 | config.rcc.pll = Some(Pll { |
| 18 | source: PllSrc::HSI16, | 18 | source: PllSrc::HSI16, |
| 19 | prediv_m: PllM::Div4, | 19 | prediv_m: PllM::DIV4, |
| 20 | mul_n: PllN::Mul85, | 20 | mul_n: PllN::MUL85, |
| 21 | div_p: None, | 21 | div_p: None, |
| 22 | div_q: None, | 22 | div_q: None, |
| 23 | // Main system clock at 170 MHz | 23 | // Main system clock at 170 MHz |
| 24 | div_r: Some(PllR::Div2), | 24 | div_r: Some(PllR::DIV2), |
| 25 | }); | 25 | }); |
| 26 | 26 | ||
| 27 | config.rcc.adc12_clock_source = AdcClockSource::SysClk; | 27 | config.rcc.adc12_clock_source = AdcClockSource::SysClk; |
diff --git a/examples/stm32g4/src/bin/pll.rs b/examples/stm32g4/src/bin/pll.rs index ef7d4800c..f8159cb53 100644 --- a/examples/stm32g4/src/bin/pll.rs +++ b/examples/stm32g4/src/bin/pll.rs | |||
| @@ -15,12 +15,12 @@ async fn main(_spawner: Spawner) { | |||
| 15 | 15 | ||
| 16 | config.rcc.pll = Some(Pll { | 16 | config.rcc.pll = Some(Pll { |
| 17 | source: PllSrc::HSI16, | 17 | source: PllSrc::HSI16, |
| 18 | prediv_m: PllM::Div4, | 18 | prediv_m: PllM::DIV4, |
| 19 | mul_n: PllN::Mul85, | 19 | mul_n: PllN::MUL85, |
| 20 | div_p: None, | 20 | div_p: None, |
| 21 | div_q: None, | 21 | div_q: None, |
| 22 | // Main system clock at 170 MHz | 22 | // Main system clock at 170 MHz |
| 23 | div_r: Some(PllR::Div2), | 23 | div_r: Some(PllR::DIV2), |
| 24 | }); | 24 | }); |
| 25 | 25 | ||
| 26 | config.rcc.mux = ClockSrc::PLL; | 26 | config.rcc.mux = ClockSrc::PLL; |
diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs index 77cfa67d3..9099b609a 100644 --- a/examples/stm32g4/src/bin/usb_serial.rs +++ b/examples/stm32g4/src/bin/usb_serial.rs | |||
| @@ -25,16 +25,16 @@ async fn main(_spawner: Spawner) { | |||
| 25 | // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE. | 25 | // Change this to `false` to use the HSE clock source for the USB. This example assumes an 8MHz HSE. |
| 26 | const USE_HSI48: bool = true; | 26 | const USE_HSI48: bool = true; |
| 27 | 27 | ||
| 28 | let pllq_div = if USE_HSI48 { None } else { Some(PllQ::Div6) }; | 28 | let pllq_div = if USE_HSI48 { None } else { Some(PllQ::DIV6) }; |
| 29 | 29 | ||
| 30 | config.rcc.pll = Some(Pll { | 30 | config.rcc.pll = Some(Pll { |
| 31 | source: PllSrc::HSE(Hertz(8_000_000)), | 31 | source: PllSrc::HSE(Hertz(8_000_000)), |
| 32 | prediv_m: PllM::Div2, | 32 | prediv_m: PllM::DIV2, |
| 33 | mul_n: PllN::Mul72, | 33 | mul_n: PllN::MUL72, |
| 34 | div_p: None, | 34 | div_p: None, |
| 35 | div_q: pllq_div, | 35 | div_q: pllq_div, |
| 36 | // Main system clock at 144 MHz | 36 | // Main system clock at 144 MHz |
| 37 | div_r: Some(PllR::Div2), | 37 | div_r: Some(PllR::DIV2), |
| 38 | }); | 38 | }); |
| 39 | 39 | ||
| 40 | config.rcc.mux = ClockSrc::PLL; | 40 | config.rcc.mux = ClockSrc::PLL; |
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 4e92d0647..2f4454761 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs | |||
| @@ -9,7 +9,9 @@ use embassy_net::{Ipv4Address, Stack, StackResources}; | |||
| 9 | use embassy_stm32::eth::generic_smi::GenericSMI; | 9 | use embassy_stm32::eth::generic_smi::GenericSMI; |
| 10 | use embassy_stm32::eth::{Ethernet, PacketQueue}; | 10 | use embassy_stm32::eth::{Ethernet, PacketQueue}; |
| 11 | use embassy_stm32::peripherals::ETH; | 11 | use embassy_stm32::peripherals::ETH; |
| 12 | use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; | 12 | use embassy_stm32::rcc::{ |
| 13 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | ||
| 14 | }; | ||
| 13 | use embassy_stm32::rng::Rng; | 15 | use embassy_stm32::rng::Rng; |
| 14 | use embassy_stm32::time::Hertz; | 16 | use embassy_stm32::time::Hertz; |
| 15 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; | 17 | use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; |
| @@ -42,10 +44,10 @@ async fn main(spawner: Spawner) -> ! { | |||
| 42 | }); | 44 | }); |
| 43 | config.rcc.pll1 = Some(Pll { | 45 | config.rcc.pll1 = Some(Pll { |
| 44 | source: PllSource::Hse, | 46 | source: PllSource::Hse, |
| 45 | prediv: 2, | 47 | prediv: PllPreDiv::DIV2, |
| 46 | mul: 125, | 48 | mul: PllMul::MUL125, |
| 47 | divp: Some(2), | 49 | divp: Some(PllDiv::DIV2), |
| 48 | divq: Some(2), | 50 | divq: Some(PllDiv::DIV2), |
| 49 | divr: None, | 51 | divr: None, |
| 50 | }); | 52 | }); |
| 51 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | 53 | config.rcc.ahb_pre = AHBPrescaler::DIV1; |
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index cbe540a06..3b3c38e17 100644 --- a/examples/stm32h5/src/bin/usb_serial.rs +++ b/examples/stm32h5/src/bin/usb_serial.rs | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::{panic, *}; | 5 | use defmt::{panic, *}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; | 7 | use embassy_stm32::rcc::{ |
| 8 | AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk, VoltageScale, | ||
| 9 | }; | ||
| 8 | use embassy_stm32::time::Hertz; | 10 | use embassy_stm32::time::Hertz; |
| 9 | use embassy_stm32::usb::{Driver, Instance}; | 11 | use embassy_stm32::usb::{Driver, Instance}; |
| 10 | use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config}; | 12 | use embassy_stm32::{bind_interrupts, pac, peripherals, usb, Config}; |
| @@ -29,9 +31,9 @@ async fn main(_spawner: Spawner) { | |||
| 29 | }); | 31 | }); |
| 30 | config.rcc.pll1 = Some(Pll { | 32 | config.rcc.pll1 = Some(Pll { |
| 31 | source: PllSource::Hse, | 33 | source: PllSource::Hse, |
| 32 | prediv: 2, | 34 | prediv: PllPreDiv::DIV2, |
| 33 | mul: 125, | 35 | mul: PllMul::MUL125, |
| 34 | divp: Some(2), // 250mhz | 36 | divp: Some(PllDiv::DIV2), // 250mhz |
| 35 | divq: None, | 37 | divq: None, |
| 36 | divr: None, | 38 | divr: None, |
| 37 | }); | 39 | }); |
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs index 77922d4bc..7859b86db 100644 --- a/examples/stm32h7/src/bin/adc.rs +++ b/examples/stm32h7/src/bin/adc.rs | |||
| @@ -18,16 +18,16 @@ async fn main(_spawner: Spawner) { | |||
| 18 | config.rcc.csi = true; | 18 | config.rcc.csi = true; |
| 19 | config.rcc.pll_src = PllSource::Hsi; | 19 | config.rcc.pll_src = PllSource::Hsi; |
| 20 | config.rcc.pll1 = Some(Pll { | 20 | config.rcc.pll1 = Some(Pll { |
| 21 | prediv: 4, | 21 | prediv: PllPreDiv::DIV4, |
| 22 | mul: 50, | 22 | mul: PllMul::MUL50, |
| 23 | divp: Some(2), | 23 | divp: Some(PllDiv::DIV2), |
| 24 | divq: Some(8), // SPI1 cksel defaults to pll1_q | 24 | divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q |
| 25 | divr: None, | 25 | divr: None, |
| 26 | }); | 26 | }); |
| 27 | config.rcc.pll2 = Some(Pll { | 27 | config.rcc.pll2 = Some(Pll { |
| 28 | prediv: 4, | 28 | prediv: PllPreDiv::DIV4, |
| 29 | mul: 50, | 29 | mul: PllMul::MUL50, |
| 30 | divp: Some(8), // 100mhz | 30 | divp: Some(PllDiv::DIV8), // 100mhz |
| 31 | divq: None, | 31 | divq: None, |
| 32 | divr: None, | 32 | divr: None, |
| 33 | }); | 33 | }); |
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index 64ca65a02..40ef16cfc 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs | |||
| @@ -32,10 +32,10 @@ async fn main(_spawner: Spawner) { | |||
| 32 | config.rcc.csi = true; | 32 | config.rcc.csi = true; |
| 33 | config.rcc.pll_src = PllSource::Hsi; | 33 | config.rcc.pll_src = PllSource::Hsi; |
| 34 | config.rcc.pll1 = Some(Pll { | 34 | config.rcc.pll1 = Some(Pll { |
| 35 | prediv: 4, | 35 | prediv: PllPreDiv::DIV4, |
| 36 | mul: 50, | 36 | mul: PllMul::MUL50, |
| 37 | divp: Some(2), | 37 | divp: Some(PllDiv::DIV2), |
| 38 | divq: Some(8), // 100mhz | 38 | divq: Some(PllDiv::DIV8), // 100mhz |
| 39 | divr: None, | 39 | divr: None, |
| 40 | }); | 40 | }); |
| 41 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz | 41 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz |
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs index 93df7a319..821221897 100644 --- a/examples/stm32h7/src/bin/dac.rs +++ b/examples/stm32h7/src/bin/dac.rs | |||
| @@ -20,16 +20,16 @@ fn main() -> ! { | |||
| 20 | config.rcc.csi = true; | 20 | config.rcc.csi = true; |
| 21 | config.rcc.pll_src = PllSource::Hsi; | 21 | config.rcc.pll_src = PllSource::Hsi; |
| 22 | config.rcc.pll1 = Some(Pll { | 22 | config.rcc.pll1 = Some(Pll { |
| 23 | prediv: 4, | 23 | prediv: PllPreDiv::DIV4, |
| 24 | mul: 50, | 24 | mul: PllMul::MUL50, |
| 25 | divp: Some(2), | 25 | divp: Some(PllDiv::DIV2), |
| 26 | divq: Some(8), // SPI1 cksel defaults to pll1_q | 26 | divq: Some(PllDiv::DIV8), // 100mhz |
| 27 | divr: None, | 27 | divr: None, |
| 28 | }); | 28 | }); |
| 29 | config.rcc.pll2 = Some(Pll { | 29 | config.rcc.pll2 = Some(Pll { |
| 30 | prediv: 4, | 30 | prediv: PllPreDiv::DIV4, |
| 31 | mul: 50, | 31 | mul: PllMul::MUL50, |
| 32 | divp: Some(8), // 100mhz | 32 | divp: Some(PllDiv::DIV8), // 100mhz |
| 33 | divq: None, | 33 | divq: None, |
| 34 | divr: None, | 34 | divr: None, |
| 35 | }); | 35 | }); |
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index 8c921abca..933641ae4 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs | |||
| @@ -28,16 +28,16 @@ async fn main(spawner: Spawner) { | |||
| 28 | config.rcc.csi = true; | 28 | config.rcc.csi = true; |
| 29 | config.rcc.pll_src = PllSource::Hsi; | 29 | config.rcc.pll_src = PllSource::Hsi; |
| 30 | config.rcc.pll1 = Some(Pll { | 30 | config.rcc.pll1 = Some(Pll { |
| 31 | prediv: 4, | 31 | prediv: PllPreDiv::DIV4, |
| 32 | mul: 50, | 32 | mul: PllMul::MUL50, |
| 33 | divp: Some(2), | 33 | divp: Some(PllDiv::DIV2), |
| 34 | divq: Some(8), // SPI1 cksel defaults to pll1_q | 34 | divq: Some(PllDiv::DIV8), // 100mhz |
| 35 | divr: None, | 35 | divr: None, |
| 36 | }); | 36 | }); |
| 37 | config.rcc.pll2 = Some(Pll { | 37 | config.rcc.pll2 = Some(Pll { |
| 38 | prediv: 4, | 38 | prediv: PllPreDiv::DIV4, |
| 39 | mul: 50, | 39 | mul: PllMul::MUL50, |
| 40 | divp: Some(8), // 100mhz | 40 | divp: Some(PllDiv::DIV8), // 100mhz |
| 41 | divq: None, | 41 | divq: None, |
| 42 | divr: None, | 42 | divr: None, |
| 43 | }); | 43 | }); |
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index 1b5d71ed3..a6603d507 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs | |||
| @@ -39,9 +39,9 @@ async fn main(spawner: Spawner) -> ! { | |||
| 39 | config.rcc.hsi48 = true; // needed for RNG | 39 | config.rcc.hsi48 = true; // needed for RNG |
| 40 | config.rcc.pll_src = PllSource::Hsi; | 40 | config.rcc.pll_src = PllSource::Hsi; |
| 41 | config.rcc.pll1 = Some(Pll { | 41 | config.rcc.pll1 = Some(Pll { |
| 42 | prediv: 4, | 42 | prediv: PllPreDiv::DIV4, |
| 43 | mul: 50, | 43 | mul: PllMul::MUL50, |
| 44 | divp: Some(2), | 44 | divp: Some(PllDiv::DIV2), |
| 45 | divq: None, | 45 | divq: None, |
| 46 | divr: None, | 46 | divr: None, |
| 47 | }); | 47 | }); |
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 3abd31c73..596de2f40 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs | |||
| @@ -40,9 +40,9 @@ async fn main(spawner: Spawner) -> ! { | |||
| 40 | config.rcc.hsi48 = true; // needed for RNG | 40 | config.rcc.hsi48 = true; // needed for RNG |
| 41 | config.rcc.pll_src = PllSource::Hsi; | 41 | config.rcc.pll_src = PllSource::Hsi; |
| 42 | config.rcc.pll1 = Some(Pll { | 42 | config.rcc.pll1 = Some(Pll { |
| 43 | prediv: 4, | 43 | prediv: PllPreDiv::DIV4, |
| 44 | mul: 50, | 44 | mul: PllMul::MUL50, |
| 45 | divp: Some(2), | 45 | divp: Some(PllDiv::DIV2), |
| 46 | divq: None, | 46 | divq: None, |
| 47 | divr: None, | 47 | divr: None, |
| 48 | }); | 48 | }); |
diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs index de0b351df..7ae87b02c 100644 --- a/examples/stm32h7/src/bin/fmc.rs +++ b/examples/stm32h7/src/bin/fmc.rs | |||
| @@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) { | |||
| 18 | config.rcc.csi = true; | 18 | config.rcc.csi = true; |
| 19 | config.rcc.pll_src = PllSource::Hsi; | 19 | config.rcc.pll_src = PllSource::Hsi; |
| 20 | config.rcc.pll1 = Some(Pll { | 20 | config.rcc.pll1 = Some(Pll { |
| 21 | prediv: 4, | 21 | prediv: PllPreDiv::DIV4, |
| 22 | mul: 50, | 22 | mul: PllMul::MUL50, |
| 23 | divp: Some(2), | 23 | divp: Some(PllDiv::DIV2), |
| 24 | divq: Some(8), // 100mhz | 24 | divq: Some(PllDiv::DIV8), // 100mhz |
| 25 | divr: None, | 25 | divr: None, |
| 26 | }); | 26 | }); |
| 27 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz | 27 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz |
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index a1e955c39..f4fa06909 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs | |||
| @@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) { | |||
| 22 | config.rcc.hsi48 = true; // needed for RNG | 22 | config.rcc.hsi48 = true; // needed for RNG |
| 23 | config.rcc.pll_src = PllSource::Hsi; | 23 | config.rcc.pll_src = PllSource::Hsi; |
| 24 | config.rcc.pll1 = Some(Pll { | 24 | config.rcc.pll1 = Some(Pll { |
| 25 | prediv: 4, | 25 | prediv: PllPreDiv::DIV4, |
| 26 | mul: 50, | 26 | mul: PllMul::MUL50, |
| 27 | divp: Some(2), | 27 | divp: Some(PllDiv::DIV2), |
| 28 | divq: Some(8), // 100 Mhz | 28 | divq: Some(PllDiv::DIV8), // 100mhz |
| 29 | divr: None, | 29 | divr: None, |
| 30 | }); | 30 | }); |
| 31 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz | 31 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz |
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs index 5c8e57aa2..37e4c92cc 100644 --- a/examples/stm32h7/src/bin/pwm.rs +++ b/examples/stm32h7/src/bin/pwm.rs | |||
| @@ -21,9 +21,9 @@ async fn main(_spawner: Spawner) { | |||
| 21 | config.rcc.csi = true; | 21 | config.rcc.csi = true; |
| 22 | config.rcc.pll_src = PllSource::Hsi; | 22 | config.rcc.pll_src = PllSource::Hsi; |
| 23 | config.rcc.pll1 = Some(Pll { | 23 | config.rcc.pll1 = Some(Pll { |
| 24 | prediv: 4, | 24 | prediv: PllPreDiv::DIV4, |
| 25 | mul: 50, | 25 | mul: PllMul::MUL50, |
| 26 | divp: Some(2), | 26 | divp: Some(PllDiv::DIV2), |
| 27 | divq: None, | 27 | divq: None, |
| 28 | divr: None, | 28 | divr: None, |
| 29 | }); | 29 | }); |
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs index 752aefdf7..ecb8d6542 100644 --- a/examples/stm32h7/src/bin/sdmmc.rs +++ b/examples/stm32h7/src/bin/sdmmc.rs | |||
| @@ -22,10 +22,10 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 22 | config.rcc.csi = true; | 22 | config.rcc.csi = true; |
| 23 | config.rcc.pll_src = PllSource::Hsi; | 23 | config.rcc.pll_src = PllSource::Hsi; |
| 24 | config.rcc.pll1 = Some(Pll { | 24 | config.rcc.pll1 = Some(Pll { |
| 25 | prediv: 4, | 25 | prediv: PllPreDiv::DIV4, |
| 26 | mul: 50, | 26 | mul: PllMul::MUL50, |
| 27 | divp: Some(2), | 27 | divp: Some(PllDiv::DIV2), |
| 28 | divq: Some(4), // default clock chosen by SDMMCSEL. 200 Mhz | 28 | divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz |
| 29 | divr: None, | 29 | divr: None, |
| 30 | }); | 30 | }); |
| 31 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz | 31 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz |
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index 9fe46f031..f128d4a56 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs | |||
| @@ -44,10 +44,10 @@ fn main() -> ! { | |||
| 44 | config.rcc.csi = true; | 44 | config.rcc.csi = true; |
| 45 | config.rcc.pll_src = PllSource::Hsi; | 45 | config.rcc.pll_src = PllSource::Hsi; |
| 46 | config.rcc.pll1 = Some(Pll { | 46 | config.rcc.pll1 = Some(Pll { |
| 47 | prediv: 4, | 47 | prediv: PllPreDiv::DIV4, |
| 48 | mul: 50, | 48 | mul: PllMul::MUL50, |
| 49 | divp: Some(2), | 49 | divp: Some(PllDiv::DIV2), |
| 50 | divq: Some(4), // used by SPI3. 100Mhz. | 50 | divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. |
| 51 | divr: None, | 51 | divr: None, |
| 52 | }); | 52 | }); |
| 53 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz | 53 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz |
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index 88d65d5be..d4c0bcdbd 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs | |||
| @@ -40,10 +40,10 @@ fn main() -> ! { | |||
| 40 | config.rcc.csi = true; | 40 | config.rcc.csi = true; |
| 41 | config.rcc.pll_src = PllSource::Hsi; | 41 | config.rcc.pll_src = PllSource::Hsi; |
| 42 | config.rcc.pll1 = Some(Pll { | 42 | config.rcc.pll1 = Some(Pll { |
| 43 | prediv: 4, | 43 | prediv: PllPreDiv::DIV4, |
| 44 | mul: 50, | 44 | mul: PllMul::MUL50, |
| 45 | divp: Some(2), | 45 | divp: Some(PllDiv::DIV2), |
| 46 | divq: Some(4), // used by SPI3. 100Mhz. | 46 | divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. |
| 47 | divr: None, | 47 | divr: None, |
| 48 | }); | 48 | }); |
| 49 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz | 49 | config.rcc.sys = Sysclk::Pll1P; // 400 Mhz |
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs index 14de43568..c1e5144be 100644 --- a/examples/stm32h7/src/bin/usb_serial.rs +++ b/examples/stm32h7/src/bin/usb_serial.rs | |||
| @@ -28,9 +28,9 @@ async fn main(_spawner: Spawner) { | |||
| 28 | config.rcc.hsi48 = true; // needed for USB | 28 | config.rcc.hsi48 = true; // needed for USB |
| 29 | config.rcc.pll_src = PllSource::Hsi; | 29 | config.rcc.pll_src = PllSource::Hsi; |
| 30 | config.rcc.pll1 = Some(Pll { | 30 | config.rcc.pll1 = Some(Pll { |
| 31 | prediv: 4, | 31 | prediv: PllPreDiv::DIV4, |
| 32 | mul: 50, | 32 | mul: PllMul::MUL50, |
| 33 | divp: Some(2), | 33 | divp: Some(PllDiv::DIV2), |
| 34 | divq: None, | 34 | divq: None, |
| 35 | divr: None, | 35 | divr: None, |
| 36 | }); | 36 | }); |
diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs index 806e49f59..d0208d8a3 100644 --- a/examples/stm32l4/src/bin/rng.rs +++ b/examples/stm32l4/src/bin/rng.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; | 7 | use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv}; |
| 8 | use embassy_stm32::rng::Rng; | 8 | use embassy_stm32::rng::Rng; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -19,10 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 19 | // 72Mhz clock (16 / 1 * 18 / 4) | 19 | // 72Mhz clock (16 / 1 * 18 / 4) |
| 20 | config.rcc.mux = ClockSrc::PLL( | 20 | config.rcc.mux = ClockSrc::PLL( |
| 21 | PLLSource::HSI16, | 21 | PLLSource::HSI16, |
| 22 | PLLClkDiv::Div4, | 22 | PllRDiv::DIV4, |
| 23 | PLLSrcDiv::Div1, | 23 | PllPreDiv::DIV1, |
| 24 | PLLMul::Mul18, | 24 | PllMul::MUL18, |
| 25 | Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6) | 25 | Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6) |
| 26 | ); | 26 | ); |
| 27 | let p = embassy_stm32::init(config); | 27 | let p = embassy_stm32::init(config); |
| 28 | 28 | ||
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index eb1eed012..7e2b8c783 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | use chrono::{NaiveDate, NaiveDateTime}; | 5 | use chrono::{NaiveDate, NaiveDateTime}; |
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_stm32::rcc::{self, ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; | 8 | use embassy_stm32::rcc::{self, ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv}; |
| 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | 9 | use embassy_stm32::rtc::{Rtc, RtcConfig}; |
| 10 | use embassy_stm32::time::Hertz; | 10 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::Config; | 11 | use embassy_stm32::Config; |
| @@ -18,9 +18,9 @@ async fn main(_spawner: Spawner) { | |||
| 18 | let mut config = Config::default(); | 18 | let mut config = Config::default(); |
| 19 | config.rcc.mux = ClockSrc::PLL( | 19 | config.rcc.mux = ClockSrc::PLL( |
| 20 | PLLSource::HSE(Hertz::mhz(8)), | 20 | PLLSource::HSE(Hertz::mhz(8)), |
| 21 | PLLClkDiv::Div2, | 21 | PllRDiv::DIV2, |
| 22 | PLLSrcDiv::Div1, | 22 | PllPreDiv::DIV1, |
| 23 | PLLMul::Mul20, | 23 | PllMul::MUL20, |
| 24 | None, | 24 | None, |
| 25 | ); | 25 | ); |
| 26 | config.rcc.lse = Some(Hertz(32_768)); | 26 | config.rcc.lse = Some(Hertz(32_768)); |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index ba4a9d230..8db89be24 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -49,7 +49,7 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110}; | |||
| 49 | use embedded_hal_bus::spi::ExclusiveDevice; | 49 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 50 | use hal::gpio::Pull; | 50 | use hal::gpio::Pull; |
| 51 | use hal::i2c::Config as I2C_Config; | 51 | use hal::i2c::Config as I2C_Config; |
| 52 | use hal::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; | 52 | use hal::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllRDiv}; |
| 53 | use hal::spi::{Config as SPI_Config, Spi}; | 53 | use hal::spi::{Config as SPI_Config, Spi}; |
| 54 | use hal::time::Hertz; | 54 | use hal::time::Hertz; |
| 55 | 55 | ||
| @@ -80,9 +80,9 @@ async fn main(spawner: Spawner) { | |||
| 80 | // 80MHz highest frequency for flash 0 wait. | 80 | // 80MHz highest frequency for flash 0 wait. |
| 81 | config.rcc.mux = ClockSrc::PLL( | 81 | config.rcc.mux = ClockSrc::PLL( |
| 82 | PLLSource::HSE(Hertz(8_000_000)), | 82 | PLLSource::HSE(Hertz(8_000_000)), |
| 83 | PLLClkDiv::Div2, | 83 | PllRDiv::DIV2, |
| 84 | PLLSrcDiv::Div1, | 84 | PllPreDiv::DIV1, |
| 85 | PLLMul::Mul20, | 85 | PllMul::MUL20, |
| 86 | None, | 86 | None, |
| 87 | ); | 87 | ); |
| 88 | config.rcc.hsi48 = true; // needed for rng | 88 | config.rcc.hsi48 = true; // needed for rng |
diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs index 410d6891b..dc0d98ad4 100644 --- a/examples/stm32l4/src/bin/usb_serial.rs +++ b/examples/stm32l4/src/bin/usb_serial.rs | |||
| @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | info!("Hello World!"); | 23 | info!("Hello World!"); |
| 24 | 24 | ||
| 25 | let mut config = Config::default(); | 25 | let mut config = Config::default(); |
| 26 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); | 26 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); |
| 27 | config.rcc.hsi48 = true; | 27 | config.rcc.hsi48 = true; |
| 28 | 28 | ||
| 29 | let p = embassy_stm32::init(config); | 29 | let p = embassy_stm32::init(config); |
diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs index 9549d64d8..cc3c99b57 100644 --- a/examples/stm32l5/src/bin/rng.rs +++ b/examples/stm32l5/src/bin/rng.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; | 7 | use embassy_stm32::rcc::{ClockSrc, PLLSource, PllMul, PllPreDiv, PllQDiv, PllRDiv}; |
| 8 | use embassy_stm32::rng::Rng; | 8 | use embassy_stm32::rng::Rng; |
| 9 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; | 9 | use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -18,10 +18,10 @@ async fn main(_spawner: Spawner) { | |||
| 18 | let mut config = Config::default(); | 18 | let mut config = Config::default(); |
| 19 | config.rcc.mux = ClockSrc::PLL( | 19 | config.rcc.mux = ClockSrc::PLL( |
| 20 | PLLSource::HSI16, | 20 | PLLSource::HSI16, |
| 21 | PLLClkDiv::Div2, | 21 | PllRDiv::DIV2, |
| 22 | PLLSrcDiv::Div1, | 22 | PllPreDiv::DIV1, |
| 23 | PLLMul::Mul8, | 23 | PllMul::MUL8, |
| 24 | Some(PLLClkDiv::Div2), | 24 | Some(PllQDiv::DIV2), |
| 25 | ); | 25 | ); |
| 26 | let p = embassy_stm32::init(config); | 26 | let p = embassy_stm32::init(config); |
| 27 | 27 | ||
diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 15b84761b..498147f9d 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs | |||
| @@ -45,7 +45,7 @@ async fn net_task(stack: &'static Stack<Device<'static, MTU>>) -> ! { | |||
| 45 | #[embassy_executor::main] | 45 | #[embassy_executor::main] |
| 46 | async fn main(spawner: Spawner) { | 46 | async fn main(spawner: Spawner) { |
| 47 | let mut config = Config::default(); | 47 | let mut config = Config::default(); |
| 48 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); | 48 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); |
| 49 | config.rcc.hsi48 = true; | 49 | config.rcc.hsi48 = true; |
| 50 | let p = embassy_stm32::init(config); | 50 | let p = embassy_stm32::init(config); |
| 51 | 51 | ||
diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs index 7e894e407..db6a9c76f 100644 --- a/examples/stm32l5/src/bin/usb_hid_mouse.rs +++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs | |||
| @@ -22,7 +22,7 @@ bind_interrupts!(struct Irqs { | |||
| 22 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 23 | async fn main(_spawner: Spawner) { |
| 24 | let mut config = Config::default(); | 24 | let mut config = Config::default(); |
| 25 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); | 25 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); |
| 26 | config.rcc.hsi48 = true; | 26 | config.rcc.hsi48 = true; |
| 27 | let p = embassy_stm32::init(config); | 27 | let p = embassy_stm32::init(config); |
| 28 | 28 | ||
diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs index 0c719560f..e19ecbf08 100644 --- a/examples/stm32l5/src/bin/usb_serial.rs +++ b/examples/stm32l5/src/bin/usb_serial.rs | |||
| @@ -20,7 +20,7 @@ bind_interrupts!(struct Irqs { | |||
| 20 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 21 | async fn main(_spawner: Spawner) { | 21 | async fn main(_spawner: Spawner) { |
| 22 | let mut config = Config::default(); | 22 | let mut config = Config::default(); |
| 23 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PLLClkDiv::Div2, PLLSrcDiv::Div1, PLLMul::Mul10, None); | 23 | config.rcc.mux = ClockSrc::PLL(PLLSource::HSI16, PllRDiv::DIV2, PllPreDiv::DIV1, PllMul::MUL10, None); |
| 24 | config.rcc.hsi48 = true; | 24 | config.rcc.hsi48 = true; |
| 25 | let p = embassy_stm32::init(config); | 25 | let p = embassy_stm32::init(config); |
| 26 | 26 | ||
diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs index 278bd30f0..9b2adb0ac 100644 --- a/examples/stm32u5/src/bin/usb_serial.rs +++ b/examples/stm32u5/src/bin/usb_serial.rs | |||
| @@ -25,9 +25,9 @@ async fn main(_spawner: Spawner) { | |||
| 25 | let mut config = Config::default(); | 25 | let mut config = Config::default(); |
| 26 | config.rcc.mux = ClockSrc::PLL1R(PllConfig { | 26 | config.rcc.mux = ClockSrc::PLL1R(PllConfig { |
| 27 | source: PllSrc::HSI16, | 27 | source: PllSrc::HSI16, |
| 28 | m: PllM::Div2, | 28 | m: Pllm::DIV2, |
| 29 | n: PllN::Mul10, | 29 | n: Plln::MUL10, |
| 30 | r: PllClkDiv::NotDivided, | 30 | r: Plldiv::DIV1, |
| 31 | }); | 31 | }); |
| 32 | //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); | 32 | //config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); |
| 33 | config.rcc.hsi48 = true; | 33 | config.rcc.hsi48 = true; |
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 32ba03e4f..79a9b5e86 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs | |||
| @@ -202,9 +202,9 @@ pub fn config() -> Config { | |||
| 202 | // 1 MHz PLL input * 240 = 240 MHz PLL VCO | 202 | // 1 MHz PLL input * 240 = 240 MHz PLL VCO |
| 203 | mul: unwrap!(PLLMul::try_from(240)), | 203 | mul: unwrap!(PLLMul::try_from(240)), |
| 204 | // 240 MHz PLL VCO / 2 = 120 MHz main PLL output | 204 | // 240 MHz PLL VCO / 2 = 120 MHz main PLL output |
| 205 | main_div: PLLMainDiv::Div2, | 205 | p_div: PLLPDiv::DIV2, |
| 206 | // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output | 206 | // 240 MHz PLL VCO / 5 = 48 MHz PLL48 output |
| 207 | pll48_div: unwrap!(PLL48Div::try_from(5)), | 207 | q_div: PLLQDiv::DIV5, |
| 208 | }; | 208 | }; |
| 209 | // System clock comes from PLL (= the 120 MHz main PLL output) | 209 | // System clock comes from PLL (= the 120 MHz main PLL output) |
| 210 | config.rcc.mux = ClockSrc::PLL; | 210 | config.rcc.mux = ClockSrc::PLL; |
| @@ -239,10 +239,10 @@ pub fn config() -> Config { | |||
| 239 | }); | 239 | }); |
| 240 | config.rcc.pll1 = Some(Pll { | 240 | config.rcc.pll1 = Some(Pll { |
| 241 | source: PllSource::Hse, | 241 | source: PllSource::Hse, |
| 242 | prediv: 2, | 242 | prediv: PllPreDiv::DIV2, |
| 243 | mul: 125, | 243 | mul: PllMul::MUL125, |
| 244 | divp: Some(2), | 244 | divp: Some(PllDiv::DIV2), |
| 245 | divq: Some(2), | 245 | divq: Some(PllDiv::DIV2), |
| 246 | divr: None, | 246 | divr: None, |
| 247 | }); | 247 | }); |
| 248 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | 248 | config.rcc.ahb_pre = AHBPrescaler::DIV1; |
| @@ -261,16 +261,16 @@ pub fn config() -> Config { | |||
| 261 | config.rcc.hsi48 = true; // needed for RNG | 261 | config.rcc.hsi48 = true; // needed for RNG |
| 262 | config.rcc.pll_src = PllSource::Hsi; | 262 | config.rcc.pll_src = PllSource::Hsi; |
| 263 | config.rcc.pll1 = Some(Pll { | 263 | config.rcc.pll1 = Some(Pll { |
| 264 | prediv: 4, | 264 | prediv: PllPreDiv::DIV4, |
| 265 | mul: 50, | 265 | mul: PllMul::MUL50, |
| 266 | divp: Some(2), | 266 | divp: Some(PllDiv::DIV2), |
| 267 | divq: Some(8), // SPI1 cksel defaults to pll1_q | 267 | divq: Some(PllDiv::DIV8), // SPI1 cksel defaults to pll1_q |
| 268 | divr: None, | 268 | divr: None, |
| 269 | }); | 269 | }); |
| 270 | config.rcc.pll2 = Some(Pll { | 270 | config.rcc.pll2 = Some(Pll { |
| 271 | prediv: 4, | 271 | prediv: PllPreDiv::DIV4, |
| 272 | mul: 50, | 272 | mul: PllMul::MUL50, |
| 273 | divp: Some(8), // 100mhz | 273 | divp: Some(PllDiv::DIV8), // 100mhz |
| 274 | divq: None, | 274 | divq: None, |
| 275 | divr: None, | 275 | divr: None, |
| 276 | }); | 276 | }); |
| @@ -290,10 +290,10 @@ pub fn config() -> Config { | |||
| 290 | config.rcc.mux = ClockSrc::PLL( | 290 | config.rcc.mux = ClockSrc::PLL( |
| 291 | // 72Mhz clock (16 / 1 * 18 / 4) | 291 | // 72Mhz clock (16 / 1 * 18 / 4) |
| 292 | PLLSource::HSI16, | 292 | PLLSource::HSI16, |
| 293 | PLLClkDiv::Div4, | 293 | PllRDiv::DIV4, |
| 294 | PLLSrcDiv::Div1, | 294 | PllPreDiv::DIV1, |
| 295 | PLLMul::Mul18, | 295 | PllMul::MUL18, |
| 296 | Some(PLLClkDiv::Div6), // 48Mhz (16 / 1 * 18 / 6) | 296 | Some(PllQDiv::DIV6), // 48Mhz (16 / 1 * 18 / 6) |
| 297 | ); | 297 | ); |
| 298 | } | 298 | } |
| 299 | 299 | ||
| @@ -303,9 +303,9 @@ pub fn config() -> Config { | |||
| 303 | config.rcc.mux = ClockSrc::PLL( | 303 | config.rcc.mux = ClockSrc::PLL( |
| 304 | // 110Mhz clock (16 / 4 * 55 / 2) | 304 | // 110Mhz clock (16 / 4 * 55 / 2) |
| 305 | PLLSource::HSI16, | 305 | PLLSource::HSI16, |
| 306 | PLLClkDiv::Div2, | 306 | PllRDiv::DIV2, |
| 307 | PLLSrcDiv::Div4, | 307 | PllPreDiv::DIV4, |
| 308 | PLLMul::Mul55, | 308 | PllMul::MUL55, |
| 309 | None, | 309 | None, |
| 310 | ); | 310 | ); |
| 311 | } | 311 | } |
| @@ -313,7 +313,7 @@ pub fn config() -> Config { | |||
| 313 | #[cfg(feature = "stm32u585ai")] | 313 | #[cfg(feature = "stm32u585ai")] |
| 314 | { | 314 | { |
| 315 | use embassy_stm32::rcc::*; | 315 | use embassy_stm32::rcc::*; |
| 316 | config.rcc.mux = ClockSrc::MSI(MSIRange::Range48mhz); | 316 | config.rcc.mux = ClockSrc::MSI(Msirange::RANGE_48MHZ); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | #[cfg(feature = "stm32l073rz")] | 319 | #[cfg(feature = "stm32l073rz")] |
