diff options
| author | Carl St-Laurent <[email protected]> | 2023-06-03 22:05:24 -0400 |
|---|---|---|
| committer | Carl St-Laurent <[email protected]> | 2023-06-03 22:05:24 -0400 |
| commit | 2f269f32560ab178f62d08730909745f49b8eaef (patch) | |
| tree | f69042dd8da036623157a820e7d5b4119723923e | |
| parent | f2c2536cf3d67e4e28616f631b6bdde789b15560 (diff) | |
stm32/rcc: Implement basic PLL support for STM32G4 series
| -rw-r--r-- | embassy-stm32/src/rcc/g4.rs | 163 |
1 files changed, 162 insertions, 1 deletions
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index 7e748c7b5..13dced73d 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | use stm32_metapac::rcc::vals::{Hpre, Ppre, Sw}; | 1 | use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; |
| 2 | 2 | ||
| 3 | use crate::pac::{PWR, RCC}; | 3 | use crate::pac::{PWR, RCC}; |
| 4 | use crate::rcc::{set_freqs, Clocks}; | 4 | use crate::rcc::{set_freqs, Clocks}; |
| @@ -15,6 +15,7 @@ pub const LSI_FREQ: Hertz = Hertz(32_000); | |||
| 15 | pub enum ClockSrc { | 15 | pub enum ClockSrc { |
| 16 | HSE(Hertz), | 16 | HSE(Hertz), |
| 17 | HSI16, | 17 | HSI16, |
| 18 | PLL(PllSrc, PllM, PllN, PllClkDiv), | ||
| 18 | } | 19 | } |
| 19 | 20 | ||
| 20 | /// AHB prescaler | 21 | /// AHB prescaler |
| @@ -41,6 +42,128 @@ pub enum APBPrescaler { | |||
| 41 | Div16, | 42 | Div16, |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 45 | /// PLL clock input source | ||
| 46 | #[derive(Clone, Copy, Debug)] | ||
| 47 | pub enum PllSrc { | ||
| 48 | HSI16, | ||
| 49 | HSE(Hertz), | ||
| 50 | } | ||
| 51 | |||
| 52 | impl Into<Pllsrc> for PllSrc { | ||
| 53 | fn into(self) -> Pllsrc { | ||
| 54 | match self { | ||
| 55 | PllSrc::HSE(..) => Pllsrc::HSE, | ||
| 56 | PllSrc::HSI16 => Pllsrc::HSI16, | ||
| 57 | } | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | #[derive(Clone, Copy)] | ||
| 62 | pub enum PllClkDiv { | ||
| 63 | Div2, | ||
| 64 | Div4, | ||
| 65 | Div6, | ||
| 66 | Div8, | ||
| 67 | } | ||
| 68 | |||
| 69 | impl PllClkDiv { | ||
| 70 | pub fn to_div(self) -> u32 { | ||
| 71 | let val: u8 = self.into(); | ||
| 72 | (val as u32 + 1) * 2 | ||
| 73 | } | ||
| 74 | } | ||
| 75 | |||
| 76 | impl From<PllClkDiv> for u8 { | ||
| 77 | fn from(val: PllClkDiv) -> u8 { | ||
| 78 | match val { | ||
| 79 | PllClkDiv::Div2 => 0b00, | ||
| 80 | PllClkDiv::Div4 => 0b01, | ||
| 81 | PllClkDiv::Div6 => 0b10, | ||
| 82 | PllClkDiv::Div8 => 0b11, | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | seq_macro::seq!(N in 8..=127 { | ||
| 88 | #[derive(Clone, Copy)] | ||
| 89 | pub enum PllN { | ||
| 90 | #( | ||
| 91 | Mul~N, | ||
| 92 | )* | ||
| 93 | } | ||
| 94 | |||
| 95 | impl From<PllN> for u8 { | ||
| 96 | fn from(val: PllN) -> u8 { | ||
| 97 | match val { | ||
| 98 | #( | ||
| 99 | PllN::Mul~N => N, | ||
| 100 | )* | ||
| 101 | } | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | impl PllN { | ||
| 106 | pub fn to_mul(self) -> u32 { | ||
| 107 | match self { | ||
| 108 | #( | ||
| 109 | PllN::Mul~N => N, | ||
| 110 | )* | ||
| 111 | } | ||
| 112 | } | ||
| 113 | } | ||
| 114 | }); | ||
| 115 | |||
| 116 | // Pre-division | ||
| 117 | #[derive(Copy, Clone)] | ||
| 118 | pub enum PllM { | ||
| 119 | Div1, | ||
| 120 | Div2, | ||
| 121 | Div3, | ||
| 122 | Div4, | ||
| 123 | Div5, | ||
| 124 | Div6, | ||
| 125 | Div7, | ||
| 126 | Div8, | ||
| 127 | Div9, | ||
| 128 | Div10, | ||
| 129 | Div11, | ||
| 130 | Div12, | ||
| 131 | Div13, | ||
| 132 | Div14, | ||
| 133 | Div15, | ||
| 134 | Div16, | ||
| 135 | } | ||
| 136 | |||
| 137 | impl PllM { | ||
| 138 | pub fn to_div(self) -> u32 { | ||
| 139 | let val: u8 = self.into(); | ||
| 140 | val as u32 + 1 | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | impl From<PllM> for u8 { | ||
| 145 | fn from(val: PllM) -> u8 { | ||
| 146 | match val { | ||
| 147 | PllM::Div1 => 0b0000, | ||
| 148 | PllM::Div2 => 0b0001, | ||
| 149 | PllM::Div3 => 0b0010, | ||
| 150 | PllM::Div4 => 0b0011, | ||
| 151 | PllM::Div5 => 0b0100, | ||
| 152 | PllM::Div6 => 0b0101, | ||
| 153 | PllM::Div7 => 0b0110, | ||
| 154 | PllM::Div8 => 0b0111, | ||
| 155 | PllM::Div9 => 0b1000, | ||
| 156 | PllM::Div10 => 0b1001, | ||
| 157 | PllM::Div11 => 0b1010, | ||
| 158 | PllM::Div12 => 0b1011, | ||
| 159 | PllM::Div13 => 0b1100, | ||
| 160 | PllM::Div14 => 0b1101, | ||
| 161 | PllM::Div15 => 0b1110, | ||
| 162 | PllM::Div16 => 0b1111, | ||
| 163 | } | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 44 | impl AHBPrescaler { | 167 | impl AHBPrescaler { |
| 45 | const fn div(self) -> u32 { | 168 | const fn div(self) -> u32 { |
| 46 | match self { | 169 | match self { |
| @@ -135,6 +258,44 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 135 | 258 | ||
| 136 | (freq.0, Sw::HSE) | 259 | (freq.0, Sw::HSE) |
| 137 | } | 260 | } |
| 261 | ClockSrc::PLL(src, prediv, mul, div) => { | ||
| 262 | let src_freq = match src { | ||
| 263 | PllSrc::HSI16 => { | ||
| 264 | // Enable HSI16 | ||
| 265 | RCC.cr().write(|w| w.set_hsion(true)); | ||
| 266 | while !RCC.cr().read().hsirdy() {} | ||
| 267 | |||
| 268 | HSI_FREQ.0 | ||
| 269 | } | ||
| 270 | PllSrc::HSE(freq) => { | ||
| 271 | // Enable HSE | ||
| 272 | RCC.cr().write(|w| w.set_hseon(true)); | ||
| 273 | while !RCC.cr().read().hserdy() {} | ||
| 274 | |||
| 275 | freq.0 | ||
| 276 | } | ||
| 277 | }; | ||
| 278 | |||
| 279 | // Disable PLL | ||
| 280 | RCC.cr().modify(|w| w.set_pllon(false)); | ||
| 281 | while RCC.cr().read().pllrdy() {} | ||
| 282 | |||
| 283 | let freq = src_freq / prediv.to_div() * mul.to_mul() / div.to_div(); | ||
| 284 | assert!(freq <= 170_000_000); | ||
| 285 | |||
| 286 | RCC.pllcfgr().write(move |w| { | ||
| 287 | w.set_plln(mul.into()); | ||
| 288 | w.set_pllm(prediv.into()); | ||
| 289 | w.set_pllr(div.into()); | ||
| 290 | w.set_pllsrc(src.into()); | ||
| 291 | }); | ||
| 292 | |||
| 293 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 294 | while !RCC.cr().read().pllrdy() {} | ||
| 295 | RCC.pllcfgr().modify(|w| w.set_pllren(true)); | ||
| 296 | |||
| 297 | (freq, Sw::PLLRCLK) | ||
| 298 | } | ||
| 138 | }; | 299 | }; |
| 139 | 300 | ||
| 140 | RCC.cfgr().modify(|w| { | 301 | RCC.cfgr().modify(|w| { |
