aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/hifive1/.cargo/config.toml11
-rw-r--r--examples/hifive1/Cargo.lock364
-rw-r--r--examples/hifive1/Cargo.toml22
-rw-r--r--examples/hifive1/examples/prio_inheritance.rs140
-rw-r--r--examples/hifive1/examples/static.rs60
-rw-r--r--examples/hifive1/examples/task.rs57
-rw-r--r--examples/hifive1/examples/zero_prio_task.rs61
-rw-r--r--examples/hifive1/rust-toolchain.toml4
-rw-r--r--examples/lm3s6965/.cargo/config.toml13
-rw-r--r--examples/lm3s6965/Cargo.lock527
-rw-r--r--examples/lm3s6965/Cargo.toml36
-rw-r--r--examples/lm3s6965/examples/async-channel-done.rs65
-rw-r--r--examples/lm3s6965/examples/async-channel-no-receiver.rs37
-rw-r--r--examples/lm3s6965/examples/async-channel-no-sender.rs38
-rw-r--r--examples/lm3s6965/examples/async-channel-try.rs56
-rw-r--r--examples/lm3s6965/examples/async-channel.rs62
-rw-r--r--examples/lm3s6965/examples/async-delay.rs58
-rw-r--r--examples/lm3s6965/examples/async-task-multiple-prios.rs93
-rw-r--r--examples/lm3s6965/examples/async-task.rs71
-rw-r--r--examples/lm3s6965/examples/async-timeout.rs96
-rw-r--r--examples/lm3s6965/examples/big-struct-opt.rs80
-rw-r--r--examples/lm3s6965/examples/binds.rs54
-rw-r--r--examples/lm3s6965/examples/common.rs86
-rw-r--r--examples/lm3s6965/examples/complex.rs129
-rw-r--r--examples/lm3s6965/examples/declared_locals.rs47
-rw-r--r--examples/lm3s6965/examples/destructure.rs56
-rw-r--r--examples/lm3s6965/examples/executor-size.rs42
-rw-r--r--examples/lm3s6965/examples/extern_binds.rs59
-rw-r--r--examples/lm3s6965/examples/extern_spawn.rs40
-rw-r--r--examples/lm3s6965/examples/generics.rs67
-rw-r--r--examples/lm3s6965/examples/hardware.rs60
-rw-r--r--examples/lm3s6965/examples/idle-wfi.rs48
-rw-r--r--examples/lm3s6965/examples/idle.rs41
-rw-r--r--examples/lm3s6965/examples/init.rs42
-rw-r--r--examples/lm3s6965/examples/locals.rs86
-rw-r--r--examples/lm3s6965/examples/lock-free.rs50
-rw-r--r--examples/lm3s6965/examples/lock.rs72
-rw-r--r--examples/lm3s6965/examples/multilock.rs56
-rw-r--r--examples/lm3s6965/examples/not-sync.rs67
-rw-r--r--examples/lm3s6965/examples/only-shared-access.rs43
-rw-r--r--examples/lm3s6965/examples/peripherals-taken.rs28
-rw-r--r--examples/lm3s6965/examples/pool.rs_old69
-rw-r--r--examples/lm3s6965/examples/preempt.rs48
-rw-r--r--examples/lm3s6965/examples/prio-inversion.rs86
-rw-r--r--examples/lm3s6965/examples/ramfunc.rs49
-rw-r--r--examples/lm3s6965/examples/resource-user-struct.rs72
-rw-r--r--examples/lm3s6965/examples/shared.rs51
-rw-r--r--examples/lm3s6965/examples/smallest.rs27
-rw-r--r--examples/lm3s6965/examples/spawn.rs35
-rw-r--r--examples/lm3s6965/examples/spawn_arguments.rs34
-rw-r--r--examples/lm3s6965/examples/spawn_err.rs39
-rw-r--r--examples/lm3s6965/examples/spawn_loop.rs42
-rw-r--r--examples/lm3s6965/examples/static.rs60
-rw-r--r--examples/lm3s6965/examples/t-binds.rs45
-rw-r--r--examples/lm3s6965/examples/t-cfg-resources.rs44
-rw-r--r--examples/lm3s6965/examples/t-htask-main.rs32
-rw-r--r--examples/lm3s6965/examples/t-idle-main.rs33
-rw-r--r--examples/lm3s6965/examples/t-late-not-send.rs50
-rw-r--r--examples/lm3s6965/examples/task.rs57
-rw-r--r--examples/lm3s6965/examples/zero-prio-task.rs61
60 files changed, 4058 insertions, 0 deletions
diff --git a/examples/hifive1/.cargo/config.toml b/examples/hifive1/.cargo/config.toml
new file mode 100644
index 0000000..2ce90b2
--- /dev/null
+++ b/examples/hifive1/.cargo/config.toml
@@ -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)
diff --git a/examples/hifive1/Cargo.lock b/examples/hifive1/Cargo.lock
new file mode 100644
index 0000000..7cd694c
--- /dev/null
+++ b/examples/hifive1/Cargo.lock
@@ -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"
diff --git a/examples/hifive1/Cargo.toml b/examples/hifive1/Cargo.toml
new file mode 100644
index 0000000..42d60a7
--- /dev/null
+++ b/examples/hifive1/Cargo.toml
@@ -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 = []
diff --git a/examples/hifive1/examples/prio_inheritance.rs b/examples/hifive1/examples/prio_inheritance.rs
new file mode 100644
index 0000000..5fc2399
--- /dev/null
+++ b/examples/hifive1/examples/prio_inheritance.rs
@@ -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");
+ }
+}
diff --git a/examples/hifive1/examples/static.rs b/examples/hifive1/examples/static.rs
new file mode 100644
index 0000000..34e71c6
--- /dev/null
+++ b/examples/hifive1/examples/static.rs
@@ -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();
+ }
+}
diff --git a/examples/hifive1/examples/task.rs b/examples/hifive1/examples/task.rs
new file mode 100644
index 0000000..6968edb
--- /dev/null
+++ b/examples/hifive1/examples/task.rs
@@ -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");
+ }
+}
diff --git a/examples/hifive1/examples/zero_prio_task.rs b/examples/hifive1/examples/zero_prio_task.rs
new file mode 100644
index 0000000..2528c4f
--- /dev/null
+++ b/examples/hifive1/examples/zero_prio_task.rs
@@ -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
+ }
+}
diff --git a/examples/hifive1/rust-toolchain.toml b/examples/hifive1/rust-toolchain.toml
new file mode 100644
index 0000000..3dc1c7e
--- /dev/null
+++ b/examples/hifive1/rust-toolchain.toml
@@ -0,0 +1,4 @@
+[toolchain]
+channel = "stable"
+components = [ "rust-src", "rustfmt" ]
+targets = [ "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf" ]
diff --git a/examples/lm3s6965/.cargo/config.toml b/examples/lm3s6965/.cargo/config.toml
new file mode 100644
index 0000000..46b5177
--- /dev/null
+++ b/examples/lm3s6965/.cargo/config.toml
@@ -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"
diff --git a/examples/lm3s6965/Cargo.lock b/examples/lm3s6965/Cargo.lock
new file mode 100644
index 0000000..696c606
--- /dev/null
+++ b/examples/lm3s6965/Cargo.lock
@@ -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",
+]
diff --git a/examples/lm3s6965/Cargo.toml b/examples/lm3s6965/Cargo.toml
new file mode 100644
index 0000000..86a7cbb
--- /dev/null
+++ b/examples/lm3s6965/Cargo.toml
@@ -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"]
diff --git a/examples/lm3s6965/examples/async-channel-done.rs b/examples/lm3s6965/examples/async-channel-done.rs
new file mode 100644
index 0000000..e9b9887
--- /dev/null
+++ b/examples/lm3s6965/examples/async-channel-done.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/async-channel-no-receiver.rs b/examples/lm3s6965/examples/async-channel-no-receiver.rs
new file mode 100644
index 0000000..7e416be
--- /dev/null
+++ b/examples/lm3s6965/examples/async-channel-no-receiver.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/async-channel-no-sender.rs b/examples/lm3s6965/examples/async-channel-no-sender.rs
new file mode 100644
index 0000000..c4f043c
--- /dev/null
+++ b/examples/lm3s6965/examples/async-channel-no-sender.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/async-channel-try.rs b/examples/lm3s6965/examples/async-channel-try.rs
new file mode 100644
index 0000000..92c6ab6
--- /dev/null
+++ b/examples/lm3s6965/examples/async-channel-try.rs
@@ -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();
+ }
+}
diff --git a/examples/lm3s6965/examples/async-channel.rs b/examples/lm3s6965/examples/async-channel.rs
new file mode 100644
index 0000000..642e218
--- /dev/null
+++ b/examples/lm3s6965/examples/async-channel.rs
@@ -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();
+ }
+}
diff --git a/examples/lm3s6965/examples/async-delay.rs b/examples/lm3s6965/examples/async-delay.rs
new file mode 100644
index 0000000..9ccfc02
--- /dev/null
+++ b/examples/lm3s6965/examples/async-delay.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/async-task-multiple-prios.rs b/examples/lm3s6965/examples/async-task-multiple-prios.rs
new file mode 100644
index 0000000..39b6d60
--- /dev/null
+++ b/examples/lm3s6965/examples/async-task-multiple-prios.rs
@@ -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
+ })
+ );
+ }
+}
diff --git a/examples/lm3s6965/examples/async-task.rs b/examples/lm3s6965/examples/async-task.rs
new file mode 100644
index 0000000..1867c4d
--- /dev/null
+++ b/examples/lm3s6965/examples/async-task.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/async-timeout.rs b/examples/lm3s6965/examples/async-timeout.rs
new file mode 100644
index 0000000..e5e129f
--- /dev/null
+++ b/examples/lm3s6965/examples/async-timeout.rs
@@ -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
+}
diff --git a/examples/lm3s6965/examples/big-struct-opt.rs b/examples/lm3s6965/examples/big-struct-opt.rs
new file mode 100644
index 0000000..109cc5d
--- /dev/null
+++ b/examples/lm3s6965/examples/big-struct-opt.rs
@@ -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]));
+ }
+}
diff --git a/examples/lm3s6965/examples/binds.rs b/examples/lm3s6965/examples/binds.rs
new file mode 100644
index 0000000..b101d54
--- /dev/null
+++ b/examples/lm3s6965/examples/binds.rs
@@ -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 { "" }
+ );
+ }
+}
diff --git a/examples/lm3s6965/examples/common.rs b/examples/lm3s6965/examples/common.rs
new file mode 100644
index 0000000..7f68739
--- /dev/null
+++ b/examples/lm3s6965/examples/common.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/complex.rs b/examples/lm3s6965/examples/complex.rs
new file mode 100644
index 0000000..a4fe659
--- /dev/null
+++ b/examples/lm3s6965/examples/complex.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/declared_locals.rs b/examples/lm3s6965/examples/declared_locals.rs
new file mode 100644
index 0000000..b1bb9f4
--- /dev/null
+++ b/examples/lm3s6965/examples/declared_locals.rs
@@ -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;
+ }
+}
diff --git a/examples/lm3s6965/examples/destructure.rs b/examples/lm3s6965/examples/destructure.rs
new file mode 100644
index 0000000..ac35187
--- /dev/null
+++ b/examples/lm3s6965/examples/destructure.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/executor-size.rs b/examples/lm3s6965/examples/executor-size.rs
new file mode 100644
index 0000000..d825729
--- /dev/null
+++ b/examples/lm3s6965/examples/executor-size.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/extern_binds.rs b/examples/lm3s6965/examples/extern_binds.rs
new file mode 100644
index 0000000..45939d2
--- /dev/null
+++ b/examples/lm3s6965/examples/extern_binds.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/extern_spawn.rs b/examples/lm3s6965/examples/extern_spawn.rs
new file mode 100644
index 0000000..7f68b42
--- /dev/null
+++ b/examples/lm3s6965/examples/extern_spawn.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/generics.rs b/examples/lm3s6965/examples/generics.rs
new file mode 100644
index 0000000..dd042a3
--- /dev/null
+++ b/examples/lm3s6965/examples/generics.rs
@@ -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);
+}
diff --git a/examples/lm3s6965/examples/hardware.rs b/examples/lm3s6965/examples/hardware.rs
new file mode 100644
index 0000000..3bd62b6
--- /dev/null
+++ b/examples/lm3s6965/examples/hardware.rs
@@ -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 { "" }
+ );
+ }
+}
diff --git a/examples/lm3s6965/examples/idle-wfi.rs b/examples/lm3s6965/examples/idle-wfi.rs
new file mode 100644
index 0000000..72aaa95
--- /dev/null
+++ b/examples/lm3s6965/examples/idle-wfi.rs
@@ -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()
+ }
+ }
+}
diff --git a/examples/lm3s6965/examples/idle.rs b/examples/lm3s6965/examples/idle.rs
new file mode 100644
index 0000000..4149818
--- /dev/null
+++ b/examples/lm3s6965/examples/idle.rs
@@ -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();
+ }
+ }
+}
diff --git a/examples/lm3s6965/examples/init.rs b/examples/lm3s6965/examples/init.rs
new file mode 100644
index 0000000..634d309
--- /dev/null
+++ b/examples/lm3s6965/examples/init.rs
@@ -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 {})
+ }
+}
diff --git a/examples/lm3s6965/examples/locals.rs b/examples/lm3s6965/examples/locals.rs
new file mode 100644
index 0000000..5d5e246
--- /dev/null
+++ b/examples/lm3s6965/examples/locals.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/lock-free.rs b/examples/lm3s6965/examples/lock-free.rs
new file mode 100644
index 0000000..c9d2ab0
--- /dev/null
+++ b/examples/lm3s6965/examples/lock-free.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/lock.rs b/examples/lm3s6965/examples/lock.rs
new file mode 100644
index 0000000..091a1b0
--- /dev/null
+++ b/examples/lm3s6965/examples/lock.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/multilock.rs b/examples/lm3s6965/examples/multilock.rs
new file mode 100644
index 0000000..77245ae
--- /dev/null
+++ b/examples/lm3s6965/examples/multilock.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/not-sync.rs b/examples/lm3s6965/examples/not-sync.rs
new file mode 100644
index 0000000..09ba77e
--- /dev/null
+++ b/examples/lm3s6965/examples/not-sync.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/only-shared-access.rs b/examples/lm3s6965/examples/only-shared-access.rs
new file mode 100644
index 0000000..c83dca5
--- /dev/null
+++ b/examples/lm3s6965/examples/only-shared-access.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/peripherals-taken.rs b/examples/lm3s6965/examples/peripherals-taken.rs
new file mode 100644
index 0000000..2f63001
--- /dev/null
+++ b/examples/lm3s6965/examples/peripherals-taken.rs
@@ -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 {})
+ }
+}
diff --git a/examples/lm3s6965/examples/pool.rs_old b/examples/lm3s6965/examples/pool.rs_old
new file mode 100644
index 0000000..b399202
--- /dev/null
+++ b/examples/lm3s6965/examples/pool.rs_old
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/preempt.rs b/examples/lm3s6965/examples/preempt.rs
new file mode 100644
index 0000000..62c67dc
--- /dev/null
+++ b/examples/lm3s6965/examples/preempt.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/prio-inversion.rs b/examples/lm3s6965/examples/prio-inversion.rs
new file mode 100644
index 0000000..36dcbe2
--- /dev/null
+++ b/examples/lm3s6965/examples/prio-inversion.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/ramfunc.rs b/examples/lm3s6965/examples/ramfunc.rs
new file mode 100644
index 0000000..d072ecb
--- /dev/null
+++ b/examples/lm3s6965/examples/ramfunc.rs
@@ -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();
+ }
+}
diff --git a/examples/lm3s6965/examples/resource-user-struct.rs b/examples/lm3s6965/examples/resource-user-struct.rs
new file mode 100644
index 0000000..cad42d7
--- /dev/null
+++ b/examples/lm3s6965/examples/resource-user-struct.rs
@@ -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);
+ }
+}
diff --git a/examples/lm3s6965/examples/shared.rs b/examples/lm3s6965/examples/shared.rs
new file mode 100644
index 0000000..79ebab8
--- /dev/null
+++ b/examples/lm3s6965/examples/shared.rs
@@ -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());
+ }
+}
diff --git a/examples/lm3s6965/examples/smallest.rs b/examples/lm3s6965/examples/smallest.rs
new file mode 100644
index 0000000..fee3f05
--- /dev/null
+++ b/examples/lm3s6965/examples/smallest.rs
@@ -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 {})
+ }
+}
diff --git a/examples/lm3s6965/examples/spawn.rs b/examples/lm3s6965/examples/spawn.rs
new file mode 100644
index 0000000..448bcda
--- /dev/null
+++ b/examples/lm3s6965/examples/spawn.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/spawn_arguments.rs b/examples/lm3s6965/examples/spawn_arguments.rs
new file mode 100644
index 0000000..61c4608
--- /dev/null
+++ b/examples/lm3s6965/examples/spawn_arguments.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/spawn_err.rs b/examples/lm3s6965/examples/spawn_err.rs
new file mode 100644
index 0000000..e5a9420
--- /dev/null
+++ b/examples/lm3s6965/examples/spawn_err.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/spawn_loop.rs b/examples/lm3s6965/examples/spawn_loop.rs
new file mode 100644
index 0000000..13e386a
--- /dev/null
+++ b/examples/lm3s6965/examples/spawn_loop.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/static.rs b/examples/lm3s6965/examples/static.rs
new file mode 100644
index 0000000..fec73fc
--- /dev/null
+++ b/examples/lm3s6965/examples/static.rs
@@ -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();
+ }
+}
diff --git a/examples/lm3s6965/examples/t-binds.rs b/examples/lm3s6965/examples/t-binds.rs
new file mode 100644
index 0000000..01c262c
--- /dev/null
+++ b/examples/lm3s6965/examples/t-binds.rs
@@ -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) {}
diff --git a/examples/lm3s6965/examples/t-cfg-resources.rs b/examples/lm3s6965/examples/t-cfg-resources.rs
new file mode 100644
index 0000000..2ddfae7
--- /dev/null
+++ b/examples/lm3s6965/examples/t-cfg-resources.rs
@@ -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();
+ }
+ }
+}
diff --git a/examples/lm3s6965/examples/t-htask-main.rs b/examples/lm3s6965/examples/t-htask-main.rs
new file mode 100644
index 0000000..61280f8
--- /dev/null
+++ b/examples/lm3s6965/examples/t-htask-main.rs
@@ -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
+ }
+}
diff --git a/examples/lm3s6965/examples/t-idle-main.rs b/examples/lm3s6965/examples/t-idle-main.rs
new file mode 100644
index 0000000..88566a9
--- /dev/null
+++ b/examples/lm3s6965/examples/t-idle-main.rs
@@ -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();
+ }
+ }
+}
diff --git a/examples/lm3s6965/examples/t-late-not-send.rs b/examples/lm3s6965/examples/t-late-not-send.rs
new file mode 100644
index 0000000..be5cc66
--- /dev/null
+++ b/examples/lm3s6965/examples/t-late-not-send.rs
@@ -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();
+ }
+ }
+}
diff --git a/examples/lm3s6965/examples/task.rs b/examples/lm3s6965/examples/task.rs
new file mode 100644
index 0000000..b6b6bbd
--- /dev/null
+++ b/examples/lm3s6965/examples/task.rs
@@ -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");
+ }
+}
diff --git a/examples/lm3s6965/examples/zero-prio-task.rs b/examples/lm3s6965/examples/zero-prio-task.rs
new file mode 100644
index 0000000..8cfd705
--- /dev/null
+++ b/examples/lm3s6965/examples/zero-prio-task.rs
@@ -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
+ }
+}