arch:riscv32
- Add basic riscv32 executor - Add 16MHZ timer support
This commit is contained in:
		| @@ -47,6 +47,7 @@ time = [] | ||||
| time-tick-32768hz = ["time"] | ||||
| time-tick-1000hz = ["time"] | ||||
| time-tick-1mhz = ["time"] | ||||
| time-tick-16mhz = ["time"] | ||||
|  | ||||
| executor-agnostic = [] | ||||
|  | ||||
|   | ||||
							
								
								
									
										74
									
								
								embassy/src/executor/arch/riscv32.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								embassy/src/executor/arch/riscv32.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| use core::marker::PhantomData; | ||||
| use core::ptr; | ||||
|  | ||||
| use atomic_polyfill::{AtomicBool, Ordering}; | ||||
|  | ||||
| use super::{raw, Spawner}; | ||||
|  | ||||
| /// global atomic used to keep track of whether there is work to do since sev() is not available on RISCV | ||||
| /// | ||||
| static SIGNAL_WORK_THREAD_MODE: AtomicBool = AtomicBool::new(false); | ||||
|  | ||||
| /// RISCV32 Executor | ||||
| pub struct Executor { | ||||
|     inner: raw::Executor, | ||||
|     not_send: PhantomData<*mut ()>, | ||||
| } | ||||
|  | ||||
| impl Executor { | ||||
|     /// Create a new Executor. | ||||
|     pub fn new() -> Self { | ||||
|         Self { | ||||
|             // use Signal_Work_Thread_Mode as substitute for local interrupt register | ||||
|             inner: raw::Executor::new( | ||||
|                 |_| { | ||||
|                     SIGNAL_WORK_THREAD_MODE.store(true, Ordering::SeqCst); | ||||
|                 }, | ||||
|                 ptr::null_mut(), | ||||
|             ), | ||||
|             not_send: PhantomData, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Run the executor. | ||||
|     /// | ||||
|     /// The `init` closure is called with a [`Spawner`] that spawns tasks on | ||||
|     /// this executor. Use it to spawn the initial task(s). After `init` returns, | ||||
|     /// the executor starts running the tasks. | ||||
|     /// | ||||
|     /// To spawn more tasks later, you may keep copies of the [`Spawner`] (it is `Copy`), | ||||
|     /// for example by passing it as an argument to the initial tasks. | ||||
|     /// | ||||
|     /// This function requires `&'static mut self`. This means you have to store the | ||||
|     /// Executor instance in a place where it'll live forever and grants you mutable | ||||
|     /// access. There's a few ways to do this: | ||||
|     /// | ||||
|     /// - a [Forever](crate::util::Forever) (safe) | ||||
|     /// - a `static mut` (unsafe) | ||||
|     /// - a local variable in a function you know never returns (like `fn main() -> !`), upgrading its lifetime with `transmute`. (unsafe) | ||||
|     /// | ||||
|     /// This function never returns. | ||||
|     pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { | ||||
|         init(self.inner.spawner()); | ||||
|  | ||||
|         loop { | ||||
|             unsafe { | ||||
|                 self.inner.poll(); | ||||
|                 // we do not care about race conditions between the load and store operations, interrupts | ||||
|                 //will only set this value to true. | ||||
|                 critical_section::with(|_| { | ||||
|                     // if there is work to do, loop back to polling | ||||
|                     // TODO can we relax this? | ||||
|                     if SIGNAL_WORK_THREAD_MODE.load(Ordering::SeqCst) { | ||||
|                         SIGNAL_WORK_THREAD_MODE.store(false, Ordering::SeqCst); | ||||
|                     } | ||||
|                     // if not, wait for interrupt | ||||
|                     else { | ||||
|                         core::arch::asm!("wfi"); | ||||
|                     } | ||||
|                 }); | ||||
|                 // if an interrupt occurred while waiting, it will be serviced here | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -18,6 +18,11 @@ cfg_if::cfg_if! { | ||||
|         mod arch; | ||||
|         pub use arch::*; | ||||
|     } | ||||
|     else if #[cfg(target_arch="riscv32")] { | ||||
|         #[path="arch/riscv32.rs"] | ||||
|         mod arch; | ||||
|         pub use arch::*; | ||||
|     } | ||||
|     else if #[cfg(feature="wasm")] { | ||||
|         #[path="arch/wasm.rs"] | ||||
|         mod arch; | ||||
|   | ||||
| @@ -68,6 +68,9 @@ const TPS: u64 = 32_768; | ||||
| #[cfg(feature = "time-tick-1mhz")] | ||||
| const TPS: u64 = 1_000_000; | ||||
|  | ||||
| #[cfg(feature = "time-tick-16mhz")] | ||||
| const TPS: u64 = 16_000_000; | ||||
|  | ||||
| /// Ticks per second of the global timebase. | ||||
| /// | ||||
| /// This value is specified by the `time-tick-*` Cargo features, which | ||||
|   | ||||
		Reference in New Issue
	
	Block a user