diff options
Diffstat (limited to 'examples/lm3s6965')
52 files changed, 3339 insertions, 0 deletions
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 + } +} |
