Skip to content

Commit 4c8b890

Browse files
committed
Full RCC support for STM32F107
1 parent 169f9c2 commit 4c8b890

File tree

2 files changed

+241
-1
lines changed

2 files changed

+241
-1
lines changed

embassy-stm32/src/rcc/f107.rs

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
use crate::pac::flash::vals::Latency;
2+
pub use crate::pac::rcc::vals::{
3+
Adcpre as ADCPrescaler, Hpre as AHBPrescaler, Pll2mul, Pllmul as PllMul, Pllsrc, Ppre as APBPrescaler, Prediv1,
4+
Prediv1src, Sw as Sysclk,
5+
};
6+
use crate::pac::{FLASH, RCC};
7+
use crate::time::Hertz;
8+
9+
/// HSI speed
10+
pub const HSI_FREQ: Hertz = Hertz(8_000_000);
11+
12+
#[derive(Clone, Copy, Eq, PartialEq)]
13+
pub enum HseMode {
14+
Oscillator,
15+
Bypass,
16+
}
17+
18+
#[derive(Clone, Copy, Eq, PartialEq)]
19+
pub struct Hse {
20+
pub freq: Hertz,
21+
pub mode: HseMode,
22+
}
23+
24+
#[derive(Clone, Copy, Eq, PartialEq)]
25+
pub enum PllSource {
26+
HSE,
27+
HSI,
28+
}
29+
30+
#[derive(Clone, Copy)]
31+
pub struct Pll {
32+
pub src: PllSource,
33+
pub prediv: Prediv1,
34+
pub mul: PllMul,
35+
}
36+
37+
#[derive(Clone, Copy)]
38+
pub struct Pll23 {
39+
pub mul: Pll2mul,
40+
}
41+
42+
#[derive(Clone, Copy)]
43+
pub struct Config {
44+
pub hsi: bool,
45+
pub hse: Option<Hse>,
46+
pub sys: Sysclk,
47+
pub pll: Option<Pll>,
48+
pub pll2: Option<Pll23>,
49+
pub pll3: Option<Pll23>,
50+
pub prediv1_src: Option<Prediv1src>,
51+
pub prediv2: Option<Prediv1>,
52+
pub ahb_pre: AHBPrescaler,
53+
pub apb1_pre: APBPrescaler,
54+
pub apb2_pre: APBPrescaler,
55+
pub adc_pre: ADCPrescaler,
56+
pub usb_pre: Option<crate::pac::rcc::vals::Usbpre>,
57+
pub i2s2_src: Option<crate::pac::rcc::vals::I2s2src>,
58+
pub i2s3_src: Option<crate::pac::rcc::vals::I2s2src>,
59+
}
60+
61+
impl Default for Config {
62+
fn default() -> Self {
63+
Self {
64+
hsi: true,
65+
hse: None,
66+
sys: Sysclk::HSI,
67+
pll: None,
68+
pll2: None,
69+
pll3: None,
70+
prediv1_src: None,
71+
prediv2: None,
72+
ahb_pre: AHBPrescaler::DIV1,
73+
apb1_pre: APBPrescaler::DIV1,
74+
apb2_pre: APBPrescaler::DIV1,
75+
adc_pre: ADCPrescaler::DIV6,
76+
usb_pre: None,
77+
i2s2_src: None,
78+
i2s3_src: None,
79+
}
80+
}
81+
}
82+
83+
pub(crate) unsafe fn init(config: Config) {
84+
RCC.cr().modify(|w| w.set_hsion(true));
85+
while !RCC.cr().read().hsirdy() {}
86+
87+
RCC.cfgr().modify(|w| w.set_sw(Sysclk::HSI));
88+
while RCC.cfgr().read().sws() != Sysclk::HSI {}
89+
90+
let hsi = if config.hsi { Some(HSI_FREQ) } else { None };
91+
92+
let hse = match config.hse {
93+
None => {
94+
RCC.cr().modify(|w| w.set_hseon(false));
95+
None
96+
}
97+
Some(hse) => {
98+
RCC.cr().modify(|w| w.set_hsebyp(hse.mode != HseMode::Oscillator));
99+
RCC.cr().modify(|w| w.set_hseon(true));
100+
while !RCC.cr().read().hserdy() {}
101+
Some(hse.freq)
102+
}
103+
};
104+
105+
// Calculate pll2clk and pll3clk
106+
let pll2clk = config.pll2.map(|pll2| {
107+
let prediv2 = config.prediv2.unwrap_or(Prediv1::DIV1);
108+
let in_freq = hse.unwrap() / (prediv2.to_bits() + 1);
109+
in_freq * pll2.mul
110+
});
111+
trace!("pll2clk: {:?}", pll2clk);
112+
113+
let pll3clk = config.pll3.map(|pll3| {
114+
let prediv2 = config.prediv2.unwrap_or(Prediv1::DIV1);
115+
let in_freq = hse.unwrap() / (prediv2.to_bits() + 1);
116+
in_freq * pll3.mul
117+
});
118+
trace!("pll3clk: {:?}", pll3clk);
119+
120+
let pll = config.pll.map(|pll| {
121+
let prediv1_src = config.prediv1_src.unwrap_or(Prediv1src::HSE);
122+
let (src_val, src_freq) = match pll.src {
123+
PllSource::HSI => {
124+
if pll.prediv != Prediv1::DIV2 {
125+
panic!("if PLL source is HSI, PLL prediv must be 2.");
126+
}
127+
(Pllsrc::HSI_DIV2, hsi.unwrap())
128+
}
129+
PllSource::HSE => (
130+
Pllsrc::HSE_DIV_PREDIV,
131+
match prediv1_src {
132+
Prediv1src::HSE => hse.unwrap(),
133+
Prediv1src::PLL2 => pll2clk.unwrap(),
134+
},
135+
),
136+
};
137+
let in_freq = src_freq / (pll.prediv.to_bits() + 1);
138+
let out_freq = in_freq * pll.mul;
139+
140+
RCC.cfgr2().modify(|w| w.set_prediv1(pll.prediv));
141+
RCC.cfgr().modify(|w| {
142+
w.set_pllmul(pll.mul);
143+
w.set_pllsrc(src_val);
144+
});
145+
RCC.cr().modify(|w| w.set_pllon(true));
146+
while !RCC.cr().read().pllrdy() {}
147+
148+
out_freq
149+
});
150+
151+
// Configure Prediv1 Source Mux
152+
if let Some(prediv1_src) = config.prediv1_src {
153+
RCC.cfgr2().modify(|w| w.set_prediv1src(prediv1_src));
154+
}
155+
156+
// Configure common prediv for PLL2 and PLL3
157+
if let Some(prediv) = config.prediv2 {
158+
RCC.cfgr2().modify(|w| w.set_prediv2(prediv));
159+
}
160+
161+
// Configure PLL2
162+
if let Some(pll2) = config.pll2 {
163+
RCC.cfgr2().modify(|w| w.set_pll2mul(pll2.mul));
164+
RCC.cr().modify(|w| w.set_pll2on(true));
165+
while !RCC.cr().read().pll2rdy() {}
166+
}
167+
168+
// Configure PLL3
169+
if let Some(pll3) = config.pll3 {
170+
RCC.cfgr2().modify(|w| w.set_pll3mul(pll3.mul));
171+
RCC.cr().modify(|w| w.set_pll3on(true));
172+
while !RCC.cr().read().pll3rdy() {}
173+
}
174+
175+
let sys = match config.sys {
176+
Sysclk::HSI => hsi.unwrap(),
177+
Sysclk::HSE => hse.unwrap(),
178+
Sysclk::PLL1_P => pll.unwrap(),
179+
_ => unreachable!(),
180+
};
181+
182+
let hclk = sys / config.ahb_pre;
183+
let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
184+
let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
185+
186+
let latency = match hclk.0 {
187+
..=24_000_000 => Latency::WS0,
188+
..=48_000_000 => Latency::WS1,
189+
_ => Latency::WS2,
190+
};
191+
FLASH.acr().modify(|w| {
192+
w.set_latency(latency);
193+
w.set_prftbe(true);
194+
});
195+
196+
RCC.cfgr().modify(|w| {
197+
w.set_ppre1(config.apb1_pre);
198+
w.set_ppre2(config.apb2_pre);
199+
w.set_hpre(config.ahb_pre);
200+
w.set_adcpre(config.adc_pre);
201+
if let Some(usb_pre) = config.usb_pre {
202+
w.set_usbpre(usb_pre);
203+
}
204+
});
205+
206+
if let Some(i2s2_src) = config.i2s2_src {
207+
RCC.cfgr2().modify(|w| w.set_i2s2src(i2s2_src));
208+
}
209+
210+
if let Some(i2s3_src) = config.i2s3_src {
211+
RCC.cfgr2().modify(|w| w.set_i2s3src(i2s3_src));
212+
}
213+
214+
cortex_m::asm::delay(16);
215+
216+
RCC.cfgr().modify(|w| w.set_sw(config.sys));
217+
while RCC.cfgr().read().sws() != config.sys {}
218+
219+
if !config.hsi {
220+
RCC.cr().modify(|w| w.set_hsion(false));
221+
}
222+
223+
// Set clocks
224+
set_clocks!(
225+
sys: Some(sys),
226+
hclk1: Some(hclk),
227+
pclk1: Some(pclk1),
228+
pclk1_tim: Some(pclk1_tim),
229+
pclk2: Some(pclk2),
230+
pclk2_tim: Some(pclk2_tim),
231+
pll1_p: pll,
232+
hsi: hsi,
233+
hse: hse,
234+
rtc: None,
235+
lsi: None,
236+
lse: None,
237+
usb: None,
238+
);
239+
}

embassy-stm32/src/rcc/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ mod hsi48;
1919
#[cfg(crs)]
2020
pub use hsi48::*;
2121

22-
#[cfg_attr(any(stm32f0, stm32f1, stm32f3), path = "f013.rs")]
22+
#[cfg_attr(any(stm32f0, all(stm32f1, not(stm32f107)), stm32f3), path = "f013.rs")]
23+
#[cfg_attr(any(stm32f107), path = "f107.rs")]
2324
#[cfg_attr(any(stm32f2, stm32f4, stm32f7), path = "f247.rs")]
2425
#[cfg_attr(stm32c0, path = "c0.rs")]
2526
#[cfg_attr(stm32g0, path = "g0.rs")]

0 commit comments

Comments
 (0)