Skip to content

Commit 4caea46

Browse files
authored
Merge pull request #4 from ilya-epifanov/risc-v
RISC-V support
2 parents 3128731 + 231d47c commit 4caea46

24 files changed

+155
-47
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[workspace]
22
members = [
3-
"async-cortex-m",
3+
"async-embedded",
44
"cortex-m-udf",
55
"nrf52",
66
"panic-udf",

async-cortex-m/src/lib.rs

Lines changed: 0 additions & 16 deletions
This file was deleted.

async-cortex-m/Cargo.toml renamed to async-embedded/Cargo.toml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,25 @@
22
authors = ["Jorge Aparicio <jorge.aparicio@ferrous-systems.com>"]
33
edition = "2018"
44
license = "MIT OR Apache-2.0"
5-
name = "async-cortex-m"
5+
name = "async-embedded"
66
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" }
1210
generic-array = "0.13.2"
1311
heapless = { git = "https://github.com/japaric/heapless", branch = "slab" }
1412
pin-utils = "0.1.0-alpha.4"
1513
typenum = "1.11.2"
14+
15+
[target.'cfg(target_arch = "arm")'.dependencies]
16+
cortex-m = "0.6.2"
17+
cortex-m-udf = { path = "../cortex-m-udf" }
18+
19+
[target.'cfg(any(target_arch = "riscv32", target_arch = "riscv64"))'.dependencies]
20+
riscv = "0.5.6"
21+
22+
[features]
23+
default = ["riscv-wait-nop"]
24+
riscv-wait-nop = []
25+
riscv-wait-wfi-single-hart = []
26+
riscv-wait-extern = []
File renamed without changes.

async-cortex-m/src/executor.rs renamed to async-embedded/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-embedded/src/lib.rs

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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;

async-cortex-m/src/task.rs renamed to async-embedded/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
}
File renamed without changes.

async-cortex-m/src/unsync/channel.rs renamed to async-embedded/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

0 commit comments

Comments
 (0)