aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl St-Laurent <[email protected]>2023-06-03 22:05:24 -0400
committerCarl St-Laurent <[email protected]>2023-06-03 22:05:24 -0400
commit2f269f32560ab178f62d08730909745f49b8eaef (patch)
treef69042dd8da036623157a820e7d5b4119723923e
parentf2c2536cf3d67e4e28616f631b6bdde789b15560 (diff)
stm32/rcc: Implement basic PLL support for STM32G4 series
-rw-r--r--embassy-stm32/src/rcc/g4.rs163
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 @@
1use stm32_metapac::rcc::vals::{Hpre, Ppre, Sw}; 1use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw};
2 2
3use crate::pac::{PWR, RCC}; 3use crate::pac::{PWR, RCC};
4use crate::rcc::{set_freqs, Clocks}; 4use crate::rcc::{set_freqs, Clocks};
@@ -15,6 +15,7 @@ pub const LSI_FREQ: Hertz = Hertz(32_000);
15pub enum ClockSrc { 15pub 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)]
47pub enum PllSrc {
48 HSI16,
49 HSE(Hertz),
50}
51
52impl 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)]
62pub enum PllClkDiv {
63 Div2,
64 Div4,
65 Div6,
66 Div8,
67}
68
69impl PllClkDiv {
70 pub fn to_div(self) -> u32 {
71 let val: u8 = self.into();
72 (val as u32 + 1) * 2
73 }
74}
75
76impl 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
87seq_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)]
118pub 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
137impl PllM {
138 pub fn to_div(self) -> u32 {
139 let val: u8 = self.into();
140 val as u32 + 1
141 }
142}
143
144impl 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
44impl AHBPrescaler { 167impl 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| {