1#![no_std]
2#![doc = include_str!("../README.md")]
3
4pub(crate) mod fmt;
6
7#[cfg(feature = "set-msplim")]
8use core::arch::global_asm;
9
10mod macros;
11
12mod utils;
13
14pub mod rcc;
15pub mod gpio;
16pub mod timer;
17pub mod time;
18pub mod pmu;
19pub mod usart;
20pub mod adc;
21pub mod lcdc;
22pub mod dma;
23#[cfg(feature = "usb")]
24pub mod usb;
25#[cfg(feature = "_time-driver")]
26pub mod time_driver;
27
28pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
30#[cfg(feature = "unstable-pac")]
31pub use sifli_pac as pac;
32#[cfg(not(feature = "unstable-pac"))]
33pub(crate) use sifli_pac as pac;
34
35pub mod mode {
37 trait SealedMode {}
38
39 #[allow(private_bounds)]
41 pub trait Mode: SealedMode {}
42
43 macro_rules! impl_mode {
44 ($name:ident) => {
45 impl SealedMode for $name {}
46 impl Mode for $name {}
47 };
48 }
49
50 pub struct Blocking;
52 pub struct Async;
54
55 impl_mode!(Blocking);
56 impl_mode!(Async);
57}
58
59pub mod config {
61 use crate::rcc;
62 use crate::interrupt;
63
64 #[non_exhaustive]
66 pub struct Config {
67 pub rcc: rcc::Config,
68 pub gpio1_it_priority: interrupt::Priority,
69 }
70
71 impl Default for Config {
72 fn default() -> Self {
73 Self {
74 rcc: rcc::Config::new_keep(),
75 gpio1_it_priority: interrupt::Priority::P3,
76 }
77 }
78 }
79}
80pub use config::Config;
81
82pub fn init(config: Config) -> Peripherals {
88 system_init();
89
90 let p = Peripherals::take();
93
94 unsafe {
95 config.rcc.apply();
96
97 #[cfg(feature = "_time-driver")]
98 time_driver::init();
99
100 gpio::init(config.gpio1_it_priority);
101 critical_section::with(|cs| {
102 dma::init(cs);
103 });
104
105 }
106 p
107}
108
109fn system_init() {
110 unsafe {
111 let mut cp = cortex_m::Peripherals::steal();
112
113 cp.SCB.cpacr.modify(|r| {
115 r | (0b111111)
116 });
117
118 cp.SCB.enable_icache();
120 cp.SCB.enable_dcache(&mut cp.CPUID);
121 }
122}
123
124pub(crate) mod _generated {
125 #![allow(dead_code)]
126 #![allow(unused_imports)]
127 #![allow(non_snake_case)]
128 #![allow(missing_docs)]
129
130 include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
131}
132
133pub use _generated::interrupt;
134pub use _generated::{peripherals, Peripherals};
135
136pub fn cortex_m_blocking_delay_us(us: u32) {
138 let freq = rcc::get_hclk_freq().unwrap().0 as u64;
139 let cycles = freq * us as u64 / 1_000_000;
140 cortex_m::asm::delay(cycles as u32);
141}
142
143pub fn blocking_delay_us(us: u32) {
145 #[cfg(feature = "time")]
146 embassy_time::block_for(embassy_time::Duration::from_micros(us as u64));
147 #[cfg(not(feature = "time"))]
148 cortex_m_blocking_delay_us(us);
149}
150
151#[macro_export]
169macro_rules! bind_interrupts {
170 ($vis:vis struct $name:ident {
171 $(
172 $(#[cfg($cond_irq:meta)])?
173 $irq:ident => $(
174 $(#[cfg($cond_handler:meta)])?
175 $handler:ty
176 ),*;
177 )*
178 }) => {
179 #[derive(Copy, Clone)]
180 $vis struct $name;
181
182 $(
183 #[allow(non_snake_case)]
184 #[no_mangle]
185 $(#[cfg($cond_irq)])?
186 unsafe extern "C" fn $irq() {
187 $(
188 $(#[cfg($cond_handler)])?
189 <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
190
191 )*
192 }
193
194 $(#[cfg($cond_irq)])?
195 $crate::bind_interrupts!(@inner
196 $(
197 $(#[cfg($cond_handler)])?
198 unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
199 )*
200 );
201 )*
202 };
203 (@inner $($t:tt)*) => {
204 $($t)*
205 }
206}
207
208#[cfg(feature = "set-msplim")]
210global_asm!(
211 ".section .text._pre_init",
212 ".global __pre_init",
213 ".type __pre_init, %function",
214 ".thumb_func",
215 "__pre_init:",
216 " ldr r0, =_stack_end",
217 " msr MSPLIM, r0",
218 " bx lr",
219 ".size __pre_init, . - __pre_init"
220);