aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Stakenburg <[email protected]>2021-09-24 16:50:53 +0200
committerUlf Lilleengen <[email protected]>2021-09-24 18:27:39 +0200
commit7d6d274d55098b66c1dc529b10139c57eb9dcfaa (patch)
tree7ee48417c4ef711b8c99637cea470b94377acde1
parentb6fc19182b4ae02ea1e9107ca28b88f4a3b0b60a (diff)
Add MSI and PLL clock source for L4
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/src/rcc/l4/mod.rs188
2 files changed, 189 insertions, 0 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 3e91040f0..aedb54b74 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -27,6 +27,7 @@ atomic-polyfill = "0.1.3"
27stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] } 27stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] }
28vcell = { version = "0.1.3", optional = true } 28vcell = { version = "0.1.3", optional = true }
29bxcan = "0.5.1" 29bxcan = "0.5.1"
30seq-macro = "0.2.2"
30 31
31cfg-if = "1.0.0" 32cfg-if = "1.0.0"
32 33
diff --git a/embassy-stm32/src/rcc/l4/mod.rs b/embassy-stm32/src/rcc/l4/mod.rs
index 4247d8ffb..aac0febe2 100644
--- a/embassy-stm32/src/rcc/l4/mod.rs
+++ b/embassy-stm32/src/rcc/l4/mod.rs
@@ -7,6 +7,7 @@ use crate::time::U32Ext;
7use core::marker::PhantomData; 7use core::marker::PhantomData;
8use embassy::util::Unborrow; 8use embassy::util::Unborrow;
9use embassy_hal_common::unborrow; 9use embassy_hal_common::unborrow;
10use stm32_metapac::rcc::vals::Msirange;
10 11
11/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 12/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
12/// and with the addition of the init function to configure a system clock. 13/// and with the addition of the init function to configure a system clock.
@@ -19,10 +20,123 @@ pub const HSI_FREQ: u32 = 16_000_000;
19/// System clock mux source 20/// System clock mux source
20#[derive(Clone, Copy)] 21#[derive(Clone, Copy)]
21pub enum ClockSrc { 22pub enum ClockSrc {
23 PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul),
24 MSI(MSIRange),
22 HSE(Hertz), 25 HSE(Hertz),
23 HSI16, 26 HSI16,
24} 27}
25 28
29seq_macro::seq!(N in 8..=86 {
30 #[derive(Clone, Copy)]
31 pub enum PLLMul {
32 #(
33 Mul#N,
34 )*
35 }
36
37 impl Into<u8> for PLLMul {
38 fn into(self) -> u8 {
39 match self {
40 #(
41 PLLMul::Mul#N => N,
42 )*
43 }
44 }
45 }
46
47 impl PLLMul {
48 pub fn to_mul(self) -> u32 {
49 match self {
50 #(
51 PLLMul::Mul#N => N,
52 )*
53 }
54 }
55 }
56});
57
58#[derive(Clone, Copy)]
59pub enum PLLClkDiv {
60 Div2,
61 Div4,
62 Div6,
63 Div8,
64}
65
66impl PLLClkDiv {
67 pub fn to_div(self) -> u32 {
68 let val: u8 = self.into();
69 val as u32 + 1 * 2
70 }
71}
72
73impl Into<u8> for PLLClkDiv {
74 fn into(self) -> u8 {
75 match self {
76 PLLClkDiv::Div2 => 0b00,
77 PLLClkDiv::Div4 => 0b01,
78 PLLClkDiv::Div6 => 0b10,
79 PLLClkDiv::Div8 => 0b11,
80 }
81 }
82}
83
84#[derive(Clone, Copy)]
85pub enum PLLSrcDiv {
86 Div1,
87 Div2,
88 Div3,
89 Div4,
90 Div5,
91 Div6,
92 Div7,
93 Div8,
94}
95
96impl PLLSrcDiv {
97 pub fn to_div(self) -> u32 {
98 let val: u8 = self.into();
99 val as u32 + 1
100 }
101}
102
103impl Into<u8> for PLLSrcDiv {
104 fn into(self) -> u8 {
105 match self {
106 PLLSrcDiv::Div1 => 0b000,
107 PLLSrcDiv::Div2 => 0b001,
108 PLLSrcDiv::Div3 => 0b010,
109 PLLSrcDiv::Div4 => 0b011,
110 PLLSrcDiv::Div5 => 0b100,
111 PLLSrcDiv::Div6 => 0b101,
112 PLLSrcDiv::Div7 => 0b110,
113 PLLSrcDiv::Div8 => 0b111,
114 }
115 }
116}
117
118impl Into<u8> for PLLSource {
119 fn into(self) -> u8 {
120 match self {
121 PLLSource::HSI16 => 0b10,
122 PLLSource::HSE(_) => 0b11,
123 }
124 }
125}
126
127impl Into<Msirange> for MSIRange {
128 fn into(self) -> Msirange {
129 match self {
130 MSIRange::Range0 => Msirange::RANGE100K,
131 MSIRange::Range1 => Msirange::RANGE200K,
132 MSIRange::Range2 => Msirange::RANGE400K,
133 MSIRange::Range3 => Msirange::RANGE800K,
134 MSIRange::Range4 => Msirange::RANGE1M,
135 MSIRange::Range5 => Msirange::RANGE2M,
136 MSIRange::Range6 => Msirange::RANGE4M,
137 }
138 }
139}
26impl Into<u8> for APBPrescaler { 140impl Into<u8> for APBPrescaler {
27 fn into(self) -> u8 { 141 fn into(self) -> u8 {
28 match self { 142 match self {
@@ -146,9 +260,83 @@ impl RccExt for RCC {
146 260
147 (freq.0, 0x02) 261 (freq.0, 0x02)
148 } 262 }
263 ClockSrc::MSI(range) => {
264 // Enable MSI
265 unsafe {
266 rcc.cr().write(|w| {
267 w.set_msirange(range.into());
268 w.set_msion(true);
269 });
270 while !rcc.cr().read().msirdy() {}
271 }
272
273 let freq = 32_768 * (1 << (range as u8 + 1));
274 (freq, 0b00)
275 }
276 ClockSrc::PLL(src, div, prediv, mul) => {
277 let freq = match src {
278 PLLSource::HSE(freq) => {
279 // Enable HSE
280 unsafe {
281 rcc.cr().write(|w| w.set_hseon(true));
282 while !rcc.cr().read().hserdy() {}
283 }
284 freq.0
285 }
286 PLLSource::HSI16 => {
287 // Enable HSI
288 unsafe {
289 rcc.cr().write(|w| w.set_hsion(true));
290 while !rcc.cr().read().hsirdy() {}
291 }
292 HSI_FREQ
293 }
294 };
295
296 // Disable PLL
297 unsafe {
298 rcc.cr().modify(|w| w.set_pllon(false));
299 while rcc.cr().read().pllrdy() {}
300 }
301
302 let freq = (freq / prediv.to_div() * mul.to_mul()) / div.to_div();
303
304 assert!(freq <= 80_000_000);
305
306 unsafe {
307 rcc.pllcfgr().write(move |w| {
308 w.set_plln(mul.into());
309 w.set_pllm(prediv.into());
310 w.set_pllr(div.into());
311 w.set_pllsrc(src.into());
312 });
313
314 // Enable PLL
315 rcc.cr().modify(|w| w.set_pllon(true));
316 while !rcc.cr().read().pllrdy() {}
317 rcc.pllcfgr().modify(|w| w.set_pllren(true));
318 }
319 (freq, 0b11)
320 }
149 }; 321 };
150 322
151 unsafe { 323 unsafe {
324 // Set flash wait states
325 pac::FLASH.acr().modify(|w| {
326 w.set_latency(if sys_clk <= 16_000_000 {
327 0b000
328 } else if sys_clk <= 32_000_000 {
329 0b001
330 } else if sys_clk <= 48_000_000 {
331 0b010
332 } else if sys_clk <= 64_000_000 {
333 0b011
334 } else {
335 0b100
336 });
337 });
338
339 // Switch active clocks to new clock source
152 rcc.cfgr().modify(|w| { 340 rcc.cfgr().modify(|w| {
153 w.set_sw(sw.into()); 341 w.set_sw(sw.into());
154 w.set_hpre(cfgr.ahb_pre.into()); 342 w.set_hpre(cfgr.ahb_pre.into());