diff options
Diffstat (limited to 'examples/hifive1')
| -rw-r--r-- | examples/hifive1/.cargo/config.toml | 11 | ||||
| -rw-r--r-- | examples/hifive1/Cargo.lock | 364 | ||||
| -rw-r--r-- | examples/hifive1/Cargo.toml | 22 | ||||
| -rw-r--r-- | examples/hifive1/examples/prio_inheritance.rs | 140 | ||||
| -rw-r--r-- | examples/hifive1/examples/static.rs | 60 | ||||
| -rw-r--r-- | examples/hifive1/examples/task.rs | 57 | ||||
| -rw-r--r-- | examples/hifive1/examples/zero_prio_task.rs | 61 | ||||
| -rw-r--r-- | examples/hifive1/rust-toolchain.toml | 4 |
8 files changed, 719 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" ] |
