|
| 1 | +//! Proof of Concept async runtime for the Cortex-M architecture |
| 2 | +
|
| 3 | +#![deny(missing_docs)] |
| 4 | +#![deny(rust_2018_idioms)] |
| 5 | +#![deny(warnings)] |
| 6 | +#![no_std] |
| 7 | + |
| 8 | +mod alloc; |
| 9 | +mod executor; |
| 10 | +pub mod task; |
| 11 | +pub mod unsync; |
| 12 | + |
| 13 | +#[cfg(target_arch = "arm")] |
| 14 | +use cortex_m::asm; |
| 15 | + |
| 16 | + |
| 17 | +#[cfg(target_arch = "arm")] |
| 18 | +pub use cortex_m_udf::udf as abort; |
| 19 | + |
| 20 | +#[cfg(target_arch = "arm")] |
| 21 | +#[inline] |
| 22 | +/// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed. |
| 23 | +/// This particular implementation does nothing, since `wait_for_interrupt` never sleeps |
| 24 | +pub(crate) unsafe fn signal_event_ready() { |
| 25 | + asm::sev(); |
| 26 | +} |
| 27 | + |
| 28 | +#[cfg(target_arch = "arm")] |
| 29 | +#[inline] |
| 30 | +/// Wait for an interrupt or until notified by other hart via `signal_task_ready` |
| 31 | +/// This particular implementation does nothing |
| 32 | +pub(crate) unsafe fn wait_for_event() { |
| 33 | + asm::wfe(); |
| 34 | +} |
| 35 | + |
| 36 | +#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))] |
| 37 | +/// This keeps dropping into the debugger and never returns |
| 38 | +pub fn abort() -> ! { |
| 39 | + loop { |
| 40 | + unsafe { riscv::asm::ebreak() } |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), feature = "riscv-wait-nop"))] |
| 45 | +#[inline] |
| 46 | +/// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed. |
| 47 | +/// This particular implementation does nothing, since `wait_for_interrupt` never sleeps |
| 48 | +pub(crate) unsafe fn signal_event_ready() {} |
| 49 | + |
| 50 | +#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), feature = "riscv-wait-nop"))] |
| 51 | +#[inline] |
| 52 | +/// Wait for an interrupt or until notified by other hart via `signal_task_ready` |
| 53 | +/// This particular implementation does nothing |
| 54 | +pub(crate) unsafe fn wait_for_event() {} |
| 55 | + |
| 56 | +#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), feature = "riscv-wait-extern"))] |
| 57 | +extern "C" { |
| 58 | + /// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed. |
| 59 | + /// User is expected to provide an actual implementation, like the one shown below. |
| 60 | + /// |
| 61 | + /// #[no_mangle] |
| 62 | + /// pub extern "C" fn signal_event_ready() { |
| 63 | + /// unimplemented!(); |
| 64 | + /// } |
| 65 | + pub(crate) fn signal_event_ready(); |
| 66 | + |
| 67 | + /// Wait for an interrupt or until notified by other hart via `signal_task_ready` |
| 68 | + /// User is expected to provide an actual implementation, like the one shown below. |
| 69 | + /// |
| 70 | + /// #[no_mangle] |
| 71 | + /// pub extern "C" fn wait_for_event() { |
| 72 | + /// unimplemented!(); |
| 73 | + /// } |
| 74 | + pub(crate) fn wait_for_event(); |
| 75 | +} |
| 76 | + |
| 77 | +#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), feature = "riscv-wait-wfi-single-hart"))] |
| 78 | +static mut TASK_READY: bool = false; |
| 79 | + |
| 80 | +#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), feature = "riscv-wait-wfi-single-hart"))] |
| 81 | +#[inline] |
| 82 | +/// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed. |
| 83 | +/// This particular implementation prevents `wait_for_interrupt` from sleeping by setting |
| 84 | +/// a global mutable flag |
| 85 | +pub(crate) unsafe fn signal_event_ready() { |
| 86 | + TASK_READY = true; |
| 87 | +} |
| 88 | + |
| 89 | +#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), feature = "riscv-wait-wfi-single-hart"))] |
| 90 | +#[inline] |
| 91 | +/// Wait for an interrupt or until notified by other hart via `signal_task_ready` |
| 92 | +/// This particular implementation decides whether to sleep or not by checking |
| 93 | +/// a global mutable flag that's set by `signal_task_ready` |
| 94 | +pub(crate) unsafe fn wait_for_event() { |
| 95 | + if !TASK_READY { |
| 96 | + riscv::asm::wfi(); |
| 97 | + } |
| 98 | + TASK_READY = false; |
| 99 | +} |
| 100 | + |
| 101 | +/// Maximum number of tasks (TODO this could be user configurable) |
| 102 | +type NTASKS = typenum::consts::U8; |
0 commit comments