stm32f1_hal/
interrupt.rs

1use crate::{Mcu, pac::Interrupt};
2use alloc::boxed::Box;
3use core::{
4    cell::{Cell, UnsafeCell},
5    mem::MaybeUninit,
6};
7
8pub struct Callback {
9    callback: UnsafeCell<MaybeUninit<Box<dyn FnMut()>>>,
10    once_flag: critical_section::Mutex<Cell<bool>>,
11    it_line: Interrupt,
12}
13
14unsafe impl Sync for Callback {}
15
16/// # Safety
17///
18/// Sharing it across multiple interrupt callbacks may lead to a data race.
19impl Callback {
20    pub const fn new(it_line: Interrupt) -> Self {
21        Self {
22            callback: UnsafeCell::new(MaybeUninit::uninit()),
23            once_flag: critical_section::Mutex::new(Cell::new(true)),
24            it_line,
25        }
26    }
27
28    /// Register the callback, and enable the interrupt line in NVIC.
29    /// You can call it only once.
30    pub fn set(&self, mcu: &mut Mcu, callback: impl FnMut() + 'static) {
31        let cb = Box::new(callback);
32        critical_section::with(|cs| {
33            assert!(self.once_flag.borrow(cs).get());
34            let callback = unsafe { &mut *self.callback.get() };
35            callback.write(cb);
36            self.once_flag.borrow(cs).set(false);
37        });
38        mcu.nvic.enable(self.it_line, true);
39    }
40
41    /// # Safety
42    ///
43    /// This function must only be called from interrupt context.
44    #[inline(always)]
45    pub unsafe fn call(&self) {
46        let cb = unsafe { (&mut *self.callback.get()).assume_init_mut() }.as_mut();
47        (*cb)();
48    }
49}
50
51#[macro_export]
52macro_rules! interrupt_handler {
53    ($(
54        ($LINE:ident, $CALLBACK:ident),
55    )+) => {
56        use $crate::pac::interrupt;
57        $(
58            pub static $CALLBACK: $crate::interrupt::Callback =
59                $crate::interrupt::Callback::new($crate::pac::Interrupt::$LINE);
60
61            #[allow(non_snake_case)]
62            #[interrupt]
63            fn $LINE() {
64                unsafe { $CALLBACK.call() }
65            }
66        )+
67    };
68}