Skip to content

Commit 8918a9c

Browse files
committed
abstracted async-cortex-m over specifics of WFE/SEV across ISAs. Added several RISC-V implementations of WFE/SEV, as RISC-V leaves implementation of these to SoC designers.
1 parent 3128731 commit 8918a9c

File tree

8 files changed

+122
-17
lines changed

8 files changed

+122
-17
lines changed

Cargo.lock

Lines changed: 19 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

async-cortex-m/Cargo.toml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@ publish = false
77
version = "0.0.0-alpha.0"
88

99
[dependencies]
10-
cortex-m = "0.6.2"
11-
cortex-m-udf = { path = "../cortex-m-udf" }
10+
cortex-m = { version = "0.6.2", optional = true }
11+
cortex-m-udf = { path = "../cortex-m-udf", optional = true }
1212
generic-array = "0.13.2"
1313
heapless = { git = "https://github.com/japaric/heapless", branch = "slab" }
1414
pin-utils = "0.1.0-alpha.4"
15+
riscv = { version = "0.5.6", optional = true }
1516
typenum = "1.11.2"
17+
18+
[features]
19+
default = ["riscv-wait-nop"]
20+
isa-cortex-m = ["cortex-m", "cortex-m-udf"]
21+
isa-riscv = ["riscv"]
22+
riscv-wait-nop = []
23+
riscv-wait-wfi-single-hart = []
24+
wait-extern = []

async-cortex-m/src/executor.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use core::{
77
task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
88
};
99

10-
use cortex_m::asm;
1110
use heapless::Vec;
1211
use pin_utils::pin_mut;
1312

@@ -120,7 +119,7 @@ impl Executor {
120119

121120
// try to sleep; this will be a no-op if any of the previous tasks generated a SEV or an
122121
// interrupt ran (regardless of whether it generated a wake-up or not)
123-
asm::wfe();
122+
unsafe { crate::wait_for_event() };
124123
};
125124
self.in_block_on.set(false);
126125
val

async-cortex-m/src/lib.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,92 @@ mod executor;
1010
pub mod task;
1111
pub mod unsync;
1212

13-
use cortex_m_udf::udf as abort;
13+
#[cfg(feature = "isa-cortex-m")]
14+
use cortex_m::asm;
15+
16+
#[cfg(feature = "isa-cortex-m")]
17+
pub use cortex_m_udf::udf as abort;
18+
19+
#[cfg(all(feature = "isa-cortex-m"))]
20+
#[inline]
21+
/// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed.
22+
/// This particular implementation does nothing, since `wait_for_interrupt` never sleeps
23+
pub(crate) unsafe fn signal_event_ready() {
24+
asm::sev();
25+
}
26+
27+
#[cfg(all(feature = "isa-cortex-m"))]
28+
#[inline]
29+
/// Wait for an interrupt or until notified by other hart via `signal_task_ready`
30+
/// This particular implementation does nothing
31+
pub(crate) unsafe fn wait_for_event() {
32+
asm::wfe();
33+
}
34+
35+
#[cfg(feature = "isa-riscv")]
36+
/// This keeps dropping into the debugger and never returns
37+
pub fn abort() -> ! {
38+
loop {
39+
unsafe { riscv::asm::ebreak() }
40+
}
41+
}
42+
43+
#[cfg(all(feature = "isa-riscv", feature = "riscv-wait-nop"))]
44+
#[inline]
45+
/// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed.
46+
/// This particular implementation does nothing, since `wait_for_interrupt` never sleeps
47+
pub(crate) unsafe fn signal_event_ready() {}
48+
49+
#[cfg(all(feature = "isa-riscv", feature = "riscv-wait-nop"))]
50+
#[inline]
51+
/// Wait for an interrupt or until notified by other hart via `signal_task_ready`
52+
/// This particular implementation does nothing
53+
pub(crate) unsafe fn wait_for_event() {}
54+
55+
#[cfg(all(feature = "isa-riscv", feature = "riscv-wait-extern"))]
56+
extern "C" {
57+
/// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed.
58+
/// User is expected to provide an actual implementation, like the one shown below.
59+
///
60+
/// #[no_mangle]
61+
/// pub extern "C" fn signal_event_ready() {
62+
/// unimplemented!();
63+
/// }
64+
pub(crate) fn signal_event_ready();
65+
66+
/// Wait for an interrupt or until notified by other hart via `signal_task_ready`
67+
/// User is expected to provide an actual implementation, like the one shown below.
68+
///
69+
/// #[no_mangle]
70+
/// pub extern "C" fn wait_for_event() {
71+
/// unimplemented!();
72+
/// }
73+
pub(crate) fn wait_for_event();
74+
}
75+
76+
#[cfg(all(feature = "isa-riscv", feature = "riscv-wait-wfi-single-hart"))]
77+
static mut TASK_READY: bool = false;
78+
79+
#[cfg(all(feature = "isa-riscv", feature = "riscv-wait-wfi-single-hart"))]
80+
#[inline]
81+
/// Prevent next `wait_for_interrupt` from sleeping, wake up other harts if needed.
82+
/// This particular implementation prevents `wait_for_interrupt` from sleeping by setting
83+
/// a global mutable flag
84+
pub(crate) unsafe fn signal_event_ready() {
85+
TASK_READY = true;
86+
}
87+
88+
#[cfg(all(feature = "isa-riscv", feature = "riscv-wait-wfi-single-hart"))]
89+
#[inline]
90+
/// Wait for an interrupt or until notified by other hart via `signal_task_ready`
91+
/// This particular implementation decides whether to sleep or not by checking
92+
/// a global mutable flag that's set by `signal_task_ready`
93+
pub(crate) unsafe fn wait_for_event() {
94+
if !TASK_READY {
95+
riscv::asm::wfi();
96+
TASK_READY = false;
97+
}
98+
}
1499

15100
/// Maximum number of tasks (TODO this could be user configurable)
16101
type NTASKS = typenum::consts::U8;

async-cortex-m/src/task.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ use core::{
66
task::{Context, Poll},
77
};
88

9-
use cortex_m::asm;
10-
119
use crate::executor;
1210

1311
/// Drives the future `f` to completion
@@ -43,7 +41,7 @@ pub async fn r#yield() {
4341
self.yielded = true;
4442
// wake ourselves
4543
cx.waker().wake_by_ref();
46-
asm::sev();
44+
unsafe { crate::signal_event_ready(); }
4745
Poll::Pending
4846
}
4947
}

async-cortex-m/src/unsync/channel.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use core::{
1212
task::{Context, Poll},
1313
};
1414

15-
use cortex_m::asm;
1615
use generic_array::{typenum::Unsigned, GenericArray};
1716

1817
use super::waker_set::WakerSet;
@@ -137,7 +136,7 @@ impl<T> Channel<T> {
137136
self.read.set(read.wrapping_add(1));
138137
// notify a sender
139138
self.send_wakers.notify_one();
140-
asm::sev();
139+
crate::signal_event_ready();
141140
Some(val)
142141
} else {
143142
// empty
@@ -162,7 +161,7 @@ impl<T> Channel<T> {
162161
self.write.set(write.wrapping_add(1));
163162
// notify a receiver
164163
self.recv_wakers.notify_one();
165-
asm::sev();
164+
crate::signal_event_ready();
166165
Ok(())
167166
} else {
168167
// full

async-cortex-m/src/unsync/mutex.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use core::{
88
task::{Context, Poll},
99
};
1010

11-
use cortex_m::asm;
12-
1311
use super::waker_set::WakerSet;
1412

1513
/// A mutual exclusion primitive for protecting shared data
@@ -94,7 +92,7 @@ impl<T> Drop for MutexGuard<'_, T> {
9492
fn drop(&mut self) {
9593
self.0.locked.set(false);
9694
self.0.wakers.notify_any();
97-
asm::sev();
95+
unsafe { crate::signal_event_ready(); }
9896
}
9997
}
10098

nrf52/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ panic-semihosting = "0.5.3"
1515
panic-udf = { path = "../panic-udf" }
1616

1717
[dependencies]
18-
async-cortex-m = { path = "../async-cortex-m" }
18+
async-cortex-m = { path = "../async-cortex-m", features = ["isa-cortex-m"] }
1919
cortex-m = "0.6.2"
2020
cortex-m-rt = "0.6.12"
2121
pac = { package = "nrf52840-pac", version = "0.9.0", features = ["rt"] }

0 commit comments

Comments
 (0)