1#![no_std]
4#![cfg_attr(nightly, feature(doc_cfg))]
5#![cfg_attr(feature = "rcc-config-override", expect(unsafe_code))]
6#![deny(missing_docs)]
7
8pub mod gpio;
9
10#[doc(hidden)]
11pub mod peripheral {
12 pub use embassy_stm32::Peri;
13}
14
15#[cfg(feature = "external-interrupts")]
16#[doc(hidden)]
17pub mod extint_registry;
18
19#[cfg(feature = "i2c")]
20pub mod i2c;
21
22#[doc(hidden)]
23pub mod identity;
24
25#[cfg(feature = "spi")]
26pub mod spi;
27
28#[cfg(feature = "uart")]
29pub mod uart;
30
31#[cfg(feature = "storage")]
32#[doc(hidden)]
33pub mod storage;
34
35#[cfg(feature = "usb")]
36#[doc(hidden)]
37pub mod usb;
38
39#[cfg(feature = "ethernet")]
40#[doc(hidden)]
41pub mod ethernet;
42
43use embassy_stm32::Config;
44
45#[doc(hidden)]
46pub use embassy_stm32::{OptionalPeripherals, Peri, PeripheralType, Peripherals, interrupt};
47
48pub use embassy_stm32::peripherals;
49
50#[cfg(feature = "executor-interrupt")]
51pub(crate) use embassy_executor::InterruptExecutor as Executor;
52
53#[cfg(feature = "hwrng")]
54#[doc(hidden)]
55pub mod hwrng;
56
57#[cfg(feature = "executor-interrupt")]
58include!(concat!(env!("OUT_DIR"), "/swi.rs"));
59
60#[cfg(capability = "hw/stm32-dual-core")]
61use {core::mem::MaybeUninit, embassy_stm32::SharedData};
62
63#[cfg(capability = "hw/stm32-dual-core")]
65static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
66
67#[cfg(feature = "executor-interrupt")]
68#[doc(hidden)]
69pub static EXECUTOR: Executor = Executor::new();
70
71#[doc(hidden)]
72pub trait IntoPeripheral<'a, T: PeripheralType>: private::Sealed {
73 fn into_hal_peripheral(self) -> Peri<'a, T>;
74}
75
76impl<T: PeripheralType> private::Sealed for Peri<'_, T> {}
77
78#[doc(hidden)]
79impl<'a, T: PeripheralType> IntoPeripheral<'a, T> for Peri<'a, T> {
80 fn into_hal_peripheral(self) -> Peri<'a, T> {
81 self
82 }
83}
84
85mod private {
86 pub trait Sealed {}
87}
88
89#[doc(hidden)]
90#[must_use]
91pub fn init() -> OptionalPeripherals {
92 let mut config = Config::default();
93 board_config(&mut config);
94
95 #[cfg(not(capability = "hw/stm32-dual-core"))]
96 let peripherals = embassy_stm32::init(config);
97
98 #[cfg(capability = "hw/stm32-dual-core")]
99 let peripherals = embassy_stm32::init_primary(config, &SHARED_DATA);
100
101 enable_flash_cache();
102
103 OptionalPeripherals::from(peripherals)
104}
105
106fn board_config(config: &mut Config) {
107 cfg_if::cfg_if! {
108 if #[cfg(feature = "rcc-config-override")] {
109 unsafe extern "Rust" {
110 fn __ariel_os_rcc_config() -> embassy_stm32::rcc::Config;
111 }
112 config.rcc = unsafe { __ariel_os_rcc_config() };
113 } else {
114 config.rcc = rcc_config();
115 }
116 }
117}
118
119#[cfg_attr(feature = "rcc-config-override", expect(dead_code))]
121fn rcc_config() -> embassy_stm32::rcc::Config {
122 #[allow(unused_mut, reason = "conditional compilation")]
123 let mut rcc = embassy_stm32::rcc::Config::default();
124
125 #[cfg(context = "st-b-l475e-iot01a")]
126 {
127 use embassy_stm32::rcc::*;
128
129 rcc.ls = LsConfig {
131 rtc: RtcClockSource::LSE,
132 lsi: false,
133 lse: Some(LseConfig {
134 frequency: embassy_stm32::time::Hertz(32768),
135 mode: LseMode::Oscillator(LseDrive::MediumHigh),
136 }),
137 };
138 rcc.hsi = false;
139 rcc.msi = Some(MSIRange::RANGE8M);
142 rcc.pll = Some(Pll {
143 source: PllSource::MSI,
144 prediv: PllPreDiv::DIV1, mul: PllMul::MUL20, divp: None,
147 divq: None,
148 divr: Some(PllRDiv::DIV2), });
150 rcc.sys = Sysclk::PLL1_R;
151 rcc.pllsai1 = Some(Pll {
152 source: PllSource::MSI,
153 prediv: PllPreDiv::DIV1,
154 mul: PllMul::MUL12, divp: None,
156 divq: Some(PllQDiv::DIV2), divr: None,
158 });
159 rcc.mux.clk48sel = mux::Clk48sel::PLLSAI1_Q;
162 }
163
164 #[cfg(context = "st-nucleo-wb55")]
165 {
166 use embassy_stm32::rcc::*;
167
168 rcc.hsi48 = Some(Hsi48Config {
169 sync_from_usb: true,
170 }); rcc.sys = Sysclk::PLL1_R;
172 rcc.hse = Some(Hse {
173 freq: embassy_stm32::time::Hertz(32000000),
174 mode: HseMode::Oscillator,
175 prescaler: HsePrescaler::DIV1,
176 });
177 rcc.pll = Some(Pll {
178 source: PllSource::HSE,
179 prediv: PllPreDiv::DIV2,
180 mul: PllMul::MUL10,
181 divp: None,
182 divq: None,
183 divr: Some(PllRDiv::DIV2), });
185 rcc.mux.clk48sel = mux::Clk48sel::HSI48;
186 }
187
188 #[cfg(any(context = "stm32f303cb", context = "stm32f303re"))]
189 {
190 use embassy_stm32::rcc::*;
191
192 rcc.hse = Some(Hse {
193 freq: embassy_stm32::time::Hertz(8000000),
194 mode: HseMode::Oscillator,
195 });
196 rcc.pll = Some(Pll {
197 src: PllSource::HSE,
198 prediv: PllPreDiv::DIV1,
199 mul: PllMul::MUL9,
200 });
201 rcc.ahb_pre = AHBPrescaler::DIV1;
202 rcc.apb1_pre = APBPrescaler::DIV4;
203 rcc.apb2_pre = APBPrescaler::DIV2;
204 rcc.sys = Sysclk::PLL1_P; }
206
207 #[cfg(context = "st-nucleo-f401re")]
208 {
209 use embassy_stm32::rcc::*;
210 rcc.hse = Some(Hse {
211 freq: embassy_stm32::time::Hertz(8000000),
212 mode: HseMode::Bypass,
213 });
214 rcc.pll_src = PllSource::HSE;
215 rcc.pll = Some(Pll {
216 prediv: PllPreDiv::DIV4,
217 mul: PllMul::MUL168,
218 divp: Some(PllPDiv::DIV4),
219 divq: Some(PllQDiv::DIV7),
220 divr: None,
221 });
222 rcc.ahb_pre = AHBPrescaler::DIV1;
223 rcc.apb1_pre = APBPrescaler::DIV4;
224 rcc.apb2_pre = APBPrescaler::DIV2;
225 rcc.sys = Sysclk::PLL1_P;
226 }
227
228 #[cfg(context = "st-nucleo-f767zi")]
229 {
230 use embassy_stm32::rcc::*;
231 rcc.hse = Some(Hse {
232 freq: embassy_stm32::time::Hertz(8000000),
233 mode: HseMode::Bypass,
234 });
235 rcc.pll_src = PllSource::HSE;
236 rcc.pll = Some(Pll {
237 prediv: PllPreDiv::DIV4,
238 mul: PllMul::MUL216,
239 divp: Some(PllPDiv::DIV2),
240 divq: None,
241 divr: None,
242 });
243 rcc.ahb_pre = AHBPrescaler::DIV1;
244 rcc.apb1_pre = APBPrescaler::DIV4;
245 rcc.apb2_pre = APBPrescaler::DIV2;
246 rcc.sys = Sysclk::PLL1_P;
247 }
248
249 #[cfg(context = "stm32h755zi")]
250 {
251 use embassy_stm32::rcc::*;
252
253 rcc.hsi = Some(HSIPrescaler::DIV1);
254 rcc.csi = true;
255 rcc.hsi48 = Some(Hsi48Config {
256 sync_from_usb: true,
257 }); rcc.pll1 = Some(Pll {
259 source: PllSource::HSI,
260 prediv: PllPreDiv::DIV4,
261 mul: PllMul::MUL50,
262 divp: Some(PllDiv::DIV2),
263 divq: Some(PllDiv::DIV16), divr: None,
266 });
267 rcc.sys = Sysclk::PLL1_P; rcc.ahb_pre = AHBPrescaler::DIV2; rcc.apb1_pre = APBPrescaler::DIV2; rcc.apb2_pre = APBPrescaler::DIV2; rcc.apb3_pre = APBPrescaler::DIV2; rcc.apb4_pre = APBPrescaler::DIV2; rcc.voltage_scale = VoltageScale::Scale1;
274 rcc.supply_config = SupplyConfig::DirectSMPS;
276 rcc.mux.usbsel = mux::Usbsel::HSI48;
277 rcc.mux.spi123sel = mux::Saisel::PLL1_Q; }
281
282 #[cfg(context = "stm32h753zi")]
283 {
284 use embassy_stm32::rcc::*;
285
286 rcc.hsi = Some(HSIPrescaler::DIV1);
287 rcc.csi = true;
288 rcc.hsi48 = Some(Hsi48Config {
289 sync_from_usb: true,
290 }); rcc.pll1 = Some(Pll {
292 source: PllSource::HSI,
293 prediv: PllPreDiv::DIV4,
294 mul: PllMul::MUL50,
295 divp: Some(PllDiv::DIV2),
296 divq: Some(PllDiv::DIV16), divr: None,
298 });
299 rcc.sys = Sysclk::PLL1_P; rcc.ahb_pre = AHBPrescaler::DIV2; rcc.apb1_pre = APBPrescaler::DIV2; rcc.apb2_pre = APBPrescaler::DIV2; rcc.apb3_pre = APBPrescaler::DIV2; rcc.apb4_pre = APBPrescaler::DIV2; rcc.voltage_scale = VoltageScale::Scale1;
306 rcc.mux.usbsel = mux::Usbsel::HSI48;
307 rcc.mux.spi123sel = mux::Saisel::PLL1_Q; }
311
312 #[cfg(any(context = "stm32u073kc", context = "stm32u083mc"))]
313 {
314 use embassy_stm32::rcc::*;
315
316 rcc.hsi48 = Some(Hsi48Config {
317 sync_from_usb: true,
318 }); rcc.hsi = true;
321 rcc.sys = Sysclk::PLL1_R;
322 rcc.pll = Some(Pll {
323 source: PllSource::HSI,
324 prediv: PllPreDiv::DIV1,
325 mul: PllMul::MUL7,
326 divp: None,
327 divq: None,
328 divr: Some(PllRDiv::DIV2), });
330 rcc.mux.clk48sel = mux::Clk48sel::HSI48;
331 }
332
333 #[cfg(context = "st-steval-mkboxpro")]
334 {
335 use embassy_stm32::rcc::*;
336
337 rcc.ls = LsConfig {
338 rtc: RtcClockSource::LSE,
339 lsi: true,
340 lse: Some(LseConfig {
341 peripherals_clocked: true,
342 frequency: embassy_stm32::time::Hertz(32768),
343 mode: LseMode::Oscillator(LseDrive::MediumHigh),
344 }),
345 };
346 rcc.hsi = true;
347 rcc.hsi48 = Some(Hsi48Config {
348 sync_from_usb: true,
349 }); rcc.sys = Sysclk::PLL1_R;
351 rcc.hse = Some(Hse {
352 freq: embassy_stm32::time::Hertz(16_000_000),
353 mode: HseMode::Oscillator,
354 });
355 rcc.pll1 = Some(Pll {
356 source: PllSource::HSE,
357 prediv: PllPreDiv::DIV1,
358 mul: PllMul::MUL10,
359 divp: None,
360 divq: None,
361 divr: Some(PllDiv::DIV1), });
363 rcc.sys = Sysclk::PLL1_R;
364 rcc.mux.iclksel = mux::Iclksel::HSI48;
365 rcc.voltage_range = VoltageScale::RANGE1;
366 }
367
368 #[cfg(context = "stm32f042k6")]
369 {
370 use embassy_stm32::rcc::*;
371
372 rcc.hsi48 = Some(Hsi48Config {
373 sync_from_usb: true,
374 }); rcc.sys = Sysclk::HSI48;
376 rcc.pll = Some(Pll {
377 src: PllSource::HSI48,
378 prediv: PllPreDiv::DIV2,
379 mul: PllMul::MUL2,
380 });
381 }
382
383 #[cfg(context = "seeedstudio-lora-e5-mini")]
384 {
385 use embassy_stm32::rcc::*;
386
387 rcc.hse = Some(Hse {
388 freq: embassy_stm32::time::Hertz(32_000_000),
389 mode: HseMode::Bypass,
390 prescaler: HsePrescaler::DIV1,
391 });
392 rcc.ls = LsConfig::default_lse();
393 rcc.msi = None;
394 rcc.pll = Some(Pll {
395 source: PllSource::HSE,
396 prediv: PllPreDiv::DIV2,
397 mul: PllMul::MUL6,
398 divp: None,
399 divq: Some(PllQDiv::DIV2), divr: Some(PllRDiv::DIV2), });
402
403 rcc.sys = Sysclk::PLL1_R;
404 }
405
406 #[cfg(context = "st-nucleo-wba65ri")]
407 {
408 use embassy_stm32::rcc::*;
409
410 rcc.hse = Some(Hse {
411 prescaler: HsePrescaler::DIV1,
412 });
413 rcc.pll1 = Some(Pll {
414 source: PllSource::HSE,
415 prediv: PllPreDiv::DIV2, mul: PllMul::MUL12, divp: Some(PllDiv::DIV6), divq: None,
419 divr: Some(PllDiv::DIV2), frac: None,
421 });
422 rcc.sys = Sysclk::PLL1_R;
423 rcc.voltage_scale = VoltageScale::RANGE1;
424 rcc.mux.otghssel = Otghssel::HSE; }
426
427 rcc
428}
429
430fn enable_flash_cache() {
431 #[cfg(any(context = "stm32f401re", context = "stm32f411re",))]
433 {
434 embassy_stm32::pac::FLASH
436 .acr()
437 .modify(|w| w.set_icrst(true));
438 embassy_stm32::pac::FLASH.acr().modify(|w| w.set_icen(true));
440 embassy_stm32::pac::FLASH
441 .acr()
442 .modify(|w| w.set_prften(true));
443 embassy_stm32::pac::FLASH
445 .acr()
446 .modify(|w| w.set_dcrst(true));
447 embassy_stm32::pac::FLASH
448 .acr()
449 .modify(|w| w.set_dcrst(false));
450 embassy_stm32::pac::FLASH.acr().modify(|w| w.set_dcen(true));
452 }
453}