mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
examples: Add asynchronous Rust example
This commit is contained in:
parent
b802a19059
commit
7a348aebde
BIN
examples/rust-async/Cargo.lock
generated
Normal file
BIN
examples/rust-async/Cargo.lock
generated
Normal file
Binary file not shown.
28
examples/rust-async/Cargo.toml
Normal file
28
examples/rust-async/Cargo.toml
Normal file
@ -0,0 +1,28 @@
|
||||
[package]
|
||||
name = "rust-async"
|
||||
version = "0.1.0"
|
||||
authors = ["Christian Amsüss <chrysn@fsfe.org>"]
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[profile.release]
|
||||
# Setting the panic mode has little effect on the built code (as Rust on RIOT
|
||||
# supports no unwinding), but setting it allows builds on native without using
|
||||
# the nightly-only lang_items feature.
|
||||
panic = "abort"
|
||||
|
||||
[dependencies]
|
||||
riot-wrappers = { version = "0.9", features = [ "set_panic_handler", "provide_critical_section_1_0", "panic_handler_format" ] }
|
||||
|
||||
embassy-executor-riot = { git = "https://gitlab.com/etonomy/riot-module-examples" }
|
||||
embassy-executor = "0.5"
|
||||
embassy-futures = "0.1.1"
|
||||
static_cell = "2.0.0"
|
||||
|
||||
# While currently this example does not use any RIOT modules implemented in
|
||||
# Rust, that may change; it is best practice for any RIOT application that has
|
||||
# its own top-level Rust crate to include rust_riotmodules from inside
|
||||
# RIOTBASE.
|
||||
rust_riotmodules = { path = "../../sys/rust_riotmodules/" }
|
30
examples/rust-async/Makefile
Normal file
30
examples/rust-async/Makefile
Normal file
@ -0,0 +1,30 @@
|
||||
# name of your application
|
||||
APPLICATION = rust-async
|
||||
|
||||
# If no BOARD is found in the environment, use this default:
|
||||
BOARD ?= native
|
||||
|
||||
# This has to be the absolute path to the RIOT base directory:
|
||||
RIOTBASE ?= $(CURDIR)/../..
|
||||
|
||||
# Some timers for the example
|
||||
USEMODULE += ztimer_msec
|
||||
|
||||
# Required by the async executor
|
||||
USEMODULE += core_thread_flags
|
||||
|
||||
# Comment this out to disable code in RIOT that does safety checking
|
||||
# which is not needed in a production environment but helps in the
|
||||
# development process:
|
||||
DEVELHELP ?= 1
|
||||
|
||||
# Change this to 0 show compiler invocation lines by default:
|
||||
QUIET ?= 1
|
||||
|
||||
# The name of crate (as per Cargo.toml package name, but with '-' replaced with '_')
|
||||
APPLICATION_RUST_MODULE = rust_async
|
||||
BASELIBS += $(APPLICATION_RUST_MODULE).module
|
||||
|
||||
FEATURES_REQUIRED += rust_target
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
21
examples/rust-async/README.md
Normal file
21
examples/rust-async/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
Rust: Asynchronous programming
|
||||
==============================
|
||||
|
||||
This is an example of how asynchronous Rust applications can be written on RIOT OS.
|
||||
|
||||
The application starts an [embassy] based executor,
|
||||
and then spawn several tasks on the main thread.
|
||||
Unlike RIOT OS threads, these tasks can not preempt each other;
|
||||
they relinquish control of the main thread when performing an asynchronous operation that would block,
|
||||
and are paused by anything that preempts the main thread.
|
||||
|
||||
Behind the scenes, the Rust compiler turns the asynchronous methods into state machines,
|
||||
and the executor polls the state machines to make progress whenever an event wakes them up.
|
||||
|
||||
Upsides of this style of programming are that there is less need for synchronization
|
||||
(for individual tasks or their parts can rely on the work they do synchronously not to be executed concurrently with other tasks if so configured),
|
||||
and that they can share a single stack space.
|
||||
State that is persisted across await points is not stored on the stack,
|
||||
but in adequately sized static memory for each task that can run.
|
||||
|
||||
[embassy]: https://embassy.dev/
|
53
examples/rust-async/src/lib.rs
Normal file
53
examples/rust-async/src/lib.rs
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2020 Christian Amsüss
|
||||
//
|
||||
// This file is subject to the terms and conditions of the GNU Lesser
|
||||
// General Public License v2.1. See the file LICENSE in the top level
|
||||
// directory for more details.
|
||||
#![no_std]
|
||||
|
||||
use riot_wrappers::riot_main;
|
||||
use riot_wrappers::println;
|
||||
use riot_wrappers::ztimer::{Clock, Ticks};
|
||||
|
||||
use static_cell::StaticCell;
|
||||
|
||||
extern crate rust_riotmodules;
|
||||
|
||||
riot_main!(main);
|
||||
|
||||
fn main() {
|
||||
// Create an executor for running async functions
|
||||
static EXECUTOR: StaticCell<embassy_executor_riot::Executor> = StaticCell::new();
|
||||
let executor: &'static mut _ = EXECUTOR.init(embassy_executor_riot::Executor::new());
|
||||
executor.run(|spawner| {
|
||||
spawner.spawn(amain(spawner)).expect("Starting task for the first time");
|
||||
})
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn amain(spawner: embassy_executor::Spawner) {
|
||||
println!("Running asynchronously:");
|
||||
|
||||
spawner.spawn(fast_messages("A")).expect("Starting task for the first time");
|
||||
spawner.spawn(fast_messages("B")).expect("Task is configured to allow two instances");
|
||||
|
||||
let msec = Clock::msec();
|
||||
|
||||
msec.sleep_async(Ticks(2500)).await;
|
||||
|
||||
println!("Slept 2.5 seconds in 'amain' task, that should be enough.");
|
||||
}
|
||||
|
||||
#[embassy_executor::task(pool_size = 2)]
|
||||
async fn fast_messages(taskname: &'static str) {
|
||||
println!("Task {taskname} is running:");
|
||||
|
||||
let msec = Clock::msec();
|
||||
|
||||
msec.sleep_async(Ticks(1000)).await;
|
||||
println!("Task {taskname} ticked");
|
||||
msec.sleep_async(Ticks(1000)).await;
|
||||
println!("Task {taskname} tocked");
|
||||
msec.sleep_async(Ticks(1000)).await;
|
||||
println!("Task {taskname} is done.");
|
||||
}
|
Loading…
Reference in New Issue
Block a user