aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy/Cargo.toml1
-rw-r--r--embassy/src/executor/arch/riscv32.rs74
-rw-r--r--embassy/src/executor/mod.rs5
-rw-r--r--embassy/src/time/mod.rs3
4 files changed, 83 insertions, 0 deletions
diff --git a/embassy/Cargo.toml b/embassy/Cargo.toml
index 1d193d6a6..d2c96e30d 100644
--- a/embassy/Cargo.toml
+++ b/embassy/Cargo.toml
@@ -47,6 +47,7 @@ time = []
47time-tick-32768hz = ["time"] 47time-tick-32768hz = ["time"]
48time-tick-1000hz = ["time"] 48time-tick-1000hz = ["time"]
49time-tick-1mhz = ["time"] 49time-tick-1mhz = ["time"]
50time-tick-16mhz = ["time"]
50 51
51executor-agnostic = [] 52executor-agnostic = []
52 53
diff --git a/embassy/src/executor/arch/riscv32.rs b/embassy/src/executor/arch/riscv32.rs
new file mode 100644
index 000000000..7a7d5698c
--- /dev/null
+++ b/embassy/src/executor/arch/riscv32.rs
@@ -0,0 +1,74 @@
1use core::marker::PhantomData;
2use core::ptr;
3
4use atomic_polyfill::{AtomicBool, Ordering};
5
6use super::{raw, Spawner};
7
8/// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV
9///
10static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false);
11
12/// RISCV32 Executor
13pub struct Executor {
14 inner: raw::Executor,
15 not_send: PhantomData<*mut ()>,
16}
17
18impl Executor {
19 /// Create a new Executor.
20 pub fn new() -> Self {
21 Self {
22 // use Signal_Work_Thread_Mode as substitute for local interrupt register
23 inner: raw::Executor::new(
24 |_| {
25 SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst);
26 },
27 ptr::null_mut(),
28 ),
29 not_send: PhantomData,
30 }
31 }
32
33 /// Run the executor.
34 ///
35 /// The `init` closure is called with a [`Spawner`] that spawns tasks on
36 /// this executor. Use it to spawn the initial task(s). After `init` returns,
37 /// the executor starts running the tasks.
38 ///
39 /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`),
40 /// for example by passing it as an argument to the initial tasks.
41 ///
42 /// This function requires `&'static mut self`. This means you have to store the
43 /// Executor instance in a place where it'll live forever and grants you mutable
44 /// access. There's a few ways to do this:
45 ///
46 /// - a [Forever](crate::util::Forever) (safe)
47 /// - a `static mut` (unsafe)
48 /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe)
49 ///
50 /// This function never returns.
51 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
52 init(self.inner.spawner());
53
54 loop {
55 unsafe {
56 self.inner.poll();
57 // we do not care about race conditions between the load and store operations, interrupts
58 //will only set this value to true.
59 critical_section::with(|_| {
60 // if there is work to do, loop back to polling
61 // TODO can we relax this?
62 if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) {
63 SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst);
64 }
65 // if not, wait for interrupt
66 else {
67 core::arch::asm!("wfi");
68 }
69 });
70 // if an interrupt occurred while waiting, it will be serviced here
71 }
72 }
73 }
74}
diff --git a/embassy/src/executor/mod.rs b/embassy/src/executor/mod.rs
index 5e5c18c0a..ca8488a93 100644
--- a/embassy/src/executor/mod.rs
+++ b/embassy/src/executor/mod.rs
@@ -18,6 +18,11 @@ cfg_if::cfg_if! {
18 mod arch; 18 mod arch;
19 pub use arch::*; 19 pub use arch::*;
20 } 20 }
21 else if #[cfg(target_arch="riscv32")] {
22 #[path="arch/riscv32.rs"]
23 mod arch;
24 pub use arch::*;
25 }
21 else if #[cfg(feature="wasm")] { 26 else if #[cfg(feature="wasm")] {
22 #[path="arch/wasm.rs"] 27 #[path="arch/wasm.rs"]
23 mod arch; 28 mod arch;
diff --git a/embassy/src/time/mod.rs b/embassy/src/time/mod.rs
index ac84b8f8d..018e01c84 100644
--- a/embassy/src/time/mod.rs
+++ b/embassy/src/time/mod.rs
@@ -68,6 +68,9 @@ const TPS: u64 = 32_768;
68#[cfg(feature = "time-tick-1mhz")] 68#[cfg(feature = "time-tick-1mhz")]
69const TPS: u64 = 1_000_000; 69const TPS: u64 = 1_000_000;
70 70
71#[cfg(feature = "time-tick-16mhz")]
72const TPS: u64 = 16_000_000;
73
71/// Ticks per second of the global timebase. 74/// Ticks per second of the global timebase.
72/// 75///
73/// This value is specified by the `time-tick-*` Cargo features, which 76/// This value is specified by the `time-tick-*` Cargo features, which