future-proof-iot / RIOT-rs

RIOT-rs is an operating system for secure, memory-safe, low-power Internet of Things, written in Rust
Apache License 2.0
32 stars 12 forks source link

`examples/embassy` doesn't work on the rpi-pico #351

Open elenaf9 opened 1 week ago

elenaf9 commented 1 week ago

Summary

I just tried running the embassy example and it didn't work as expected. Specifically, awaiting the timer never returned. The example seems quite old, is it outdated? Or any other idea why it stopped working?

Relevant log output

riot_rs_rt::startup()
rpi-pico::init()
riot-rs-embassy::init(): using interrupt mode executor
riot-rs-embassy::init_task()
riot-rs-embassy::init_task() done
Hello from main()! Running on a rpi-pico board.
async_task() signalling
before timer()
now=0ms threadtest() val=0

Hardware/ Setup

Possible Solution

This might be an issue around timers in embassy_rp; I only tested this example in the first place because I ran into some timer-related issues when running a benchmark for my WIP multicore implementation.

Would you like to work on fixing this bug?

Maybe

ROMemories commented 1 week ago

I just tried the same commit on an nRF52840, and it does seem to be working there:

riot_rs_rt::startup()
nrf52840dk::init()
nrf52::init()
riot-rs-embassy::init(): using interrupt mode executor
riot-rs-embassy::init_task()
riot-rs-embassy::init_task() done
Hello from main()! Running on a nrf52840dk board.
async_task() signalling
now=0ms threadtest() val=0
async_task()
async_task() signalling
now=199ms threadtest() val=2
async_task()
async_task() signalling
now=399ms threadtest() val=4
async_task()
async_task() signalling
now=599ms threadtest() val=6
async_task()
async_task() signalling
now=799ms threadtest() val=8
async_task()
async_task() signalling
now=999ms threadtest() val=10
async_task()
async_task() signalling
now=1199ms threadtest() val=12
async_task()
async_task() signalling
now=1399ms threadtest() val=14
async_task()
async_task() signalling
now=1599ms threadtest() val=16
async_task()
async_task() signalling
now=1799ms threadtest() val=18

However, I can reproduce your output on an Raspberry Pi Pico W (except the before timer(), which I assume you added for debugging), so I agree it seems architecture-dependent.

kaspar030 commented 1 week ago

However, I can reproduce your output on an Raspberry Pi Pico W

Same!

elenaf9 commented 1 week ago

Hmm, but generally the timers work for the RP2040, at least with the executor-thread. The below code works:

#![no_main]
#![no_std]
#![feature(type_alias_impl_trait)]
#![feature(used_with_arg)]

use embassy_time::{Duration, Timer, TICK_HZ};
use riot_rs::{
    debug::println, embassy::thread_executor::Executor, static_cell::make_static,
    thread::ThreadId,
};

// Task started in thread0
#[riot_rs::task(pool_size=1)]
async fn task0() {
    println!("task0");
    Timer::after(Duration::from_ticks(TICK_HZ / 10)).await;
    println!("task0 done");
}

#[riot_rs::thread(autostart)]
fn thread0() {
    println!("thread0 {:?}", riot_rs::thread::current_pid().unwrap());
    let executor = make_static!(Executor::new());
    executor.run(|spawner| {
        spawner.must_spawn(task0());
    });
}

// Autostarted task.
#[riot_rs::task(autostart)]
async fn task1() {
    println!("task1");
    Timer::after(Duration::from_secs(1)).await;
    println!("task1 done");
}

Maybe the issue is related to the InterruptExecutor that is used in the above example?