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