aboutsummaryrefslogtreecommitdiff
path: root/embassy-executor/src/arch/cortex_m.rs
blob: a29e5b23e94538d1cce54e850ddcbd1aa0547d92 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#[cfg(feature = "executor-thread")]
pub use thread::*;

#[cfg(feature = "executor-thread")]
mod thread {

    #[cfg(feature = "nightly")]
    pub use embassy_macros::main_cortex_m as main;

    use crate::raw::OpaqueThreadContext;
    use crate::thread::ThreadContext;

    #[export_name = "__thread_mode_pender"]
    fn __thread_mode_pender(_context: OpaqueThreadContext) {
        unsafe { core::arch::asm!("sev") }
    }

    /// TODO
    // Name pending
    #[derive(Default)] // Default enables Executor::new
    pub struct Context;

    impl ThreadContext for Context {
        fn context(&self) -> OpaqueThreadContext {
            OpaqueThreadContext(0)
        }

        fn wait(&mut self) {
            unsafe { core::arch::asm!("wfe") }
        }
    }

    /// TODO
    // Type alias for backwards compatibility
    pub type Executor = crate::thread::ThreadModeExecutor<Context>;
}

// None of this has to be public, I guess?
#[cfg(feature = "executor-interrupt")]
pub use interrupt::*;
#[cfg(feature = "executor-interrupt")]
mod interrupt {
    use cortex_m::interrupt::InterruptNumber;
    use cortex_m::peripheral::NVIC;

    use crate::interrupt::InterruptContext;
    use crate::raw::OpaqueInterruptContext;

    #[derive(Clone, Copy)]
    struct CortexMInterruptContext(u16);

    unsafe impl cortex_m::interrupt::InterruptNumber for CortexMInterruptContext {
        fn number(self) -> u16 {
            self.0
        }
    }

    impl<T> InterruptContext for T
    where
        T: InterruptNumber,
    {
        fn context(&self) -> OpaqueInterruptContext {
            OpaqueInterruptContext(self.number() as usize)
        }

        fn enable(&self) {
            unsafe { NVIC::unmask(*self) }
        }
    }

    #[export_name = "__interrupt_mode_pender"]
    fn __interrupt_mode_pender(interrupt: OpaqueInterruptContext) {
        let interrupt = CortexMInterruptContext(unsafe { core::mem::transmute::<_, usize>(interrupt) as u16 });

        // STIR is faster, but is only available in v7 and higher.
        #[cfg(not(armv6m))]
        {
            let mut nvic: NVIC = unsafe { core::mem::transmute(()) };
            nvic.request(interrupt);
        }

        #[cfg(armv6m)]
        NVIC::pend(interrupt);
    }

    /// TODO
    // Type alias for backwards compatibility
    pub type InterruptExecutor = crate::interrupt::InterruptModeExecutor;
}