mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-16 21:05:35 +01:00
RISC-V support over CLINT (#815)
* Rebase to master * using interrupt_mod * bug fixes * fix other backends * Add changelog * forgot about rtic-macros * backend-specific configuration * core peripherals optional over macro argument * pre_init_preprocessing binding * CI for RISC-V (WIP) * separation of concerns * add targets for RISC-V examples * remove qemu feature * prepare examples folder * move examples all together * move ci out of examples * minor changes * add cortex-m * new xtask: proof of concept * fix build.yml * feature typo * clean rtic examples * reproduce weird issue * remove unsafe code in user app * update dependencies * allow builds on riscv32imc * let's fix QEMU * Update .github/workflows/build.yml Co-authored-by: Henrik Tjäder <henrik@tjaders.com> * New build.rs * removing test features * adapt ui test to new version of clippy * add more examples to RISC-V backend * proper configuration of heapless for riscv32imc * opt-out examples for riscv32imc * point to new version of riscv-slic * adapt new macro bindings * adapt examples and CI to stable * fix cortex-m CI * Review --------- Co-authored-by: Henrik Tjäder <henrik@tjaders.com>
This commit is contained in:
parent
22ac33a826
commit
4060c3def8
166 changed files with 2322 additions and 315 deletions
11
examples/hifive1/.cargo/config.toml
Normal file
11
examples/hifive1/.cargo/config.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[target.'cfg(all(target_arch = "riscv32", target_os = "none"))']
|
||||
runner = "qemu-system-riscv32 -machine sifive_e,revb=true -nographic -semihosting-config enable=on,target=native -kernel"
|
||||
# runner = "riscv64-unknown-elf-gdb -q -x gdb_init"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Thifive1-link.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
# Pick ONE of these compilation targets
|
||||
# target = "riscv32imc-unknown-none-elf" # non-atomic support
|
||||
target = "riscv32imac-unknown-none-elf" # atomic support (partial)
|
||||
364
examples/hifive1/Cargo.lock
generated
Normal file
364
examples/hifive1/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
||||
|
||||
[[package]]
|
||||
name = "e310x"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/greenlsi/e310x.git?branch=master#50536cc5be2fd6adf7f879f002fdd98f66fb05f9"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"riscv-pac",
|
||||
"riscv-peripheral",
|
||||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "e310x"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/greenlsi/e310x.git#50536cc5be2fd6adf7f879f002fdd98f66fb05f9"
|
||||
dependencies = [
|
||||
"riscv-pac",
|
||||
"riscv-peripheral",
|
||||
"vcell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "e310x-hal"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/greenlsi/e310x-hal.git?branch=master#931aea7ab142c1eb9eaadd4150946d8452229f27"
|
||||
dependencies = [
|
||||
"e310x 0.11.0 (git+https://github.com/greenlsi/e310x.git?branch=master)",
|
||||
"embedded-hal 0.2.7",
|
||||
"nb 1.1.0",
|
||||
"portable-atomic",
|
||||
"riscv",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
|
||||
dependencies = [
|
||||
"nb 0.1.3",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hifive1"
|
||||
version = "0.11.0"
|
||||
source = "git+https://github.com/romancardenas/hifive1.git#ef8cea8b90bddb04509785d3e148ff145137520a"
|
||||
dependencies = [
|
||||
"e310x-hal",
|
||||
"embedded-hal 0.2.7",
|
||||
"nb 1.1.0",
|
||||
"riscv",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||
dependencies = [
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-pac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18ceb4af23fdad434f938afdc35ce895a63d84f7333bb127d8065030848eb6a6"
|
||||
|
||||
[[package]]
|
||||
name = "riscv-peripheral"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07c799fe4e144bd4dd0c68fa33a41c1485f19730eea505d195124636e1253358"
|
||||
dependencies = [
|
||||
"embedded-hal 1.0.0",
|
||||
"riscv",
|
||||
"riscv-pac",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-rt"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0d35e32cf1383183e8885d8a9aa4402a087fd094dc34c2cb6df6687d0229dfe"
|
||||
dependencies = [
|
||||
"riscv",
|
||||
"riscv-rt-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-rt-macros"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8d100d466dbb76681ef6a9386f3da9abc570d57394e86da0ba5af8c4408486d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-slic"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/romancardenas/riscv-slic.git?rev=2a91edb#2a91edbff50bcc73169549923d278ff953d0986e"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"heapless",
|
||||
"riscv",
|
||||
"riscv-slic-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riscv-slic-macros"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/romancardenas/riscv-slic.git?rev=2a91edb#2a91edbff50bcc73169549923d278ff953d0986e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic"
|
||||
version = "2.1.0"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"bare-metal",
|
||||
"critical-section",
|
||||
"riscv",
|
||||
"riscv-slic",
|
||||
"rtic-core",
|
||||
"rtic-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic-core"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42"
|
||||
|
||||
[[package]]
|
||||
name = "rtic-macros"
|
||||
version = "2.1.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic_hifive1"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"e310x 0.11.0 (git+https://github.com/greenlsi/e310x.git)",
|
||||
"heapless",
|
||||
"hifive1",
|
||||
"riscv",
|
||||
"riscv-rt",
|
||||
"rtic",
|
||||
"semihosting",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semihosting"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab7a0be8d9e9893dfb5ce313aa0324396936d8bf788f5ef493c9f122ad84fd8"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "vcell"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
22
examples/hifive1/Cargo.toml
Normal file
22
examples/hifive1/Cargo.toml
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
[package]
|
||||
name = "rtic_hifive1"
|
||||
categories = ["embedded", "no-std"]
|
||||
description = "Examples of RTIC apps for the HiFive1 board"
|
||||
license = "MIT OR Apache-2.0"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
rtic = { path = "../../rtic" }
|
||||
heapless = "0.8.0"
|
||||
hifive1 = { git = "https://github.com/romancardenas/hifive1.git", features = ["board-redv"] }
|
||||
e310x = { git = "https://github.com/greenlsi/e310x.git", features = ["rt"]}
|
||||
riscv-rt = {version = "0.12.1", features = ["single-hart"]}
|
||||
riscv = "0.11.0"
|
||||
semihosting = { version = "0.1", features = ["stdio", "panic-handler"] }
|
||||
|
||||
[features]
|
||||
riscv-clint-backend = ["rtic/riscv-clint-backend"]
|
||||
test-critical-section = []
|
||||
140
examples/hifive1/examples/prio_inheritance.rs
Normal file
140
examples/hifive1/examples/prio_inheritance.rs
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use riscv_rt as _;
|
||||
|
||||
#[rtic::app(device = e310x, backend = HART0)]
|
||||
mod app {
|
||||
use core::{future::Future, pin::Pin, task::Context, task::Poll};
|
||||
use hifive1::hal::prelude::*;
|
||||
use semihosting::{println, process::exit};
|
||||
|
||||
/// Dummy asynchronous function to showcase SW tasks
|
||||
pub async fn yield_now(task: &str) {
|
||||
/// Yield implementation
|
||||
struct YieldNow {
|
||||
yielded: bool,
|
||||
}
|
||||
println!(" [{}]: Yield", task);
|
||||
|
||||
impl Future for YieldNow {
|
||||
type Output = ();
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
|
||||
if self.yielded {
|
||||
return Poll::Ready(());
|
||||
}
|
||||
|
||||
self.yielded = true;
|
||||
cx.waker().wake_by_ref();
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
YieldNow { yielded: false }.await
|
||||
}
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
counter: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
// Pends the SoftLow interrupt but its handler won't run until *after*
|
||||
// `init` returns because interrupts are disabled
|
||||
let resources = unsafe { hifive1::hal::DeviceResources::steal() };
|
||||
let peripherals = resources.peripherals;
|
||||
|
||||
let clocks =
|
||||
hifive1::configure_clocks(peripherals.PRCI, peripherals.AONCLK, 64.mhz().into());
|
||||
let gpio = resources.pins;
|
||||
|
||||
// Configure UART for stdout
|
||||
hifive1::stdout::configure(
|
||||
peripherals.UART0,
|
||||
hifive1::pin!(gpio, uart0_tx),
|
||||
hifive1::pin!(gpio, uart0_rx),
|
||||
115_200.bps(),
|
||||
clocks,
|
||||
);
|
||||
|
||||
(Shared { counter: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[idle(shared = [counter])]
|
||||
fn idle(mut cx: idle::Context) -> ! {
|
||||
println!("[Idle]: Started");
|
||||
// pend the medium priority SW task only once
|
||||
soft_medium::spawn().unwrap();
|
||||
cx.shared.counter.lock(|counter| {
|
||||
println!("[Idle]: Shared: {}", *counter);
|
||||
});
|
||||
// exit QEMU simulator
|
||||
println!("[Idle]: Finished");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/// Medium priority SW task. It is triggered by the idle and spawns the rest of the SW tasks
|
||||
#[task(shared = [counter], priority = 2)]
|
||||
async fn soft_medium(mut cx: soft_medium::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
println!(" [SoftMedium]: Started");
|
||||
cx.shared.counter.lock(|counter| {
|
||||
// Spawn the other SW tasks INSIDE the critical section (just for showing priority inheritance)
|
||||
soft_low_1::spawn().unwrap();
|
||||
soft_high::spawn().unwrap();
|
||||
soft_low_2::spawn().unwrap();
|
||||
|
||||
*counter += 1;
|
||||
println!(" [SoftMedium]: Shared: {}", *counter);
|
||||
});
|
||||
println!(" [SoftMedium]: Finished");
|
||||
}
|
||||
|
||||
/// Low priority SW task. It runs cooperatively with soft_low_2
|
||||
#[task(shared = [counter], priority = 1)]
|
||||
async fn soft_low_1(mut cx: soft_low_1::Context) {
|
||||
println!(" [SoftLow1]: Started");
|
||||
cx.shared.counter.lock(|counter| {
|
||||
*counter += 1;
|
||||
println!(" [SoftLow1]: Shared: {}", *counter);
|
||||
});
|
||||
// Yield to the other SW task
|
||||
yield_now("SoftLow1").await;
|
||||
|
||||
println!(" [SoftLow1]: Finished");
|
||||
}
|
||||
|
||||
/// Low priority SW task. It runs cooperatively with soft_low_2
|
||||
#[task(shared = [counter], priority = 1)]
|
||||
async fn soft_low_2(mut cx: soft_low_2::Context) {
|
||||
println!(" [SoftLow2]: Started");
|
||||
cx.shared.counter.lock(|counter| {
|
||||
*counter += 1;
|
||||
println!(" [SoftLow2]: Shared: {}", *counter);
|
||||
});
|
||||
|
||||
// Yield to the other SW task
|
||||
yield_now("SoftLow2").await;
|
||||
|
||||
println!(" [SoftLow2]: Finished");
|
||||
}
|
||||
|
||||
/// High priority SW task
|
||||
#[task(shared = [counter], priority = 3)]
|
||||
async fn soft_high(mut cx: soft_high::Context) {
|
||||
println!(" [SoftHigh]: Started");
|
||||
|
||||
cx.shared.counter.lock(|counter| {
|
||||
*counter += 1;
|
||||
println!(" [SoftHigh]: Shared: {}", counter);
|
||||
});
|
||||
|
||||
println!(" [SoftHigh]: Finished");
|
||||
}
|
||||
}
|
||||
60
examples/hifive1/examples/static.rs
Normal file
60
examples/hifive1/examples/static.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
//! zero priority task
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use hifive1 as _;
|
||||
use riscv_rt as _;
|
||||
|
||||
#[rtic::app(device = e310x, backend = HART0)]
|
||||
mod app {
|
||||
use semihosting::{process::exit, println};
|
||||
use heapless::spsc::{Consumer, Producer, Queue};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
p: Producer<'static, u32, 5>,
|
||||
c: Consumer<'static, u32, 5>,
|
||||
}
|
||||
|
||||
#[init(local = [q: Queue<u32, 5> = Queue::new()])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// q has 'static life-time so after the split and return of `init`
|
||||
// it will continue to exist and be allocated
|
||||
let (p, c) = cx.local.q.split();
|
||||
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local { p, c })
|
||||
}
|
||||
|
||||
#[idle(local = [c])]
|
||||
fn idle(c: idle::Context) -> ! {
|
||||
loop {
|
||||
// Lock-free access to the same underlying queue!
|
||||
if let Some(data) = c.local.c.dequeue() {
|
||||
println!("received message: {}", data);
|
||||
|
||||
// Run foo until data
|
||||
if data == 3 {
|
||||
exit(0); // Exit QEMU simulator
|
||||
} else {
|
||||
foo::spawn().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[task(local = [p, state: u32 = 0], priority = 1)]
|
||||
async fn foo(c: foo::Context) {
|
||||
*c.local.state += 1;
|
||||
|
||||
// Lock-free access to the same underlying queue!
|
||||
c.local.p.enqueue(*c.local.state).unwrap();
|
||||
}
|
||||
}
|
||||
57
examples/hifive1/examples/task.rs
Normal file
57
examples/hifive1/examples/task.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//! zero priority task
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use hifive1 as _;
|
||||
use riscv_rt as _;
|
||||
|
||||
#[rtic::app(device = e310x, backend = HART0)]
|
||||
mod app {
|
||||
use semihosting::{println, process::exit};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
println!("foo - start");
|
||||
|
||||
// spawns `bar` onto the task scheduler
|
||||
// `foo` and `bar` have the same priority so `bar` will not run until
|
||||
// after `foo` terminates
|
||||
bar::spawn().unwrap();
|
||||
|
||||
println!("foo - middle");
|
||||
|
||||
// spawns `baz` onto the task scheduler
|
||||
// `baz` has higher priority than `foo` so it immediately preempts `foo`
|
||||
baz::spawn().unwrap();
|
||||
|
||||
println!("foo - end");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn bar(_: bar::Context) {
|
||||
println!("bar");
|
||||
|
||||
exit(0); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn baz(_: baz::Context) {
|
||||
println!("baz");
|
||||
}
|
||||
}
|
||||
61
examples/hifive1/examples/zero_prio_task.rs
Normal file
61
examples/hifive1/examples/zero_prio_task.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//! zero priority task
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use hifive1 as _;
|
||||
use riscv_rt as _;
|
||||
|
||||
/// Does not impl send
|
||||
pub struct NotSend {
|
||||
_0: PhantomData<*const ()>,
|
||||
}
|
||||
|
||||
#[rtic::app(device = e310x, backend = HART0)]
|
||||
mod app {
|
||||
use super::NotSend;
|
||||
use core::marker::PhantomData;
|
||||
use semihosting::{println, process::exit};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
x: NotSend,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
y: NotSend,
|
||||
}
|
||||
|
||||
#[init]
|
||||
fn init(_cx: init::Context) -> (Shared, Local) {
|
||||
println!("init");
|
||||
|
||||
async_task::spawn().unwrap();
|
||||
async_task2::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {
|
||||
x: NotSend { _0: PhantomData },
|
||||
},
|
||||
Local {
|
||||
y: NotSend { _0: PhantomData },
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[task(priority = 0, shared = [x], local = [y])]
|
||||
async fn async_task(_: async_task::Context) {
|
||||
println!("hello from async");
|
||||
}
|
||||
|
||||
#[task(priority = 0, shared = [x])]
|
||||
async fn async_task2(_: async_task2::Context) {
|
||||
println!("hello from async2");
|
||||
|
||||
exit(0); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
4
examples/hifive1/rust-toolchain.toml
Normal file
4
examples/hifive1/rust-toolchain.toml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "stable"
|
||||
components = [ "rust-src", "rustfmt" ]
|
||||
targets = [ "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf" ]
|
||||
13
examples/lm3s6965/.cargo/config.toml
Normal file
13
examples/lm3s6965/.cargo/config.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[target.thumbv6m-none-eabi]
|
||||
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
|
||||
|
||||
[target.thumbv7m-none-eabi]
|
||||
runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
|
||||
|
||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
527
examples/lm3s6965/Cargo.lock
generated
Normal file
527
examples/lm3s6965/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,527 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "atomic-polyfill"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3"
|
||||
dependencies = [
|
||||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bare-metal"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603"
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9"
|
||||
dependencies = [
|
||||
"bare-metal 0.2.5",
|
||||
"bitfield",
|
||||
"critical-section",
|
||||
"embedded-hal 0.2.7",
|
||||
"volatile-register",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee84e813d593101b1723e13ec38b6ab6abbdbaaa4546553f5395ed274079ddb1"
|
||||
dependencies = [
|
||||
"cortex-m-rt-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-rt-macros"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0f6f3e36f203cfedbc78b357fb28730aa2c6dc1ab060ee5c2405e843988d3c7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cortex-m-semihosting"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c23234600452033cc77e4b761e740e02d2c4168e11dbf36ab14a0f58973592b0"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "critical-section"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff"
|
||||
dependencies = [
|
||||
"nb 0.1.3",
|
||||
"void",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal-async"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884"
|
||||
dependencies = [
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal-bus"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57b4e6ede84339ebdb418cd986e6320a34b017cdf99b5cc3efceec6450b06886"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "fugit"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17186ad64927d5ac8f02c1e77ccefa08ccd9eaa314d5a4772278aa204a22f7e7"
|
||||
dependencies = [
|
||||
"gcd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-channel"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||
|
||||
[[package]]
|
||||
name = "futures-macro"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-sink"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||
|
||||
[[package]]
|
||||
name = "futures-task"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||
|
||||
[[package]]
|
||||
name = "futures-util"
|
||||
version = "0.3.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-macro",
|
||||
"futures-sink",
|
||||
"futures-task",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gcd"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a"
|
||||
|
||||
[[package]]
|
||||
name = "hash32"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
|
||||
|
||||
[[package]]
|
||||
name = "heapless"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||
dependencies = [
|
||||
"hash32",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lm3s6965"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13d7ed5360fee8fd434cf7995ef1d7ad42697abb538e34383a39da8df5495446"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f"
|
||||
dependencies = [
|
||||
"nb 1.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nb"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d"
|
||||
|
||||
[[package]]
|
||||
name = "panic-semihosting"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee8a3e1233d9073d76a870223512ce4eeea43c067a94a445c13bd6d792d7b1ab"
|
||||
dependencies = [
|
||||
"cortex-m",
|
||||
"cortex-m-semihosting",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic"
|
||||
version = "2.1.0"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"bare-metal 1.0.0",
|
||||
"cortex-m",
|
||||
"critical-section",
|
||||
"rtic-core",
|
||||
"rtic-macros",
|
||||
"rtic-monotonics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic-common"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic-core"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42"
|
||||
|
||||
[[package]]
|
||||
name = "rtic-macros"
|
||||
version = "2.1.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.49",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic-monotonics"
|
||||
version = "1.5.0"
|
||||
dependencies = [
|
||||
"atomic-polyfill",
|
||||
"cfg-if",
|
||||
"cortex-m",
|
||||
"embedded-hal 1.0.0",
|
||||
"fugit",
|
||||
"rtic-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic-sync"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
"embedded-hal-bus",
|
||||
"heapless",
|
||||
"portable-atomic",
|
||||
"rtic-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic-time"
|
||||
version = "1.3.0"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"futures-util",
|
||||
"rtic-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rtic_lm3s6965"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bare-metal 1.0.0",
|
||||
"cortex-m",
|
||||
"cortex-m-semihosting",
|
||||
"futures",
|
||||
"heapless",
|
||||
"lm3s6965",
|
||||
"panic-semihosting",
|
||||
"rtic",
|
||||
"rtic-monotonics",
|
||||
"rtic-sync",
|
||||
"rtic-time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
dependencies = [
|
||||
"semver-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.49"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "vcell"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "volatile-register"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc"
|
||||
dependencies = [
|
||||
"vcell",
|
||||
]
|
||||
36
examples/lm3s6965/Cargo.toml
Normal file
36
examples/lm3s6965/Cargo.toml
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
[package]
|
||||
name = "rtic_lm3s6965"
|
||||
categories = ["embedded", "no-std"]
|
||||
description = "Examples of RTIC apps for the lm3s6965 chip"
|
||||
license = "MIT OR Apache-2.0"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
heapless = "0.8"
|
||||
lm3s6965 = "0.2"
|
||||
cortex-m = "0.7.0"
|
||||
bare-metal = "1.0.0"
|
||||
cortex-m-semihosting = "0.5.0"
|
||||
rtic-time = { path = "../../rtic-time" }
|
||||
rtic-sync = { path = "../../rtic-sync" }
|
||||
rtic-monotonics = { path = "../../rtic-monotonics", features = ["cortex-m-systick"] }
|
||||
rtic = { path = "../../rtic" }
|
||||
|
||||
[dependencies.futures]
|
||||
version = "0.3.26"
|
||||
default-features = false
|
||||
features = ["async-await"]
|
||||
|
||||
[dependencies.panic-semihosting]
|
||||
features = ["exit"]
|
||||
version = "0.6.0"
|
||||
|
||||
[features]
|
||||
test-critical-section = ["rtic/test-critical-section"]
|
||||
thumbv6-backend = ["rtic/thumbv6-backend"]
|
||||
thumbv7-backend = ["rtic/thumbv7-backend"]
|
||||
thumbv8base-backend = ["rtic/thumbv8base-backend"]
|
||||
thumbv8main-backend = ["rtic/thumbv8main-backend"]
|
||||
65
examples/lm3s6965/examples/async-channel-done.rs
Normal file
65
examples/lm3s6965/examples/async-channel-done.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//! examples/async-channel-done.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use rtic_sync::{channel::*, make_channel};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
const CAPACITY: usize = 1;
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
let (s, r) = make_channel!(u32, CAPACITY);
|
||||
|
||||
receiver::spawn(r).unwrap();
|
||||
sender1::spawn(s.clone()).unwrap();
|
||||
sender2::spawn(s.clone()).unwrap();
|
||||
sender3::spawn(s).unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn receiver(_c: receiver::Context, mut receiver: Receiver<'static, u32, CAPACITY>) {
|
||||
while let Ok(val) = receiver.recv().await {
|
||||
hprintln!("Receiver got: {}", val);
|
||||
if val == 3 {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender1(_c: sender1::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 1 sending: 1");
|
||||
sender.send(1).await.unwrap();
|
||||
hprintln!("Sender 1 done");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender2(_c: sender2::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 2 sending: 2");
|
||||
sender.send(2).await.unwrap();
|
||||
hprintln!("Sender 2 done");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender3(_c: sender3::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 3 sending: 3");
|
||||
sender.send(3).await.unwrap();
|
||||
hprintln!("Sender 3 done");
|
||||
}
|
||||
}
|
||||
37
examples/lm3s6965/examples/async-channel-no-receiver.rs
Normal file
37
examples/lm3s6965/examples/async-channel-no-receiver.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
//! examples/async-channel-no-receiver.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use rtic_sync::{channel::*, make_channel};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
const CAPACITY: usize = 1;
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
let (s, _r) = make_channel!(u32, CAPACITY);
|
||||
|
||||
sender1::spawn(s.clone()).unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender1(_c: sender1::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 1 sending: 1 {:?}", sender.send(1).await);
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
38
examples/lm3s6965/examples/async-channel-no-sender.rs
Normal file
38
examples/lm3s6965/examples/async-channel-no-sender.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
//! examples/async-channel-no-sender.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use rtic_sync::{channel::*, make_channel};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
const CAPACITY: usize = 1;
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
let (_s, r) = make_channel!(u32, CAPACITY);
|
||||
|
||||
receiver::spawn(r).unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn receiver(_c: receiver::Context, mut receiver: Receiver<'static, u32, CAPACITY>) {
|
||||
hprintln!("Receiver got: {:?}", receiver.recv().await);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
56
examples/lm3s6965/examples/async-channel-try.rs
Normal file
56
examples/lm3s6965/examples/async-channel-try.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//! examples/async-channel-try.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use rtic_sync::{channel::*, make_channel};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
sender: Sender<'static, u32, CAPACITY>,
|
||||
}
|
||||
|
||||
const CAPACITY: usize = 1;
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
let (s, r) = make_channel!(u32, CAPACITY);
|
||||
|
||||
receiver::spawn(r).unwrap();
|
||||
sender1::spawn(s.clone()).unwrap();
|
||||
|
||||
(Shared {}, Local { sender: s.clone() })
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn receiver(_c: receiver::Context, mut receiver: Receiver<'static, u32, CAPACITY>) {
|
||||
while let Ok(val) = receiver.recv().await {
|
||||
hprintln!("Receiver got: {}", val);
|
||||
}
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender1(_c: sender1::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 1 sending: 1");
|
||||
sender.send(1).await.unwrap();
|
||||
hprintln!("Sender 1 try sending: 2 {:?}", sender.try_send(2));
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
// This interrupt is never triggered, but is used to demonstrate that
|
||||
// one can (try to) send data into a channel from a hardware task.
|
||||
#[task(binds = GPIOA, local = [sender])]
|
||||
fn hw_task(cx: hw_task::Context) {
|
||||
cx.local.sender.try_send(3).ok();
|
||||
}
|
||||
}
|
||||
62
examples/lm3s6965/examples/async-channel.rs
Normal file
62
examples/lm3s6965/examples/async-channel.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
//! examples/async-channel.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use rtic_sync::{channel::*, make_channel};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
const CAPACITY: usize = 5;
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
let (s, r) = make_channel!(u32, CAPACITY);
|
||||
|
||||
receiver::spawn(r).unwrap();
|
||||
sender1::spawn(s.clone()).unwrap();
|
||||
sender2::spawn(s.clone()).unwrap();
|
||||
sender3::spawn(s).unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn receiver(_c: receiver::Context, mut receiver: Receiver<'static, u32, CAPACITY>) {
|
||||
while let Ok(val) = receiver.recv().await {
|
||||
hprintln!("Receiver got: {}", val);
|
||||
if val == 3 {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender1(_c: sender1::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 1 sending: 1");
|
||||
sender.send(1).await.unwrap();
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender2(_c: sender2::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 2 sending: 2");
|
||||
sender.send(2).await.unwrap();
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn sender3(_c: sender3::Context, mut sender: Sender<'static, u32, CAPACITY>) {
|
||||
hprintln!("Sender 3 sending: 3");
|
||||
sender.send(3).await.unwrap();
|
||||
}
|
||||
}
|
||||
58
examples/lm3s6965/examples/async-delay.rs
Normal file
58
examples/lm3s6965/examples/async-delay.rs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
//! examples/async-delay.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use rtic_monotonics::systick::*;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
let systick_token = rtic_monotonics::create_systick_token!();
|
||||
Systick::start(cx.core.SYST, 12_000_000, systick_token);
|
||||
|
||||
foo::spawn().ok();
|
||||
bar::spawn().ok();
|
||||
baz::spawn().ok();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_cx: foo::Context) {
|
||||
hprintln!("hello from foo");
|
||||
Systick::delay(100.millis()).await;
|
||||
hprintln!("bye from foo");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn bar(_cx: bar::Context) {
|
||||
hprintln!("hello from bar");
|
||||
Systick::delay(200.millis()).await;
|
||||
hprintln!("bye from bar");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn baz(_cx: baz::Context) {
|
||||
hprintln!("hello from baz");
|
||||
Systick::delay(300.millis()).await;
|
||||
hprintln!("bye from baz");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
93
examples/lm3s6965/examples/async-task-multiple-prios.rs
Normal file
93
examples/lm3s6965/examples/async-task-multiple-prios.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//! examples/async-task-multiple-prios.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
// NOTES:
|
||||
//
|
||||
// - Async tasks cannot have `#[lock_free]` resources, as they can interleave and each async
|
||||
// task can have a mutable reference stored.
|
||||
// - Spawning an async task equates to it being polled once.
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
async_task1::spawn(1).ok();
|
||||
async_task2::spawn().ok();
|
||||
async_task3::spawn().ok();
|
||||
async_task4::spawn().ok();
|
||||
|
||||
(Shared { a: 0, b: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
hprintln!("idle");
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
#[task(priority = 1, shared = [a, b])]
|
||||
async fn async_task1(mut cx: async_task1::Context, inc: u32) {
|
||||
hprintln!(
|
||||
"hello from async 1 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += inc;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[task(priority = 1, shared = [a, b])]
|
||||
async fn async_task2(mut cx: async_task2::Context) {
|
||||
hprintln!(
|
||||
"hello from async 2 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += 1;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [a, b])]
|
||||
async fn async_task3(mut cx: async_task3::Context) {
|
||||
hprintln!(
|
||||
"hello from async 3 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += 1;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [a, b])]
|
||||
async fn async_task4(mut cx: async_task4::Context) {
|
||||
hprintln!(
|
||||
"hello from async 4 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += 1;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
71
examples/lm3s6965/examples/async-task.rs
Normal file
71
examples/lm3s6965/examples/async-task.rs
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
//! examples/async-task.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
// NOTES:
|
||||
//
|
||||
// - Async tasks cannot have `#[lock_free]` resources, as they can interleave and each async
|
||||
// task can have a mutable reference stored.
|
||||
// - Spawning an async task equates to it being polled once.
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
async_task::spawn().unwrap();
|
||||
async_task_args::spawn(1, 2).unwrap();
|
||||
async_task2::spawn().unwrap();
|
||||
|
||||
(Shared { a: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[idle(shared = [a])]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
hprintln!("idle");
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART1, shared = [a])]
|
||||
fn hw_task(cx: hw_task::Context) {
|
||||
let hw_task::SharedResources { a: _, .. } = cx.shared;
|
||||
hprintln!("hello from hw");
|
||||
}
|
||||
|
||||
#[task(shared = [a], priority = 1)]
|
||||
async fn async_task(cx: async_task::Context) {
|
||||
let async_task::SharedResources { a: _, .. } = cx.shared;
|
||||
hprintln!("hello from async");
|
||||
}
|
||||
|
||||
#[task(priority = 1)]
|
||||
async fn async_task_args(_cx: async_task_args::Context, a: u32, b: i32) {
|
||||
hprintln!("hello from async with args a: {}, b: {}", a, b);
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [a])]
|
||||
async fn async_task2(cx: async_task2::Context) {
|
||||
let async_task2::SharedResources { a: _, .. } = cx.shared;
|
||||
hprintln!("hello from async2");
|
||||
}
|
||||
}
|
||||
96
examples/lm3s6965/examples/async-timeout.rs
Normal file
96
examples/lm3s6965/examples/async-timeout.rs
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
//! examples/async-timeout.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use panic_semihosting as _;
|
||||
use rtic_monotonics::systick::*;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)]
|
||||
mod app {
|
||||
use super::*;
|
||||
use futures::{future::FutureExt, select_biased};
|
||||
use rtic_monotonics::Monotonic;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
// ANCHOR: init
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
let systick_token = rtic_monotonics::create_systick_token!();
|
||||
Systick::start(cx.core.SYST, 12_000_000, systick_token);
|
||||
// ANCHOR_END: init
|
||||
|
||||
foo::spawn().ok();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_cx: foo::Context) {
|
||||
// ANCHOR: select_biased
|
||||
// Call hal with short relative timeout using `select_biased`
|
||||
select_biased! {
|
||||
v = hal_get(1).fuse() => hprintln!("hal returned {}", v),
|
||||
_ = Systick::delay(200.millis()).fuse() => hprintln!("timeout", ), // this will finish first
|
||||
}
|
||||
|
||||
// Call hal with long relative timeout using `select_biased`
|
||||
select_biased! {
|
||||
v = hal_get(1).fuse() => hprintln!("hal returned {}", v), // hal finish first
|
||||
_ = Systick::delay(1000.millis()).fuse() => hprintln!("timeout", ),
|
||||
}
|
||||
// ANCHOR_END: select_biased
|
||||
|
||||
// ANCHOR: timeout_after_basic
|
||||
// Call hal with long relative timeout using monotonic `timeout_after`
|
||||
match Systick::timeout_after(1000.millis(), hal_get(1)).await {
|
||||
Ok(v) => hprintln!("hal returned {}", v),
|
||||
_ => hprintln!("timeout"),
|
||||
}
|
||||
// ANCHOR_END: timeout_after_basic
|
||||
|
||||
// ANCHOR: timeout_at_basic
|
||||
// get the current time instance
|
||||
let mut instant = Systick::now();
|
||||
|
||||
// do this 3 times
|
||||
for n in 0..3 {
|
||||
// absolute point in time without drift
|
||||
instant += 1000.millis();
|
||||
Systick::delay_until(instant).await;
|
||||
|
||||
// absolute point in time for timeout
|
||||
let timeout = instant + 500.millis();
|
||||
hprintln!("now is {:?}, timeout at {:?}", Systick::now(), timeout);
|
||||
|
||||
match Systick::timeout_at(timeout, hal_get(n)).await {
|
||||
Ok(v) => hprintln!("hal returned {} at time {:?}", v, Systick::now()),
|
||||
_ => hprintln!("timeout"),
|
||||
}
|
||||
}
|
||||
// ANCHOR_END: timeout_at_basic
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
// Emulate some hal
|
||||
async fn hal_get(n: u32) -> u32 {
|
||||
// emulate some delay time dependent on n
|
||||
let d = 350.millis() + n * 100.millis();
|
||||
hprintln!("the hal takes a duration of {:?}", d);
|
||||
Systick::delay(d).await;
|
||||
// emulate some return value
|
||||
5
|
||||
}
|
||||
80
examples/lm3s6965/examples/big-struct-opt.rs
Normal file
80
examples/lm3s6965/examples/big-struct-opt.rs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
//! examples/big-struct-opt.rs
|
||||
//!
|
||||
//! Example on how to initialize a large struct without needing to copy it via `LateResources`,
|
||||
//! effectively saving stack space needed for the copies.
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Some big struct
|
||||
pub struct BigStruct {
|
||||
/// Big content
|
||||
pub data: [u8; 2048],
|
||||
}
|
||||
|
||||
impl BigStruct {
|
||||
fn new() -> Self {
|
||||
BigStruct { data: [22; 2048] }
|
||||
}
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use super::BigStruct;
|
||||
use core::mem::MaybeUninit;
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
big_struct: &'static mut BigStruct,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [bs: MaybeUninit<BigStruct> = MaybeUninit::uninit()])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
let big_struct = unsafe {
|
||||
// write directly into the static storage
|
||||
cx.local.bs.as_mut_ptr().write(BigStruct::new());
|
||||
&mut *cx.local.bs.as_mut_ptr()
|
||||
};
|
||||
|
||||
rtic::pend(Interrupt::UART0);
|
||||
async_task::spawn().unwrap();
|
||||
(
|
||||
Shared {
|
||||
// assign the reference so we can use the resource
|
||||
big_struct,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
hprintln!("idle");
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, shared = [big_struct])]
|
||||
fn uart0(mut cx: uart0::Context) {
|
||||
cx.shared
|
||||
.big_struct
|
||||
.lock(|b| hprintln!("uart0 data:{:?}", &b.data[0..5]));
|
||||
}
|
||||
|
||||
#[task(shared = [big_struct], priority = 2)]
|
||||
async fn async_task(mut cx: async_task::Context) {
|
||||
cx.shared
|
||||
.big_struct
|
||||
.lock(|b| hprintln!("async_task data:{:?}", &b.data[0..5]));
|
||||
}
|
||||
}
|
||||
54
examples/lm3s6965/examples/binds.rs
Normal file
54
examples/lm3s6965/examples/binds.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
//! examples/binds.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
// `examples/interrupt.rs` rewritten to use `binds`
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
hprintln!("idle");
|
||||
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, local = [times: u32 = 0])]
|
||||
fn foo(cx: foo::Context) {
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"foo called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
}
|
||||
}
|
||||
86
examples/lm3s6965/examples/common.rs
Normal file
86
examples/lm3s6965/examples/common.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//! examples/common.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0, UART1])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
local_to_foo: i64,
|
||||
local_to_bar: i64,
|
||||
local_to_idle: i64,
|
||||
}
|
||||
|
||||
// `#[init]` cannot access locals from the `#[local]` struct as they are initialized here.
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {},
|
||||
// initial values for the `#[local]` resources
|
||||
Local {
|
||||
local_to_foo: 0,
|
||||
local_to_bar: 0,
|
||||
local_to_idle: 0,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// `local_to_idle` can only be accessed from this context
|
||||
#[idle(local = [local_to_idle])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
let local_to_idle = cx.local.local_to_idle;
|
||||
*local_to_idle += 1;
|
||||
|
||||
hprintln!("idle: local_to_idle = {}", local_to_idle);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
// error: no `local_to_foo` field in `idle::LocalResources`
|
||||
// _cx.local.local_to_foo += 1;
|
||||
|
||||
// error: no `local_to_bar` field in `idle::LocalResources`
|
||||
// _cx.local.local_to_bar += 1;
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
// `local_to_foo` can only be accessed from this context
|
||||
#[task(local = [local_to_foo], priority = 1)]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let local_to_foo = cx.local.local_to_foo;
|
||||
*local_to_foo += 1;
|
||||
|
||||
// error: no `local_to_bar` field in `foo::LocalResources`
|
||||
// cx.local.local_to_bar += 1;
|
||||
|
||||
hprintln!("foo: local_to_foo = {}", local_to_foo);
|
||||
}
|
||||
|
||||
// `local_to_bar` can only be accessed from this context
|
||||
#[task(local = [local_to_bar], priority = 1)]
|
||||
async fn bar(cx: bar::Context) {
|
||||
let local_to_bar = cx.local.local_to_bar;
|
||||
*local_to_bar += 1;
|
||||
|
||||
// error: no `local_to_foo` field in `bar::LocalResources`
|
||||
// cx.local.local_to_foo += 1;
|
||||
|
||||
hprintln!("bar: local_to_bar = {}", local_to_bar);
|
||||
}
|
||||
}
|
||||
129
examples/lm3s6965/examples/complex.rs
Normal file
129
examples/lm3s6965/examples/complex.rs
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
//! examples/complex.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
s2: u32, // shared with ceiling 2
|
||||
s3: u32, // shared with ceiling 3
|
||||
s4: u32, // shared with ceiling 4
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
(
|
||||
Shared {
|
||||
s2: 0,
|
||||
s3: 0,
|
||||
s4: 0,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle(shared = [s2, s3])]
|
||||
fn idle(mut cx: idle::Context) -> ! {
|
||||
hprintln!("idle p0 started");
|
||||
rtic::pend(Interrupt::GPIOC);
|
||||
cx.shared.s3.lock(|s| {
|
||||
hprintln!("idle enter lock s3 {}", s);
|
||||
hprintln!("idle pend t0");
|
||||
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 3
|
||||
hprintln!("idle pend t1");
|
||||
rtic::pend(Interrupt::GPIOB); // t1 p3, with shared ceiling 3
|
||||
hprintln!("idle pend t2");
|
||||
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
|
||||
hprintln!("idle still in lock s3 {}", s);
|
||||
});
|
||||
hprintln!("\nback in idle");
|
||||
|
||||
cx.shared.s2.lock(|s| {
|
||||
hprintln!("enter lock s2 {}", s);
|
||||
hprintln!("idle pend t0");
|
||||
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 2
|
||||
hprintln!("idle pend t1");
|
||||
rtic::pend(Interrupt::GPIOB); // t1 p3, no sharing
|
||||
hprintln!("idle pend t2");
|
||||
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
|
||||
hprintln!("idle still in lock s2 {}", s);
|
||||
});
|
||||
hprintln!("\nidle exit");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = GPIOA, priority = 2, local = [times: u32 = 0], shared = [s2, s3])]
|
||||
fn t0(cx: t0::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"t0 p2 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
hprintln!("t0 p2 exit");
|
||||
}
|
||||
|
||||
#[task(binds = GPIOB, priority = 3, local = [times: u32 = 0], shared = [s3, s4])]
|
||||
fn t1(mut cx: t1::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"t1 p3 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
|
||||
cx.shared.s4.lock(|s| {
|
||||
hprintln!("t1 enter lock s4 {}", s);
|
||||
hprintln!("t1 pend t0");
|
||||
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 2
|
||||
hprintln!("t1 pend t2");
|
||||
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
|
||||
hprintln!("t1 still in lock s4 {}", s);
|
||||
});
|
||||
|
||||
hprintln!("t1 p3 exit");
|
||||
}
|
||||
|
||||
#[task(binds = GPIOC, priority = 4, local = [times: u32 = 0], shared = [s4])]
|
||||
fn t2(mut cx: t2::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"t2 p4 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
|
||||
cx.shared.s4.lock(|s| {
|
||||
hprintln!("enter lock s4 {}", s);
|
||||
*s += 1;
|
||||
});
|
||||
hprintln!("t3 p4 exit");
|
||||
}
|
||||
}
|
||||
47
examples/lm3s6965/examples/declared_locals.rs
Normal file
47
examples/lm3s6965/examples/declared_locals.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//! examples/declared_locals.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [a: u32 = 0])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// Locals in `#[init]` have 'static lifetime
|
||||
let _a: &'static mut u32 = cx.local.a;
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle(local = [a: u32 = 0])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
// Locals in `#[idle]` have 'static lifetime
|
||||
let _a: &'static mut u32 = cx.local.a;
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, local = [a: u32 = 0])]
|
||||
fn foo(cx: foo::Context) {
|
||||
// Locals in `#[task]`s have a local lifetime
|
||||
let _a: &mut u32 = cx.local.a;
|
||||
|
||||
// error: explicit lifetime required in the type of `cx`
|
||||
// let _a: &'static mut u32 = cx.local.a;
|
||||
}
|
||||
}
|
||||
56
examples/lm3s6965/examples/destructure.rs
Normal file
56
examples/lm3s6965/examples/destructure.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//! examples/destructure.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
|
||||
(Shared { a: 0, b: 1, c: 2 }, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {}
|
||||
}
|
||||
|
||||
// Direct destructure
|
||||
#[task(shared = [&a, &b, &c], priority = 1)]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let a = cx.shared.a;
|
||||
let b = cx.shared.b;
|
||||
let c = cx.shared.c;
|
||||
|
||||
hprintln!("foo: a = {}, b = {}, c = {}", a, b, c);
|
||||
}
|
||||
|
||||
// De-structure-ing syntax
|
||||
#[task(shared = [&a, &b, &c], priority = 1)]
|
||||
async fn bar(cx: bar::Context) {
|
||||
let bar::SharedResources { a, b, c, .. } = cx.shared;
|
||||
|
||||
hprintln!("bar: a = {}, b = {}, c = {}", a, b, c);
|
||||
}
|
||||
}
|
||||
42
examples/lm3s6965/examples/executor-size.rs
Normal file
42
examples/lm3s6965/examples/executor-size.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//! examples/executor-size.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init, total executor size = {}", cx.executors_size);
|
||||
|
||||
foo::spawn().ok();
|
||||
bar::spawn().ok();
|
||||
baz::spawn().ok();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_cx: foo::Context) {}
|
||||
|
||||
#[task]
|
||||
async fn bar(_cx: bar::Context) {}
|
||||
|
||||
#[task]
|
||||
async fn baz(_cx: baz::Context) {
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
59
examples/lm3s6965/examples/extern_binds.rs
Normal file
59
examples/lm3s6965/examples/extern_binds.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
//! examples/extern_binds.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
use panic_semihosting as _;
|
||||
|
||||
// Free function implementing `init`.
|
||||
fn init(_: app::init::Context) -> (app::Shared, app::Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
(app::Shared {}, app::Local {})
|
||||
}
|
||||
|
||||
// Free function implementing `idle`.
|
||||
fn idle(_: app::idle::Context) -> ! {
|
||||
hprintln!("idle");
|
||||
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
||||
// Free function implementing the interrupt bound task `foo`.
|
||||
fn foo(_: app::foo::Context) {
|
||||
hprintln!("foo called");
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use crate::{foo, idle, init};
|
||||
|
||||
#[shared]
|
||||
pub struct Shared {}
|
||||
|
||||
#[local]
|
||||
pub struct Local {}
|
||||
|
||||
extern "Rust" {
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local);
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> !;
|
||||
|
||||
#[task(binds = UART0)]
|
||||
fn foo(_: foo::Context);
|
||||
}
|
||||
}
|
||||
40
examples/lm3s6965/examples/extern_spawn.rs
Normal file
40
examples/lm3s6965/examples/extern_spawn.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//! examples/extern_spawn.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use panic_semihosting as _;
|
||||
|
||||
// Free function implementing the spawnable task `foo`.
|
||||
// Notice, you need to indicate an anonymous lifetime <'a_>
|
||||
async fn foo(_c: app::foo::Context<'_>) {
|
||||
hprintln!("foo");
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use crate::foo;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
#[task()]
|
||||
async fn foo(_c: foo::Context);
|
||||
}
|
||||
}
|
||||
67
examples/lm3s6965/examples/generics.rs
Normal file
67
examples/lm3s6965/examples/generics.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//! examples/generics.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use cortex_m_semihosting::hprintln;
|
||||
use panic_semihosting as _;
|
||||
use rtic::Mutex;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
(Shared { shared: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[task(binds = UART0, shared = [shared], local = [state: u32 = 0])]
|
||||
fn uart0(c: uart0::Context) {
|
||||
hprintln!("UART0(STATE = {})", *c.local.state);
|
||||
|
||||
// second argument has type `shared::shared`
|
||||
super::advance(c.local.state, c.shared.shared);
|
||||
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(binds = UART1, priority = 2, shared = [shared], local = [state: u32 = 0])]
|
||||
fn uart1(c: uart1::Context) {
|
||||
hprintln!("UART1(STATE = {})", *c.local.state);
|
||||
|
||||
// second argument has type `shared::shared`
|
||||
super::advance(c.local.state, c.shared.shared);
|
||||
}
|
||||
}
|
||||
|
||||
// the second parameter is generic: it can be any type that implements the `Mutex` trait
|
||||
fn advance(state: &mut u32, mut shared: impl Mutex<T = u32>) {
|
||||
*state += 1;
|
||||
|
||||
let (old, new) = shared.lock(|shared: &mut u32| {
|
||||
let old = *shared;
|
||||
*shared += *state;
|
||||
(old, *shared)
|
||||
});
|
||||
|
||||
hprintln!("shared: {} -> {}", old, new);
|
||||
}
|
||||
60
examples/lm3s6965/examples/hardware.rs
Normal file
60
examples/lm3s6965/examples/hardware.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
//! examples/hardware.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
// Pends the UART0 interrupt but its handler won't run until *after*
|
||||
// `init` returns because interrupts are disabled
|
||||
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
// interrupts are enabled again; the `UART0` handler runs at this point
|
||||
|
||||
hprintln!("idle");
|
||||
|
||||
// Some backends provide a manual way of pending an
|
||||
// interrupt.
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, local = [times: u32 = 0])]
|
||||
fn uart0(cx: uart0::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"UART0 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
}
|
||||
}
|
||||
48
examples/lm3s6965/examples/idle-wfi.rs
Normal file
48
examples/lm3s6965/examples/idle-wfi.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//! examples/idle-wfi.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(mut cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
// Set the ARM SLEEPONEXIT bit to go to sleep after handling interrupts
|
||||
// See https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit
|
||||
cx.core.SCB.set_sleepdeep();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle(local = [x: u32 = 0])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
// Locals in idle have lifetime 'static
|
||||
let _x: &'static mut u32 = cx.local.x;
|
||||
|
||||
hprintln!("idle");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
loop {
|
||||
// Now Wait For Interrupt is used instead of a busy-wait loop
|
||||
// to allow MCU to sleep between interrupts
|
||||
// https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/WFI
|
||||
rtic::export::wfi()
|
||||
}
|
||||
}
|
||||
}
|
||||
41
examples/lm3s6965/examples/idle.rs
Normal file
41
examples/lm3s6965/examples/idle.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
//! examples/idle.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle(local = [x: u32 = 0])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
// Locals in idle have lifetime 'static
|
||||
let _x: &'static mut u32 = cx.local.x;
|
||||
|
||||
hprintln!("idle");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
42
examples/lm3s6965/examples/init.rs
Normal file
42
examples/lm3s6965/examples/init.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//! examples/init.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [x: u32 = 0])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// Cortex-M peripherals
|
||||
let _core: cortex_m::Peripherals = cx.core;
|
||||
|
||||
// Device specific peripherals
|
||||
let _device: lm3s6965::Peripherals = cx.device;
|
||||
|
||||
// Locals in `init` have 'static lifetime
|
||||
let _x: &'static mut u32 = cx.local.x;
|
||||
|
||||
// Access to the critical section token,
|
||||
// to indicate that this is a critical section
|
||||
let _cs_token: bare_metal::CriticalSection = cx.cs;
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
}
|
||||
86
examples/lm3s6965/examples/locals.rs
Normal file
86
examples/lm3s6965/examples/locals.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//! examples/locals.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0, UART1])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
local_to_foo: i64,
|
||||
local_to_bar: i64,
|
||||
local_to_idle: i64,
|
||||
}
|
||||
|
||||
// `#[init]` cannot access locals from the `#[local]` struct as they are initialized here.
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {},
|
||||
// initial values for the `#[local]` resources
|
||||
Local {
|
||||
local_to_foo: 0,
|
||||
local_to_bar: 0,
|
||||
local_to_idle: 0,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// `local_to_idle` can only be accessed from this context
|
||||
#[idle(local = [local_to_idle])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
let local_to_idle = cx.local.local_to_idle;
|
||||
*local_to_idle += 1;
|
||||
|
||||
hprintln!("idle: local_to_idle = {}", local_to_idle);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
// error: no `local_to_foo` field in `idle::LocalResources`
|
||||
// _cx.local.local_to_foo += 1;
|
||||
|
||||
// error: no `local_to_bar` field in `idle::LocalResources`
|
||||
// _cx.local.local_to_bar += 1;
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
// `local_to_foo` can only be accessed from this context
|
||||
#[task(local = [local_to_foo], priority = 1)]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let local_to_foo = cx.local.local_to_foo;
|
||||
*local_to_foo += 1;
|
||||
|
||||
// error: no `local_to_bar` field in `foo::LocalResources`
|
||||
// cx.local.local_to_bar += 1;
|
||||
|
||||
hprintln!("foo: local_to_foo = {}", local_to_foo);
|
||||
}
|
||||
|
||||
// `local_to_bar` can only be accessed from this context
|
||||
#[task(local = [local_to_bar], priority = 1)]
|
||||
async fn bar(cx: bar::Context) {
|
||||
let local_to_bar = cx.local.local_to_bar;
|
||||
*local_to_bar += 1;
|
||||
|
||||
// error: no `local_to_foo` field in `bar::LocalResources`
|
||||
// cx.local.local_to_foo += 1;
|
||||
|
||||
hprintln!("bar: local_to_bar = {}", local_to_bar);
|
||||
}
|
||||
}
|
||||
50
examples/lm3s6965/examples/lock-free.rs
Normal file
50
examples/lm3s6965/examples/lock-free.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//! examples/lock-free.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
#[lock_free] // <- lock-free shared resource
|
||||
counter: u64,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
(Shared { counter: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[task(binds = UART0, shared = [counter])] // <- same priority
|
||||
fn foo(c: foo::Context) {
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
*c.shared.counter += 1; // <- no lock API required
|
||||
let counter = *c.shared.counter;
|
||||
hprintln!(" foo = {}", counter);
|
||||
}
|
||||
|
||||
#[task(binds = UART1, shared = [counter])] // <- same priority
|
||||
fn bar(c: bar::Context) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
*c.shared.counter += 1; // <- no lock API required
|
||||
let counter = *c.shared.counter;
|
||||
hprintln!(" bar = {}", counter);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
72
examples/lm3s6965/examples/lock.rs
Normal file
72
examples/lm3s6965/examples/lock.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//! examples/lock.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [GPIOA, GPIOB, GPIOC])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared { shared: 0 }, Local {})
|
||||
}
|
||||
|
||||
// when omitted priority is assumed to be `1`
|
||||
#[task(shared = [shared])]
|
||||
async fn foo(mut c: foo::Context) {
|
||||
hprintln!("A");
|
||||
|
||||
// the lower priority task requires a critical section to access the data
|
||||
c.shared.shared.lock(|shared| {
|
||||
// data can only be modified within this critical section (closure)
|
||||
*shared += 1;
|
||||
|
||||
// bar will *not* run right now due to the critical section
|
||||
bar::spawn().unwrap();
|
||||
|
||||
hprintln!("B - shared = {}", *shared);
|
||||
|
||||
// baz does not contend for `shared` so it's allowed to run now
|
||||
baz::spawn().unwrap();
|
||||
});
|
||||
|
||||
// critical section is over: bar can now start
|
||||
|
||||
hprintln!("E");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [shared])]
|
||||
async fn bar(mut c: bar::Context) {
|
||||
// the higher priority task does still need a critical section
|
||||
let shared = c.shared.shared.lock(|shared| {
|
||||
*shared += 1;
|
||||
|
||||
*shared
|
||||
});
|
||||
|
||||
hprintln!("D - shared = {}", shared);
|
||||
}
|
||||
|
||||
#[task(priority = 3)]
|
||||
async fn baz(_: baz::Context) {
|
||||
hprintln!("C");
|
||||
}
|
||||
}
|
||||
56
examples/lm3s6965/examples/multilock.rs
Normal file
56
examples/lm3s6965/examples/multilock.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
//! examples/mutlilock.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [GPIOA])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared1: u32,
|
||||
shared2: u32,
|
||||
shared3: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
locks::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {
|
||||
shared1: 0,
|
||||
shared2: 0,
|
||||
shared3: 0,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
// when omitted priority is assumed to be `1`
|
||||
#[task(shared = [shared1, shared2, shared3])]
|
||||
async fn locks(c: locks::Context) {
|
||||
let s1 = c.shared.shared1;
|
||||
let s2 = c.shared.shared2;
|
||||
let s3 = c.shared.shared3;
|
||||
|
||||
(s1, s2, s3).lock(|s1, s2, s3| {
|
||||
*s1 += 1;
|
||||
*s2 += 1;
|
||||
*s3 += 1;
|
||||
|
||||
hprintln!("Multiple locks, s1: {}, s2: {}, s3: {}", *s1, *s2, *s3);
|
||||
});
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
67
examples/lm3s6965/examples/not-sync.rs
Normal file
67
examples/lm3s6965/examples/not-sync.rs
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
//! `examples/not-sync.rs`
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Not sync
|
||||
pub struct NotSync {
|
||||
_0: PhantomData<*const ()>,
|
||||
data: u32,
|
||||
}
|
||||
|
||||
unsafe impl Send for NotSync {}
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use super::NotSync;
|
||||
use core::marker::PhantomData;
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared: NotSync,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
(
|
||||
Shared {
|
||||
shared: NotSync {
|
||||
_0: PhantomData,
|
||||
data: 13,
|
||||
},
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[task(shared = [&shared], priority = 1)]
|
||||
async fn foo(c: foo::Context) {
|
||||
let shared: &NotSync = c.shared.shared;
|
||||
hprintln!("foo a {}", shared.data);
|
||||
}
|
||||
|
||||
#[task(shared = [&shared], priority = 1)]
|
||||
async fn bar(c: bar::Context) {
|
||||
let shared: &NotSync = c.shared.shared;
|
||||
hprintln!("bar a {}", shared.data);
|
||||
}
|
||||
}
|
||||
43
examples/lm3s6965/examples/only-shared-access.rs
Normal file
43
examples/lm3s6965/examples/only-shared-access.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
//! examples/only-shared-access.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0, UART1])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
key: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
|
||||
(Shared { key: 0xdeadbeef }, Local {})
|
||||
}
|
||||
|
||||
#[task(shared = [&key])]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let key: &u32 = cx.shared.key;
|
||||
hprintln!("foo(key = {:#x})", key);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [&key])]
|
||||
async fn bar(cx: bar::Context) {
|
||||
hprintln!("bar(key = {:#x})", cx.shared.key);
|
||||
}
|
||||
}
|
||||
28
examples/lm3s6965/examples/peripherals-taken.rs
Normal file
28
examples/lm3s6965/examples/peripherals-taken.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
//! examples/peripherals-taken.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
assert!(cortex_m::Peripherals::take().is_none());
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
}
|
||||
69
examples/lm3s6965/examples/pool.rs_old
Normal file
69
examples/lm3s6965/examples/pool.rs_old
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
//! examples/pool.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
|
||||
use heapless::{
|
||||
pool,
|
||||
pool::singleton::{Box, Pool},
|
||||
};
|
||||
use panic_semihosting as _;
|
||||
use rtic::app;
|
||||
|
||||
// Declare a pool of 128-byte memory blocks
|
||||
pool!(P: [u8; 128]);
|
||||
|
||||
#[app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
use crate::{Box, Pool};
|
||||
use cortex_m_semihosting::debug;
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
// Import the memory pool into scope
|
||||
use super::P;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [memory: [u8; 512] = [0; 512]])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// Increase the capacity of the memory pool by ~4
|
||||
P::grow(cx.local.memory);
|
||||
|
||||
rtic::pend(Interrupt::I2C0);
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task(binds = I2C0, priority = 2)]
|
||||
fn i2c0(_: i2c0::Context) {
|
||||
// claim a memory block, initialize it and ..
|
||||
let x = P::alloc().unwrap().init([0u8; 128]);
|
||||
|
||||
// .. send it to the `foo` task
|
||||
foo::spawn(x).ok().unwrap();
|
||||
|
||||
// send another block to the task `bar`
|
||||
bar::spawn(P::alloc().unwrap().init([0u8; 128]))
|
||||
.ok()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_: foo::Context, _x: Box<P>) {
|
||||
// explicitly return the block to the pool
|
||||
drop(_x);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn bar(_: bar::Context, _x: Box<P>) {
|
||||
// this is done automatically so we can omit the call to `drop`
|
||||
// drop(_x);
|
||||
}
|
||||
}
|
||||
48
examples/lm3s6965/examples/preempt.rs
Normal file
48
examples/lm3s6965/examples/preempt.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
//! examples/preempt.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
use rtic::app;
|
||||
|
||||
#[app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task(priority = 1)]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo - start");
|
||||
baz::spawn().unwrap();
|
||||
hprintln!("foo - end");
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn bar(_: bar::Context) {
|
||||
hprintln!(" bar");
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn baz(_: baz::Context) {
|
||||
hprintln!(" baz - start");
|
||||
bar::spawn().unwrap();
|
||||
hprintln!(" baz - end");
|
||||
}
|
||||
}
|
||||
86
examples/lm3s6965/examples/prio-inversion.rs
Normal file
86
examples/lm3s6965/examples/prio-inversion.rs
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
//! examples/prio-inversion.rs
|
||||
//!
|
||||
//! Here we test to make sure we don't have priority inversion.
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
use rtic::app;
|
||||
|
||||
// t1 p1 use b, a
|
||||
// t2 p2 use a
|
||||
// t3 p3
|
||||
// t4 p4 use b
|
||||
//
|
||||
// so t1 start , take b take a, pend t3
|
||||
// t3 should not start
|
||||
// try to see if it starts, IT SHOULD NOT
|
||||
|
||||
#[app(device = lm3s6965, dispatchers = [SSI0, QEI0, GPIOA, GPIOB])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared { a: 0, b: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[task(priority = 1, shared = [a, b])]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let foo::SharedResources { mut a, mut b, .. } = cx.shared;
|
||||
|
||||
hprintln!("foo - start");
|
||||
|
||||
// basepri = 0
|
||||
b.lock(|b| {
|
||||
// basepri = max(basepri = 0, ceil(b) = 4) = 4
|
||||
a.lock(|a| {
|
||||
// basepri = max(basepri = 4, ceil(a) = 2) = 4
|
||||
|
||||
hprintln!("pre baz spawn {} {}", a, b);
|
||||
|
||||
// This spawn should be blocked as prio(baz) = 3
|
||||
baz::spawn().unwrap();
|
||||
|
||||
hprintln!("post baz spawn {} {}", a, b);
|
||||
});
|
||||
// basepri = 4
|
||||
});
|
||||
// basepri = 0
|
||||
|
||||
hprintln!("foo - end");
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [a])]
|
||||
async fn bar(_: bar::Context) {
|
||||
hprintln!(" bar");
|
||||
}
|
||||
|
||||
#[task(priority = 3)]
|
||||
async fn baz(_: baz::Context) {
|
||||
hprintln!(" baz - start");
|
||||
hprintln!(" baz - end");
|
||||
}
|
||||
|
||||
#[task(priority = 4, shared = [b])]
|
||||
async fn pow(_: pow::Context) {
|
||||
hprintln!(" pow - start");
|
||||
hprintln!(" pow - end");
|
||||
}
|
||||
}
|
||||
49
examples/lm3s6965/examples/ramfunc.rs
Normal file
49
examples/lm3s6965/examples/ramfunc.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
//! examples/ramfunc.rs
|
||||
//! TODO: verify that ram-sections are properly used
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(
|
||||
device = lm3s6965,
|
||||
dispatchers = [
|
||||
UART0,
|
||||
#[link_section = ".data.UART1"]
|
||||
UART1
|
||||
])
|
||||
]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
// run this task from RAM
|
||||
#[inline(never)]
|
||||
#[link_section = ".data.bar"]
|
||||
#[task(priority = 2)]
|
||||
async fn bar(_: bar::Context) {
|
||||
foo::spawn().unwrap();
|
||||
}
|
||||
}
|
||||
72
examples/lm3s6965/examples/resource-user-struct.rs
Normal file
72
examples/lm3s6965/examples/resource-user-struct.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//! examples/resource.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
// A resource
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
// Should not collide with the struct above
|
||||
#[allow(dead_code)]
|
||||
struct Shared2 {
|
||||
// A resource
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
(Shared { shared: 0 }, Local {})
|
||||
}
|
||||
|
||||
// `shared` cannot be accessed from this context
|
||||
#[idle]
|
||||
fn idle(_cx: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
// error: no `shared` field in `idle::Context`
|
||||
// _cx.shared.shared += 1;
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
// `shared` can be accessed from this context
|
||||
#[task(binds = UART0, shared = [shared])]
|
||||
fn uart0(mut cx: uart0::Context) {
|
||||
let shared = cx.shared.shared.lock(|shared| {
|
||||
*shared += 1;
|
||||
*shared
|
||||
});
|
||||
|
||||
hprintln!("UART0: shared = {}", shared);
|
||||
}
|
||||
|
||||
// `shared` can be accessed from this context
|
||||
#[task(binds = UART1, shared = [shared])]
|
||||
fn uart1(mut cx: uart1::Context) {
|
||||
let shared = cx.shared.shared.lock(|shared| {
|
||||
*shared += 1;
|
||||
*shared
|
||||
});
|
||||
|
||||
hprintln!("UART1: shared = {}", shared);
|
||||
}
|
||||
}
|
||||
51
examples/lm3s6965/examples/shared.rs
Normal file
51
examples/lm3s6965/examples/shared.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//! examples/late.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use heapless::spsc::{Consumer, Producer, Queue};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
p: Producer<'static, u32, 5>,
|
||||
c: Consumer<'static, u32, 5>,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [q: Queue<u32, 5> = Queue::new()])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
let (p, c) = cx.local.q.split();
|
||||
|
||||
// Initialization of shared resources
|
||||
(Shared { p, c }, Local {})
|
||||
}
|
||||
|
||||
#[idle(shared = [c])]
|
||||
fn idle(mut c: idle::Context) -> ! {
|
||||
loop {
|
||||
if let Some(byte) = c.shared.c.lock(|c| c.dequeue()) {
|
||||
hprintln!("received message: {}", byte);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
} else {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, shared = [p])]
|
||||
fn uart0(mut c: uart0::Context) {
|
||||
c.shared.p.lock(|p| p.enqueue(42).unwrap());
|
||||
}
|
||||
}
|
||||
27
examples/lm3s6965/examples/smallest.rs
Normal file
27
examples/lm3s6965/examples/smallest.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
//! examples/smallest.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _; // panic handler
|
||||
use rtic::app;
|
||||
|
||||
#[app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
}
|
||||
35
examples/lm3s6965/examples/spawn.rs
Normal file
35
examples/lm3s6965/examples/spawn.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//! examples/spawn.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
34
examples/lm3s6965/examples/spawn_arguments.rs
Normal file
34
examples/lm3s6965/examples/spawn_arguments.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
//! examples/spawn_arguments.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn(1, 1).unwrap();
|
||||
assert!(foo::spawn(1, 4).is_err()); // The capacity of `foo` is reached
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_c: foo::Context, x: i32, y: u32) {
|
||||
hprintln!("foo {}, {}", x, y);
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
39
examples/lm3s6965/examples/spawn_err.rs
Normal file
39
examples/lm3s6965/examples/spawn_err.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
//! examples/spawn_err.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
foo::spawn().unwrap();
|
||||
match foo::spawn() {
|
||||
Ok(_) => {}
|
||||
Err(()) => hprintln!("Cannot spawn a spawned (running) task!"),
|
||||
}
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
42
examples/lm3s6965/examples/spawn_loop.rs
Normal file
42
examples/lm3s6965/examples/spawn_loop.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//! examples/spawn_loop.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
for _ in 0..3 {
|
||||
foo::spawn().unwrap();
|
||||
hprintln!("idle");
|
||||
}
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[task(priority = 1)]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo");
|
||||
}
|
||||
}
|
||||
60
examples/lm3s6965/examples/static.rs
Normal file
60
examples/lm3s6965/examples/static.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
//! examples/static.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use heapless::spsc::{Consumer, Producer, Queue};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
p: Producer<'static, u32, 5>,
|
||||
c: Consumer<'static, u32, 5>,
|
||||
}
|
||||
|
||||
#[init(local = [q: Queue<u32, 5> = Queue::new()])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// q has 'static life-time so after the split and return of `init`
|
||||
// it will continue to exist and be allocated
|
||||
let (p, c) = cx.local.q.split();
|
||||
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local { p, c })
|
||||
}
|
||||
|
||||
#[idle(local = [c])]
|
||||
fn idle(c: idle::Context) -> ! {
|
||||
loop {
|
||||
// Lock-free access to the same underlying queue!
|
||||
if let Some(data) = c.local.c.dequeue() {
|
||||
hprintln!("received message: {}", data);
|
||||
|
||||
// Run foo until data
|
||||
if data == 3 {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
} else {
|
||||
foo::spawn().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[task(local = [p, state: u32 = 0], priority = 1)]
|
||||
async fn foo(c: foo::Context) {
|
||||
*c.local.state += 1;
|
||||
|
||||
// Lock-free access to the same underlying queue!
|
||||
c.local.p.enqueue(*c.local.state).unwrap();
|
||||
}
|
||||
}
|
||||
45
examples/lm3s6965/examples/t-binds.rs
Normal file
45
examples/lm3s6965/examples/t-binds.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
//! [compile-pass] Check that `binds` works as advertised
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
// Cortex-M exception
|
||||
#[task(binds = SVCall)]
|
||||
fn foo(c: foo::Context) {
|
||||
crate::foo_trampoline(c)
|
||||
}
|
||||
|
||||
// LM3S6965 interrupt
|
||||
#[task(binds = UART0)]
|
||||
fn bar(c: bar::Context) {
|
||||
crate::bar_trampoline(c)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn foo_trampoline(_: app::foo::Context) {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn bar_trampoline(_: app::bar::Context) {}
|
||||
44
examples/lm3s6965/examples/t-cfg-resources.rs
Normal file
44
examples/lm3s6965/examples/t-cfg-resources.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//! [compile-pass] check that `#[cfg]` attributes applied on resources work
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
// A conditionally compiled resource behind feature_x
|
||||
#[cfg(feature = "feature_x")]
|
||||
x: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(
|
||||
Shared {
|
||||
#[cfg(feature = "feature_x")]
|
||||
x: 0,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_cx: idle::Context) -> ! {
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
32
examples/lm3s6965/examples/t-htask-main.rs
Normal file
32
examples/lm3s6965/examples/t-htask-main.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
//! examples/t-task-main.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(lm3s6965::Interrupt::UART0);
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task(binds = UART0)]
|
||||
fn taskmain(_: taskmain::Context) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
33
examples/lm3s6965/examples/t-idle-main.rs
Normal file
33
examples/lm3s6965/examples/t-idle-main.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
//! examples/t-idle-main.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn taskmain(_: taskmain::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
50
examples/lm3s6965/examples/t-late-not-send.rs
Normal file
50
examples/lm3s6965/examples/t-late-not-send.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//! [compile-pass] shared resources don't need to be `Send` if they are owned by `idle`
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Not send
|
||||
pub struct NotSend {
|
||||
_0: PhantomData<*const ()>,
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use super::NotSend;
|
||||
use core::marker::PhantomData;
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
x: NotSend,
|
||||
y: Option<NotSend>,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
(
|
||||
Shared {
|
||||
x: NotSend { _0: PhantomData },
|
||||
y: None,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle(shared = [x, y])]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
57
examples/lm3s6965/examples/task.rs
Normal file
57
examples/lm3s6965/examples/task.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
//! examples/task.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo - start");
|
||||
|
||||
// spawns `bar` onto the task scheduler
|
||||
// `foo` and `bar` have the same priority so `bar` will not run until
|
||||
// after `foo` terminates
|
||||
bar::spawn().unwrap();
|
||||
|
||||
hprintln!("foo - middle");
|
||||
|
||||
// spawns `baz` onto the task scheduler
|
||||
// `baz` has higher priority than `foo` so it immediately preempts `foo`
|
||||
baz::spawn().unwrap();
|
||||
|
||||
hprintln!("foo - end");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn bar(_: bar::Context) {
|
||||
hprintln!("bar");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn baz(_: baz::Context) {
|
||||
hprintln!("baz");
|
||||
}
|
||||
}
|
||||
61
examples/lm3s6965/examples/zero-prio-task.rs
Normal file
61
examples/lm3s6965/examples/zero-prio-task.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//! examples/zero-prio-task.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(warnings)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Does not impl send
|
||||
pub struct NotSend {
|
||||
_0: PhantomData<*const ()>,
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||
mod app {
|
||||
use super::NotSend;
|
||||
use core::marker::PhantomData;
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
x: NotSend,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
y: NotSend,
|
||||
}
|
||||
|
||||
#[init]
|
||||
fn init(_cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
async_task::spawn().unwrap();
|
||||
async_task2::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {
|
||||
x: NotSend { _0: PhantomData },
|
||||
},
|
||||
Local {
|
||||
y: NotSend { _0: PhantomData },
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[task(priority = 0, shared = [x], local = [y])]
|
||||
async fn async_task(_: async_task::Context) {
|
||||
hprintln!("hello from async");
|
||||
}
|
||||
|
||||
#[task(priority = 0, shared = [x])]
|
||||
async fn async_task2(_: async_task2::Context) {
|
||||
hprintln!("hello from async2");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue