aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--macros/src/codegen/software_tasks.rs4
-rw-r--r--src/async_util.rs74
2 files changed, 78 insertions, 0 deletions
diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs
index 833e338d..f055428c 100644
--- a/macros/src/codegen/software_tasks.rs
+++ b/macros/src/codegen/software_tasks.rs
@@ -117,6 +117,10 @@ pub fn codegen(
));
}
+ if &task.is_async {
+ eprintln!("")
+ }
+
root.push(module::codegen(
Context::SoftwareTask(name),
needs_lt,
diff --git a/src/async_util.rs b/src/async_util.rs
new file mode 100644
index 00000000..bd8882d8
--- /dev/null
+++ b/src/async_util.rs
@@ -0,0 +1,74 @@
+//! Async support for RTIC
+
+use core::{
+ future::Future,
+ mem,
+ pin::Pin,
+ task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+};
+
+//=============
+// Waker
+
+///
+pub static WAKER_VTABLE: RawWakerVTable =
+ RawWakerVTable::new(waker_clone, waker_wake, waker_wake, waker_drop);
+
+unsafe fn waker_clone(p: *const ()) -> RawWaker {
+ RawWaker::new(p, &WAKER_VTABLE)
+}
+
+unsafe fn waker_wake(p: *const ()) {
+ let f: fn() = mem::transmute(p);
+ f();
+}
+
+unsafe fn waker_drop(_: *const ()) {
+ // nop
+}
+
+//============
+// Task
+
+///
+pub enum Task<F: Future + 'static> {
+ ///
+ Idle,
+
+ ///
+ Running(F),
+
+ ///
+ Done(F::Output),
+}
+
+impl<F: Future + 'static> Task<F> {
+ ///
+ pub const fn new() -> Self {
+ Self::Idle
+ }
+
+ ///
+ pub fn spawn(&mut self, future: impl FnOnce() -> F) {
+ *self = Task::Running(future());
+ }
+
+ ///
+ pub unsafe fn poll(&mut self, wake: fn()) {
+ match self {
+ Task::Idle => {}
+ Task::Running(future) => {
+ let future = Pin::new_unchecked(future);
+ let waker_data: *const () = mem::transmute(wake);
+ let waker = Waker::from_raw(RawWaker::new(waker_data, &WAKER_VTABLE));
+ let mut cx = Context::from_waker(&waker);
+
+ match future.poll(&mut cx) {
+ Poll::Ready(r) => *self = Task::Done(r),
+ Poll::Pending => {}
+ };
+ }
+ Task::Done(_) => {}
+ }
+ }
+}