1use crate::pac::rcc::vals::Pllsrc;
7#[cfg(rcc_f030)]
9use crate::pac::rcc::vals::HseFreq;
10#[cfg(rcc_f072)]
11pub use crate::pac::rcc::vals::Pllmul as PllMul;
12pub use crate::pac::rcc::vals::{
13 Hpre as AHBPrescaler, HsiFs, Hsidiv, Ppre as APBPrescaler, Sw as Sysclk,
14};
15
16use crate::pac::{CONFIGBYTES, FLASH, RCC};
17use crate::time::Hertz;
18
19#[derive(Clone, Copy, Eq, PartialEq)]
23pub enum HseMode {
24 Oscillator,
26 Bypass,
28}
29
30#[derive(Clone, Copy, Eq, PartialEq)]
31pub struct Hse {
32 pub freq: Hertz,
34 pub mode: HseMode,
36}
37
38#[derive(Clone, Copy, Eq, PartialEq)]
39pub struct Hsi {
40 pub freq: Hertz,
42 pub mode: HseMode,
44}
45
46#[derive(Clone, Copy, Eq, PartialEq)]
47pub enum PllSource {
48 HSE,
49 HSI,
50}
51
52#[derive(Clone, Copy)]
53pub struct Pll {
54 pub src: PllSource,
55
56 #[cfg(rcc_f072)]
61 pub mul: PllMul,
63}
64
65#[non_exhaustive]
67#[derive(Clone, Copy)]
68pub struct Config {
69 pub hsi: Option<HsiFs>,
70 pub hsidiv: Hsidiv,
71 pub hse: Option<Hse>,
72 pub sys: Sysclk,
73
74 pub pll: Option<Pll>,
75
76 pub ahb_pre: AHBPrescaler,
77 pub apb1_pre: APBPrescaler,
78 pub mux: super::mux::ClockMux,
80 }
82
83impl Default for Config {
84 fn default() -> Self {
85 Self {
86 hsi: Some(HsiFs::HSI_8MHZ),
87 hse: None,
88 sys: Sysclk::HSI,
89 hsidiv: Hsidiv::DIV1,
90 pll: None,
91 ahb_pre: AHBPrescaler::DIV1,
92 apb1_pre: APBPrescaler::DIV1,
93 mux: Default::default(),
95 }
96 }
97}
98
99pub(crate) unsafe fn init(config: Config) {
101 RCC.cr().modify(|w| w.set_hsion(true));
103 let hsi_value = if let Some(value) = config.hsi {
104 let hsi_trimming_bytes = CONFIGBYTES.hsi_trimming(value as usize).read();
105
106 assert_eq!(hsi_trimming_bytes.hsi_fs(), value as u8);
107
108 RCC.icscr().modify(|w| {
109 w.set_hsi_fs(value);
110 w.set_hsi_trim(hsi_trimming_bytes.hsi_trim());
111 });
112
113 match value {
114 HsiFs::HSI_4MHZ => Some(Hertz(4_000_000)),
115 HsiFs::HSI_8MHZ => Some(Hertz(8_000_000)),
116 HsiFs::HSI_16MHZ => Some(Hertz(16_000_000)),
117 HsiFs::HSI_22_12MHZ => Some(Hertz(22_120_000)),
118 HsiFs::HSI_24MHZ => Some(Hertz(24_000_000)),
119 _ => unreachable!(),
120 }
121 } else {
122 None
123 };
124 while !RCC.cr().read().hsirdy() {}
125
126 RCC.cfgr().modify(|w| w.set_sw(Sysclk::HSI));
128 while RCC.cfgr().read().sws() != Sysclk::HSI {}
129
130 RCC.cr().modify(|w| w.set_hsidiv(config.hsidiv));
131
132 let hsi = config.hsi;
134
135 let hse = match config.hse {
137 None => {
138 RCC.cr().modify(|w| w.set_hseon(false));
139 None
140 }
141 Some(hse) => {
142 match hse.mode {
143 HseMode::Bypass => assert!(max::HSE_BYP.contains(&hse.freq)),
144 HseMode::Oscillator => assert!(max::HSE_OSC.contains(&hse.freq)),
145 }
146
147 #[cfg(rcc_f030)]
148 RCC.ecscr().modify(|w| {
149 w.set_hse_freq(match hse.freq.0 {
150 ..=8_000_000 => HseFreq::RANGE1,
151 ..=16_000_000 => HseFreq::RANGE2,
152 _ => HseFreq::RANGE3,
153 })
154 });
155 RCC.cr()
156 .modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator));
157 RCC.cr().modify(|w| w.set_hseon(true));
158 while !RCC.cr().read().hserdy() {}
159 Some(hse.freq)
160 }
161 };
162 let pll = match config.pll {
164 None => None,
165 Some(pll) => {
166 let (src_val, src_freq) = match pll.src {
167 PllSource::HSE => (Pllsrc::HSE, unwrap!(hse)),
168 PllSource::HSI => (Pllsrc::HSI, unwrap!(hsi_value)),
169 };
170 #[cfg(rcc_f030)]
171 let out_freq = src_freq * 2u8;
172 #[cfg(rcc_f072)]
173 let out_freq = src_freq * pll.mul;
174 assert!(max::PLL_IN.contains(&src_freq));
175 RCC.cr().modify(|w| w.set_pllon(false));
178 while RCC.cr().read().pllrdy() {}
179
180 RCC.pllcfgr().modify(|w| {
181 #[cfg(rcc_f072)]
182 w.set_pllmul(pll.mul);
183 w.set_pllsrc(src_val);
184 });
185 RCC.cr().modify(|w| w.set_pllon(true));
186 cortex_m::asm::delay(1_000);
187 while !RCC.cr().read().pllrdy() {}
188 Some(out_freq)
189 }
190 };
191
192 let sys = match config.sys {
204 Sysclk::HSI => unwrap!(hsi_value) / config.hsidiv,
205 Sysclk::HSE => unwrap!(hse),
206 Sysclk::PLL => unwrap!(pll),
207 _ => unreachable!(),
208 };
209
210 let hclk1 = sys / config.ahb_pre;
211 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
212
213 let latency: u8 = match hclk1.0 {
217 ..=24_000_000 => 0,
218 ..=48_000_000 => 1,
219 _ => 2,
220 };
221 FLASH.acr().modify(|w| {
222 #[cfg(rcc_f072)]
223 w.set_latency(latency);
224 #[cfg(rcc_f030)]
225 w.set_latency(latency != 0);
226 });
227 RCC.cfgr().modify(|w| {
230 w.set_ppre(config.apb1_pre);
231 w.set_hpre(config.ahb_pre);
232 });
233
234 cortex_m::asm::delay(16);
238
239 RCC.cfgr().modify(|w| w.set_sw(config.sys));
241 while RCC.cfgr().read().sws() != config.sys {}
242
243 if hsi == None {
245 RCC.cr().modify(|w| w.set_hsion(false));
246 }
247
248 config.mux.init();
270
271 let clocks = crate::rcc::Clocks {
285 hclk1: Some(hclk1).into(),
286 pclk1: Some(pclk1).into(),
287 pclk1_tim: Some(pclk1_tim).into(),
288 sys: Some(sys).into(),
289 hsi: hsi_value.into(),
290 lse: None.into(),
291 pll: pll.into(),
292 };
293 crate::rcc::set_freqs(clocks);
294}
295
296mod max {
297 use core::ops::RangeInclusive;
298
299 use crate::time::Hertz;
300
301 pub(crate) const HSE_OSC: RangeInclusive<Hertz> = Hertz(4_000_000)..=Hertz(32_000_000);
302 pub(crate) const HSE_BYP: RangeInclusive<Hertz> = Hertz(1_000_000)..=Hertz(32_000_000);
303
304 #[cfg(any(rcc_f030, rcc_f072))]
308 pub(crate) const PLL_IN: RangeInclusive<Hertz> = Hertz(16_000_000)..=Hertz(24_000_000);
309 }