embassy_executor_riot/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//! An asynchronous executor for RIOT OS, based on [embassy](https://embassy.dev/).
//!
//! See the [rust-async](https://github.com/RIOT-OS/RIOT/tree/master/examples/rust-async) example
//! for how to use it.
#![no_std]
use core::mem::MaybeUninit;

/// An embassy_executor implementation for RIOT OS
pub struct Executor {
    thread: MaybeUninit<riot_wrappers::thread::KernelPID>,
    flag: usize,
    raw_executor: MaybeUninit<embassy_executor::raw::Executor>,
}

impl Executor {
    pub fn new() -> Self {
        Self {
            thread: MaybeUninit::uninit(),
            flag: 0,
            raw_executor: MaybeUninit::uninit(),
        }
    }

    pub fn run(&'static mut self, init: impl FnOnce(embassy_executor::Spawner)) -> ! {
        self.thread.write(riot_wrappers::thread::get_pid());

        let selfptr = self as *mut _ as *mut ();
        let flag_bitset = 1 << self.flag;

        let exec: &'static _ = self
            .raw_executor
            .write(embassy_executor::raw::Executor::new(selfptr));
        let spawner = embassy_executor::raw::Executor::spawner(&exec);

        init(spawner);

        loop {
            unsafe { riot_sys::thread_flags_wait_any(flag_bitset) };
            unsafe { embassy_executor::raw::Executor::poll(&exec) };
        }
    }
}

#[export_name = "__pender"]
fn pender(context: *mut ()) {
    let context = context as *mut Executor;
    let context = unsafe { &mut *context };
    let thread = unsafe { riot_sys::thread_get(context.thread.assume_init().into()) };
    unsafe { riot_sys::thread_flags_set(thread as _, 1 << context.flag) };
}