aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-05-27 13:36:14 +0200
committerGitHub <[email protected]>2021-05-27 13:36:14 +0200
commit3f6f1d99bb90b478aa5c4c7d4ccc062e830c667a (patch)
tree3bf57900621b0ab930b8861093b73f7399f66373
parent1d3e685821bea75fe61919b5a38dbaf78bff55b3 (diff)
parent3669eba561aa25c492e446c72899452e61e5a921 (diff)
Merge pull request #207 from lulf/clock-init
Enable clock by default for stm32l0
-rw-r--r--embassy-macros/src/chip/stm32.rs17
-rw-r--r--embassy-stm32/src/clock.rs19
-rw-r--r--embassy-stm32/src/lib.rs7
-rw-r--r--embassy-stm32/src/rcc/h7/mod.rs5
-rw-r--r--embassy-stm32/src/rcc/l0/mod.rs485
-rw-r--r--embassy-stm32/src/rcc/mod.rs35
6 files changed, 551 insertions, 17 deletions
diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs
index a1ceadd55..274560a03 100644
--- a/embassy-macros/src/chip/stm32.rs
+++ b/embassy-macros/src/chip/stm32.rs
@@ -7,20 +7,21 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream
7 let embassy_stm32_path = embassy_prefix.append("embassy_stm32").path(); 7 let embassy_stm32_path = embassy_prefix.append("embassy_stm32").path();
8 8
9 quote!( 9 quote!(
10 use #embassy_stm32_path::{clock::Clock}; 10 use #embassy_stm32_path::{interrupt, peripherals, clock::Clock, time::Hertz};
11 11
12 let p = #embassy_stm32_path::init(#config); 12 let p = #embassy_stm32_path::init(#config);
13 13
14 /* 14 let mut c = Clock::new(
15 let mut rtc = #embass::RTC::new(unsafe { <peripherals::TIM2 as #embassy_path::util::Steal>::steal() }, interrupt::take!(TIM2)); 15 unsafe { <peripherals::TIM2 as embassy::util::Steal>::steal() },
16 let rtc = unsafe { make_static(&mut rtc) }; 16 interrupt::take!(TIM2),
17 rtc.start(); 17 );
18 let mut alarm = rtc.alarm0(); 18 let clock = unsafe { make_static(&mut c) };
19 clock.start_tim2();
19 20
20 unsafe { #embassy_path::time::set_clock(rtc) }; 21 let mut alarm = clock.alarm1();
22 unsafe { #embassy_path::time::set_clock(clock) };
21 23
22 let alarm = unsafe { make_static(&mut alarm) }; 24 let alarm = unsafe { make_static(&mut alarm) };
23 executor.set_alarm(alarm); 25 executor.set_alarm(alarm);
24 */
25 ) 26 )
26} 27}
diff --git a/embassy-stm32/src/clock.rs b/embassy-stm32/src/clock.rs
index 709a2d36c..3ae83bbb0 100644
--- a/embassy-stm32/src/clock.rs
+++ b/embassy-stm32/src/clock.rs
@@ -10,6 +10,7 @@ use embassy::time::{Clock as EmbassyClock, TICKS_PER_SECOND};
10 10
11use crate::interrupt::{CriticalSection, Interrupt, Mutex}; 11use crate::interrupt::{CriticalSection, Interrupt, Mutex};
12use crate::pac::timer::TimGp16; 12use crate::pac::timer::TimGp16;
13use crate::rcc::get_freqs;
13use crate::time::Hertz; 14use crate::time::Hertz;
14 15
15// Clock timekeeping works with something we call "periods", which are time intervals 16// Clock timekeeping works with something we call "periods", which are time intervals
@@ -75,6 +76,24 @@ impl<T: Instance> Clock<T> {
75 } 76 }
76 } 77 }
77 78
79 // TODO: Temporary until clock code generation is in place
80 pub fn start_tim2(&'static self) {
81 cfg_if::cfg_if! {
82 if #[cfg(feature = "_stm32l0")] {
83 unsafe {
84 let rcc = crate::pac::RCC;
85 rcc.apb1enr()
86 .modify(|w| w.set_tim2en(crate::pac::rcc::vals::Lptimen::ENABLED));
87 rcc.apb1rstr().modify(|w| w.set_tim2rst(true));
88 rcc.apb1rstr().modify(|w| w.set_tim2rst(false));
89 }
90
91 let timer_freq = unsafe { crate::rcc::get_freqs().apb1_clk };
92 self.start(timer_freq);
93 }
94 }
95 }
96
78 pub fn start(&'static self, timer_freq: Hertz) { 97 pub fn start(&'static self, timer_freq: Hertz) {
79 let inner = T::inner(); 98 let inner = T::inner();
80 99
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 365b58f3c..01e6ea51b 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -47,6 +47,13 @@ pub struct Config {
47 rcc: rcc::Config, 47 rcc: rcc::Config,
48} 48}
49 49
50impl Config {
51 pub fn rcc(mut self, rcc: rcc::Config) -> Self {
52 self.rcc = rcc;
53 self
54 }
55}
56
50impl Default for Config { 57impl Default for Config {
51 fn default() -> Self { 58 fn default() -> Self {
52 Self { 59 Self {
diff --git a/embassy-stm32/src/rcc/h7/mod.rs b/embassy-stm32/src/rcc/h7/mod.rs
index 85e1cd00f..26d9f0bb9 100644
--- a/embassy-stm32/src/rcc/h7/mod.rs
+++ b/embassy-stm32/src/rcc/h7/mod.rs
@@ -528,6 +528,5 @@ impl<'d> Rcc<'d> {
528 } 528 }
529} 529}
530 530
531pub unsafe fn init(config: Config) { 531// TODO
532 // TODO 532pub unsafe fn init(_config: Config) {}
533}
diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0/mod.rs
index 000aaa9e0..0cf3c2cb7 100644
--- a/embassy-stm32/src/rcc/l0/mod.rs
+++ b/embassy-stm32/src/rcc/l0/mod.rs
@@ -1,13 +1,484 @@
1use crate::pac; 1use crate::pac;
2use embassy::util::Steal; 2use crate::pac::peripherals::{self, RCC};
3use pac::rcc::{self, vals}; 3use crate::rcc::{set_freqs, Clocks};
4use crate::time::Hertz;
5use crate::time::U32Ext;
6use embassy::util::Unborrow;
7use pac::rcc::vals;
8use vals::{Hpre, Msirange, Plldiv, Pllmul, Pllon, Pllsrc, Ppre, Sw};
4 9
5#[derive(Default)] 10/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
6pub struct Config {} 11/// and with the addition of the init function to configure a system clock.
12
13/// System clock mux source
14#[derive(Clone, Copy)]
15pub enum ClockSrc {
16 MSI(MSIRange),
17 PLL(PLLSource, PLLMul, PLLDiv),
18 HSE(Hertz),
19 HSI16,
20}
21
22/// MSI Clock Range
23///
24/// These ranges control the frequency of the MSI. Internally, these ranges map
25/// to the `MSIRANGE` bits in the `RCC_ICSCR` register.
26#[derive(Clone, Copy)]
27pub enum MSIRange {
28 /// Around 65.536 kHz
29 Range0,
30 /// Around 131.072 kHz
31 Range1,
32 /// Around 262.144 kHz
33 Range2,
34 /// Around 524.288 kHz
35 Range3,
36 /// Around 1.048 MHz
37 Range4,
38 /// Around 2.097 MHz (reset value)
39 Range5,
40 /// Around 4.194 MHz
41 Range6,
42}
43
44impl Default for MSIRange {
45 fn default() -> MSIRange {
46 MSIRange::Range5
47 }
48}
49
50/// PLL divider
51#[derive(Clone, Copy)]
52pub enum PLLDiv {
53 Div2,
54 Div3,
55 Div4,
56}
57
58/// PLL multiplier
59#[derive(Clone, Copy)]
60pub enum PLLMul {
61 Mul3,
62 Mul4,
63 Mul6,
64 Mul8,
65 Mul12,
66 Mul16,
67 Mul24,
68 Mul32,
69 Mul48,
70}
71
72/// AHB prescaler
73#[derive(Clone, Copy)]
74pub enum AHBPrescaler {
75 NotDivided,
76 Div2,
77 Div4,
78 Div8,
79 Div16,
80 Div64,
81 Div128,
82 Div256,
83 Div512,
84}
85
86/// APB prescaler
87#[derive(Clone, Copy)]
88pub enum APBPrescaler {
89 NotDivided,
90 Div2,
91 Div4,
92 Div8,
93 Div16,
94}
95
96/// PLL clock input source
97#[derive(Clone, Copy)]
98pub enum PLLSource {
99 HSI16,
100 HSE(Hertz),
101}
102
103/// HSI speed
104pub const HSI_FREQ: u32 = 16_000_000;
105
106impl Into<Pllmul> for PLLMul {
107 fn into(self) -> Pllmul {
108 match self {
109 PLLMul::Mul3 => Pllmul::MUL3,
110 PLLMul::Mul4 => Pllmul::MUL4,
111 PLLMul::Mul6 => Pllmul::MUL6,
112 PLLMul::Mul8 => Pllmul::MUL8,
113 PLLMul::Mul12 => Pllmul::MUL12,
114 PLLMul::Mul16 => Pllmul::MUL16,
115 PLLMul::Mul24 => Pllmul::MUL24,
116 PLLMul::Mul32 => Pllmul::MUL32,
117 PLLMul::Mul48 => Pllmul::MUL48,
118 }
119 }
120}
121
122impl Into<Plldiv> for PLLDiv {
123 fn into(self) -> Plldiv {
124 match self {
125 PLLDiv::Div2 => Plldiv::DIV2,
126 PLLDiv::Div3 => Plldiv::DIV3,
127 PLLDiv::Div4 => Plldiv::DIV4,
128 }
129 }
130}
131
132impl Into<Pllsrc> for PLLSource {
133 fn into(self) -> Pllsrc {
134 match self {
135 PLLSource::HSI16 => Pllsrc::HSI16,
136 PLLSource::HSE(_) => Pllsrc::HSE,
137 }
138 }
139}
140
141impl Into<Ppre> for APBPrescaler {
142 fn into(self) -> Ppre {
143 match self {
144 APBPrescaler::NotDivided => Ppre::DIV1,
145 APBPrescaler::Div2 => Ppre::DIV2,
146 APBPrescaler::Div4 => Ppre::DIV4,
147 APBPrescaler::Div8 => Ppre::DIV8,
148 APBPrescaler::Div16 => Ppre::DIV16,
149 }
150 }
151}
152
153impl Into<Hpre> for AHBPrescaler {
154 fn into(self) -> Hpre {
155 match self {
156 AHBPrescaler::NotDivided => Hpre::DIV1,
157 AHBPrescaler::Div2 => Hpre::DIV2,
158 AHBPrescaler::Div4 => Hpre::DIV4,
159 AHBPrescaler::Div8 => Hpre::DIV8,
160 AHBPrescaler::Div16 => Hpre::DIV16,
161 AHBPrescaler::Div64 => Hpre::DIV64,
162 AHBPrescaler::Div128 => Hpre::DIV128,
163 AHBPrescaler::Div256 => Hpre::DIV256,
164 AHBPrescaler::Div512 => Hpre::DIV512,
165 }
166 }
167}
168
169impl Into<Msirange> for MSIRange {
170 fn into(self) -> Msirange {
171 match self {
172 MSIRange::Range0 => Msirange::RANGE0,
173 MSIRange::Range1 => Msirange::RANGE1,
174 MSIRange::Range2 => Msirange::RANGE2,
175 MSIRange::Range3 => Msirange::RANGE3,
176 MSIRange::Range4 => Msirange::RANGE4,
177 MSIRange::Range5 => Msirange::RANGE5,
178 MSIRange::Range6 => Msirange::RANGE6,
179 }
180 }
181}
182
183/// Clocks configutation
184pub struct Config {
185 mux: ClockSrc,
186 ahb_pre: AHBPrescaler,
187 apb1_pre: APBPrescaler,
188 apb2_pre: APBPrescaler,
189}
190
191impl Default for Config {
192 #[inline]
193 fn default() -> Config {
194 Config {
195 mux: ClockSrc::MSI(MSIRange::default()),
196 ahb_pre: AHBPrescaler::NotDivided,
197 apb1_pre: APBPrescaler::NotDivided,
198 apb2_pre: APBPrescaler::NotDivided,
199 }
200 }
201}
202
203impl Config {
204 #[inline]
205 pub fn clock_src(mut self, mux: ClockSrc) -> Self {
206 self.mux = mux;
207 self
208 }
209
210 #[inline]
211 pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self {
212 self.ahb_pre = pre;
213 self
214 }
215
216 #[inline]
217 pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self {
218 self.apb1_pre = pre;
219 self
220 }
221
222 #[inline]
223 pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self {
224 self.apb2_pre = pre;
225 self
226 }
227}
228
229/// RCC peripheral
230pub struct Rcc {}
231
232impl Rcc {
233 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'static) -> Self {
234 Self {}
235 }
236}
237
238/*
239 pub fn enable_lse(&mut self, _: &PWR) -> LSE {
240 self.rb.csr.modify(|_, w| {
241 // Enable LSE clock
242 w.lseon().set_bit()
243 });
244 while self.rb.csr.read().lserdy().bit_is_clear() {}
245 LSE(())
246 }
247}
248impl Rcc {
249 pub fn enable_hsi48(&mut self, syscfg: &mut SYSCFG, crs: CRS) -> HSI48 {
250 // Reset CRS peripheral
251 self.rb.apb1rstr.modify(|_, w| w.crsrst().set_bit());
252 self.rb.apb1rstr.modify(|_, w| w.crsrst().clear_bit());
253
254 // Enable CRS peripheral
255 self.rb.apb1enr.modify(|_, w| w.crsen().set_bit());
256
257 // Initialize CRS
258 crs.cfgr.write(|w|
259 // Select LSE as synchronization source
260 unsafe { w.syncsrc().bits(0b01) });
261 crs.cr
262 .modify(|_, w| w.autotrimen().set_bit().cen().set_bit());
263
264 // Enable VREFINT reference for HSI48 oscillator
265 syscfg
266 .syscfg
267 .cfgr3
268 .modify(|_, w| w.enref_hsi48().set_bit().en_vrefint().set_bit());
269
270 // Select HSI48 as USB clock
271 self.rb.ccipr.modify(|_, w| w.hsi48msel().set_bit());
272
273 // Enable dedicated USB clock
274 self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit());
275 while self.rb.crrcr.read().hsi48rdy().bit_is_clear() {}
276
277 HSI48(())
278 }
279}
280
281impl Rcc {
282 /// Configure MCO (Microcontroller Clock Output).
283 pub fn configure_mco<P>(
284 &mut self,
285 source: MCOSEL_A,
286 prescaler: MCOPRE_A,
287 output_pin: P,
288 ) -> MCOEnabled
289 where
290 P: mco::Pin,
291 {
292 output_pin.into_mco();
293
294 self.rb.cfgr.modify(|_, w| {
295 w.mcosel().variant(source);
296 w.mcopre().variant(prescaler)
297 });
298
299 MCOEnabled(())
300 }
301}
302*/
303
304/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
305pub trait RccExt {
306 fn freeze(self, config: Config) -> Clocks;
307}
308
309impl RccExt for RCC {
310 // `cfgr` is almost always a constant, so make sure it can be constant-propagated properly by
311 // marking this function and all `Config` constructors and setters as `#[inline]`.
312 // This saves ~900 Bytes for the `pwr.rs` example.
313 #[inline]
314 fn freeze(self, cfgr: Config) -> Clocks {
315 let rcc = pac::RCC;
316 let (sys_clk, sw) = match cfgr.mux {
317 ClockSrc::MSI(range) => {
318 // Set MSI range
319 unsafe {
320 rcc.icscr().write(|w| w.set_msirange(range.into()));
321 }
322
323 // Enable MSI
324 unsafe {
325 rcc.cr().write(|w| w.set_msion(Pllon::ENABLED));
326 while !rcc.cr().read().msirdy() {}
327 }
328
329 let freq = 32_768 * (1 << (range as u8 + 1));
330 (freq, Sw::MSI)
331 }
332 ClockSrc::HSI16 => {
333 // Enable HSI16
334 unsafe {
335 rcc.cr().write(|w| w.set_hsi16on(Pllon::ENABLED));
336 while !rcc.cr().read().hsi16rdyf() {}
337 }
338
339 (HSI_FREQ, Sw::HSI16)
340 }
341 ClockSrc::HSE(freq) => {
342 // Enable HSE
343 unsafe {
344 rcc.cr().write(|w| w.set_hseon(Pllon::ENABLED));
345 while !rcc.cr().read().hserdy() {}
346 }
347
348 (freq.0, Sw::HSE)
349 }
350 ClockSrc::PLL(src, mul, div) => {
351 let freq = match src {
352 PLLSource::HSE(freq) => {
353 // Enable HSE
354 unsafe {
355 rcc.cr().write(|w| w.set_hseon(Pllon::ENABLED));
356 while !rcc.cr().read().hserdy() {}
357 }
358 freq.0
359 }
360 PLLSource::HSI16 => {
361 // Enable HSI
362 unsafe {
363 rcc.cr().write(|w| w.set_hsi16on(Pllon::ENABLED));
364 while !rcc.cr().read().hsi16rdyf() {}
365 }
366 HSI_FREQ
367 }
368 };
369
370 // Disable PLL
371 unsafe {
372 rcc.cr().modify(|w| w.set_pllon(Pllon::DISABLED));
373 while rcc.cr().read().pllrdy() {}
374 }
375
376 let freq = match mul {
377 PLLMul::Mul3 => freq * 3,
378 PLLMul::Mul4 => freq * 4,
379 PLLMul::Mul6 => freq * 6,
380 PLLMul::Mul8 => freq * 8,
381 PLLMul::Mul12 => freq * 12,
382 PLLMul::Mul16 => freq * 16,
383 PLLMul::Mul24 => freq * 24,
384 PLLMul::Mul32 => freq * 32,
385 PLLMul::Mul48 => freq * 48,
386 };
387
388 let freq = match div {
389 PLLDiv::Div2 => freq / 2,
390 PLLDiv::Div3 => freq / 3,
391 PLLDiv::Div4 => freq / 4,
392 };
393 assert!(freq <= 32_u32.mhz().0);
394
395 unsafe {
396 rcc.cfgr().write(move |w| {
397 w.set_pllmul(mul.into());
398 w.set_plldiv(div.into());
399 w.set_pllsrc(src.into());
400 });
401
402 // Enable PLL
403 rcc.cr().modify(|w| w.set_pllon(Pllon::ENABLED));
404 while !rcc.cr().read().pllrdy() {}
405 }
406
407 (freq, Sw::PLL)
408 }
409 };
410
411 unsafe {
412 rcc.cfgr().modify(|w| {
413 w.set_sw(sw.into());
414 w.set_hpre(cfgr.ahb_pre.into());
415 w.set_ppre(0, cfgr.apb1_pre.into());
416 w.set_ppre(1, cfgr.apb2_pre.into());
417 });
418 }
419
420 let ahb_freq: u32 = match cfgr.ahb_pre {
421 AHBPrescaler::NotDivided => sys_clk,
422 pre => {
423 let pre: Hpre = pre.into();
424 let pre = 1 << (pre.0 as u32 - 7);
425 sys_clk / pre
426 }
427 };
428
429 let (apb1_freq, apb1_tim_freq, apb1_pre) = match cfgr.apb1_pre {
430 APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1),
431 pre => {
432 let pre: Ppre = pre.into();
433 let pre: u8 = 1 << (pre.0 - 3);
434 let freq = ahb_freq / pre as u32;
435 (freq, freq * 2, pre as u8)
436 }
437 };
438
439 let (apb2_freq, apb2_tim_freq, apb2_pre) = match cfgr.apb2_pre {
440 APBPrescaler::NotDivided => (ahb_freq, ahb_freq, 1),
441 pre => {
442 let pre: Ppre = pre.into();
443 let pre: u8 = 1 << (pre.0 - 3);
444 let freq = ahb_freq / (1 << (pre as u8 - 3));
445 (freq, freq * 2, pre as u8)
446 }
447 };
448
449 Clocks {
450 sys_clk: sys_clk.hz(),
451 ahb_clk: ahb_freq.hz(),
452 apb1_clk: apb1_freq.hz(),
453 apb2_clk: apb2_freq.hz(),
454 apb1_tim_clk: apb1_tim_freq.hz(),
455 apb2_tim_clk: apb2_tim_freq.hz(),
456 apb1_pre,
457 apb2_pre,
458 }
459 }
460}
461
462/// Token that exists only, if the HSI48 clock has been enabled
463///
464/// You can get an instance of this struct by calling [`Rcc::enable_hsi48`].
465#[derive(Clone, Copy)]
466pub struct HSI48(());
467
468/// Token that exists only if MCO (Microcontroller Clock Out) has been enabled.
469///
470/// You can get an instance of this struct by calling [`Rcc::configure_mco`].
471#[derive(Clone, Copy)]
472pub struct MCOEnabled(());
473
474/// Token that exists only, if the LSE clock has been enabled
475///
476/// You can get an instance of this struct by calling [`Rcc::enable_lse`].
477#[derive(Clone, Copy)]
478pub struct LSE(());
7 479
8pub unsafe fn init(config: Config) { 480pub unsafe fn init(config: Config) {
9 let rcc = pac::RCC; 481 let rcc = pac::RCC;
10
11 let enabled = vals::Iophen::ENABLED; 482 let enabled = vals::Iophen::ENABLED;
12 rcc.iopenr().write(|w| { 483 rcc.iopenr().write(|w| {
13 w.set_iopaen(enabled); 484 w.set_iopaen(enabled);
@@ -17,4 +488,8 @@ pub unsafe fn init(config: Config) {
17 w.set_iopeen(enabled); 488 w.set_iopeen(enabled);
18 w.set_iophen(enabled); 489 w.set_iophen(enabled);
19 }); 490 });
491
492 let r = <peripherals::RCC as embassy::util::Steal>::steal();
493 let clocks = r.freeze(config);
494 set_freqs(clocks);
20} 495}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 59938e7bf..cb8780343 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -1,3 +1,35 @@
1use crate::time::Hertz;
2use core::mem::MaybeUninit;
3
4/// Frozen clock frequencies
5///
6/// The existence of this value indicates that the clock configuration can no longer be changed
7#[derive(Clone, Copy)]
8pub struct Clocks {
9 pub sys_clk: Hertz,
10 pub ahb_clk: Hertz,
11 pub apb1_clk: Hertz,
12 pub apb1_tim_clk: Hertz,
13 pub apb2_clk: Hertz,
14 pub apb2_tim_clk: Hertz,
15 pub apb1_pre: u8,
16 pub apb2_pre: u8,
17}
18
19static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
20
21/// Sets the clock frequencies
22///
23/// Safety: Sets a mutable global.
24pub unsafe fn set_freqs(freqs: Clocks) {
25 CLOCK_FREQS.as_mut_ptr().write(freqs);
26}
27
28/// Safety: Reads a mutable global.
29pub unsafe fn get_freqs() -> &'static Clocks {
30 &*CLOCK_FREQS.as_ptr()
31}
32
1cfg_if::cfg_if! { 33cfg_if::cfg_if! {
2 if #[cfg(feature = "_stm32h7")] { 34 if #[cfg(feature = "_stm32h7")] {
3 mod h7; 35 mod h7;
@@ -8,6 +40,7 @@ cfg_if::cfg_if! {
8 } else { 40 } else {
9 #[derive(Default)] 41 #[derive(Default)]
10 pub struct Config {} 42 pub struct Config {}
11 pub fn init(_config: Config) {} 43 pub unsafe fn init(_config: Config) {
44 }
12 } 45 }
13} 46}