From 9a4f97ca5ebf19e6612115db5c763d0d61dd28a1 Mon Sep 17 00:00:00 2001 From: Per Lindgren Date: Sat, 7 Jan 2023 17:59:39 +0100 Subject: more examples --- Cargo.toml | 11 +-- examples/async-delay.no_rs | 63 ++++++++++++++++ examples/async-delay.rs | 67 ----------------- examples/async-infinite-loop.no_rs | 53 +++++++++++++ examples/async-infinite-loop.rs | 57 -------------- examples/async-task-multiple-prios.rs | 73 +++++++++++------- examples/async-task.rs | 6 +- examples/async-timeout.no_rs | 87 ++++++++++++++++++++++ examples/async-timeout.rs | 87 ---------------------- examples/big-struct-opt.rs | 34 +++++++-- examples/binds.rs | 4 +- examples/cancel-reschedule.no_rs | 73 ++++++++++++++++++ examples/cancel-reschedule.rs | 73 ------------------ examples/capacity.no_rs | 49 ++++++++++++ examples/capacity.rs | 49 ------------ examples/cfg-whole-task.no_rs | 94 +++++++++++++++++++++++ examples/cfg-whole-task.rs | 94 ----------------------- examples/common.no_rs | 102 +++++++++++++++++++++++++ examples/common.rs | 102 ------------------------- examples/complex.rs | 3 +- examples/declared_locals.rs | 8 +- examples/destructure.rs | 11 +-- examples/extern_binds.rs | 4 +- examples/extern_spawn.rs | 19 +++-- examples/generics.rs | 4 +- examples/hardware.rs | 4 +- examples/not-sync.rs | 32 +++++--- examples/only-shared-access.rs | 9 ++- examples/periodic-at.no_rs | 49 ++++++++++++ examples/periodic-at.rs | 49 ------------ examples/periodic-at2.no_rs | 61 +++++++++++++++ examples/periodic-at2.rs | 61 --------------- examples/periodic.no_rs | 48 ++++++++++++ examples/periodic.rs | 48 ------------ examples/peripherals-taken.rs | 4 +- examples/pool.no_rs | 70 +++++++++++++++++ examples/pool.rs | 70 ----------------- examples/preempt.rs | 11 +-- examples/ramfunc.rs | 10 +-- examples/resource-user-struct.rs | 4 +- examples/schedule.no_rs | 64 ++++++++++++++++ examples/schedule.rs | 64 ---------------- examples/shared.rs | 4 +- examples/smallest.rs | 4 +- examples/spawn.rs | 7 +- examples/static.rs | 7 +- examples/t-binds.rs | 4 +- examples/t-cfg-resources.rs | 3 +- examples/t-htask-main.rs | 4 +- examples/t-idle-main.rs | 4 +- examples/t-late-not-send.rs | 3 +- examples/t-schedule.no_rs | 136 ++++++++++++++++++++++++++++++++++ examples/t-schedule.rs | 136 ---------------------------------- examples/t-spawn.no_rs | 69 +++++++++++++++++ examples/t-spawn.rs | 68 ----------------- examples/task.rs | 11 +-- 56 files changed, 1193 insertions(+), 1152 deletions(-) create mode 100644 examples/async-delay.no_rs delete mode 100644 examples/async-delay.rs create mode 100644 examples/async-infinite-loop.no_rs delete mode 100644 examples/async-infinite-loop.rs create mode 100644 examples/async-timeout.no_rs delete mode 100644 examples/async-timeout.rs create mode 100644 examples/cancel-reschedule.no_rs delete mode 100644 examples/cancel-reschedule.rs create mode 100644 examples/capacity.no_rs delete mode 100644 examples/capacity.rs create mode 100644 examples/cfg-whole-task.no_rs delete mode 100644 examples/cfg-whole-task.rs create mode 100644 examples/common.no_rs delete mode 100644 examples/common.rs create mode 100644 examples/periodic-at.no_rs delete mode 100644 examples/periodic-at.rs create mode 100644 examples/periodic-at2.no_rs delete mode 100644 examples/periodic-at2.rs create mode 100644 examples/periodic.no_rs delete mode 100644 examples/periodic.rs create mode 100644 examples/pool.no_rs delete mode 100644 examples/pool.rs create mode 100644 examples/schedule.no_rs delete mode 100644 examples/schedule.rs create mode 100644 examples/t-schedule.no_rs delete mode 100644 examples/t-schedule.rs create mode 100644 examples/t-spawn.no_rs delete mode 100644 examples/t-spawn.rs diff --git a/Cargo.toml b/Cargo.toml index d995de4..cad9291 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,10 +49,7 @@ codegen-units = 1 lto = true [workspace] -members = [ - "macros", - "xtask", -] +members = ["macros", "xtask"] # do not optimize proc-macro deps or build scripts [profile.dev.build-override] @@ -76,6 +73,6 @@ lm3s6965 = { git = "https://github.com/japaric/lm3s6965" } [features] test-critical-section = ["cortex-m/critical-section-single-core"] -[[example]] -name = "pool" -required-features = ["test-critical-section"] +# [[example]] +# name = "pool" +# required-features = ["test-critical-section"] diff --git a/examples/async-delay.no_rs b/examples/async-delay.no_rs new file mode 100644 index 0000000..fb478c3 --- /dev/null +++ b/examples/async-delay.no_rs @@ -0,0 +1,63 @@ +#![no_main] +#![no_std] +#![feature(type_alias_impl_trait)] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; + + #[init] + fn init(cx: init::Context) -> (Shared, Local) { + hprintln!("init").unwrap(); + + foo::spawn().ok(); + bar::spawn().ok(); + baz::spawn().ok(); + + (Shared {}, Local {}) + } + + #[idle] + fn idle(_: idle::Context) -> ! { + // debug::exit(debug::EXIT_SUCCESS); + loop { + // hprintln!("idle"); + cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs + } + } + + #[task] + async fn foo(_cx: foo::Context) { + hprintln!("hello from foo").ok(); + monotonics::delay(100.millis()).await; + hprintln!("bye from foo").ok(); + } + + #[task] + async fn bar(_cx: bar::Context) { + hprintln!("hello from bar").ok(); + monotonics::delay(200.millis()).await; + hprintln!("bye from bar").ok(); + } + + #[task] + async fn baz(_cx: baz::Context) { + hprintln!("hello from baz").ok(); + monotonics::delay(300.millis()).await; + hprintln!("bye from baz").ok(); + + debug::exit(debug::EXIT_SUCCESS); + } +} diff --git a/examples/async-delay.rs b/examples/async-delay.rs deleted file mode 100644 index 7802bda..0000000 --- a/examples/async-delay.rs +++ /dev/null @@ -1,67 +0,0 @@ -#![no_main] -#![no_std] -#![feature(type_alias_impl_trait)] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - hprintln!("init").unwrap(); - - foo::spawn().ok(); - bar::spawn().ok(); - baz::spawn().ok(); - - ( - Shared {}, - Local {}, - init::Monotonics(Systick::new(cx.core.SYST, 12_000_000)), - ) - } - - #[idle] - fn idle(_: idle::Context) -> ! { - // debug::exit(debug::EXIT_SUCCESS); - loop { - // hprintln!("idle"); - cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs - } - } - - #[task] - async fn foo(_cx: foo::Context) { - hprintln!("hello from foo").ok(); - monotonics::delay(100.millis()).await; - hprintln!("bye from foo").ok(); - } - - #[task] - async fn bar(_cx: bar::Context) { - hprintln!("hello from bar").ok(); - monotonics::delay(200.millis()).await; - hprintln!("bye from bar").ok(); - } - - #[task] - async fn baz(_cx: baz::Context) { - hprintln!("hello from baz").ok(); - monotonics::delay(300.millis()).await; - hprintln!("bye from baz").ok(); - - debug::exit(debug::EXIT_SUCCESS); - } -} diff --git a/examples/async-infinite-loop.no_rs b/examples/async-infinite-loop.no_rs new file mode 100644 index 0000000..a95f998 --- /dev/null +++ b/examples/async-infinite-loop.no_rs @@ -0,0 +1,53 @@ +#![no_main] +#![no_std] +#![feature(type_alias_impl_trait)] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; + + #[init] + fn init(cx: init::Context) -> (Shared, Local) { + hprintln!("init").unwrap(); + + foo::spawn().ok(); + + (Shared {}, Local {}) + } + + #[idle] + fn idle(_: idle::Context) -> ! { + loop { + cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs + } + } + + // Infinite loops are not allowed in RTIC, however in async tasks they are - if there is an + // await inside the loop. + #[task] + async fn foo(_cx: foo::Context) { + let mut i = 0; + loop { + if i == 5 { + debug::exit(debug::EXIT_SUCCESS); + } + + hprintln!("hello from async {}", i).ok(); + monotonics::delay(100.millis()).await; // This makes it okey! + + i += 1; + } + } +} diff --git a/examples/async-infinite-loop.rs b/examples/async-infinite-loop.rs deleted file mode 100644 index 7615818..0000000 --- a/examples/async-infinite-loop.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![no_main] -#![no_std] -#![feature(type_alias_impl_trait)] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - hprintln!("init").unwrap(); - - foo::spawn().ok(); - - ( - Shared {}, - Local {}, - init::Monotonics(Systick::new(cx.core.SYST, 12_000_000)), - ) - } - - #[idle] - fn idle(_: idle::Context) -> ! { - loop { - cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs - } - } - - // Infinite loops are not allowed in RTIC, however in async tasks they are - if there is an - // await inside the loop. - #[task] - async fn foo(_cx: foo::Context) { - let mut i = 0; - loop { - if i == 5 { - debug::exit(debug::EXIT_SUCCESS); - } - - hprintln!("hello from async {}", i).ok(); - monotonics::delay(100.millis()).await; // This makes it okey! - - i += 1; - } - } -} diff --git a/examples/async-task-multiple-prios.rs b/examples/async-task-multiple-prios.rs index 3e19798..2f3a0f7 100644 --- a/examples/async-task-multiple-prios.rs +++ b/examples/async-task-multiple-prios.rs @@ -6,14 +6,13 @@ use panic_semihosting as _; // NOTES: // -// - Async tasks cannot have `#[lock_free]` resources, as they can interleve and each async +// - 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, UART0, UART1], peripherals = true)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; #[shared] struct Shared { @@ -24,53 +23,71 @@ mod app { #[local] struct Local {} - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(cx: init::Context) -> (Shared, Local) { hprintln!("init").unwrap(); - normal_task::spawn().ok(); - async_task::spawn().ok(); - normal_task2::spawn().ok(); + async_task1::spawn().ok(); async_task2::spawn().ok(); + async_task3::spawn().ok(); + async_task4::spawn().ok(); - ( - Shared { a: 0, b: 0 }, - Local {}, - init::Monotonics(Systick::new(cx.core.SYST, 12_000_000)), - ) + (Shared { a: 0, b: 0 }, Local {}) } #[idle] fn idle(_: idle::Context) -> ! { - // debug::exit(debug::EXIT_SUCCESS); loop { - // hprintln!("idle"); - cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs + hprintln!("idle"); + debug::exit(debug::EXIT_SUCCESS); } } #[task(priority = 1, shared = [a, b])] - fn normal_task(_cx: normal_task::Context) { - hprintln!("hello from normal 1").ok(); + async fn async_task1(mut cx: async_task1::Context) { + hprintln!( + "hello from async 1 a {}", + cx.shared.a.lock(|a| { + *a += 1; + *a + }) + ) + .ok(); } #[task(priority = 1, shared = [a, b])] - async fn async_task(_cx: async_task::Context) { - hprintln!("hello from async 1").ok(); - - debug::exit(debug::EXIT_SUCCESS); + async fn async_task2(mut cx: async_task2::Context) { + hprintln!( + "hello from async 2 a {}", + cx.shared.a.lock(|a| { + *a += 1; + *a + }) + ) + .ok(); } #[task(priority = 2, shared = [a, b])] - fn normal_task2(_cx: normal_task2::Context) { - hprintln!("hello from normal 2").ok(); + async fn async_task3(mut cx: async_task3::Context) { + hprintln!( + "hello from async 3 a {}", + cx.shared.a.lock(|a| { + *a += 1; + *a + }) + ) + .ok(); } #[task(priority = 2, shared = [a, b])] - async fn async_task2(_cx: async_task2::Context) { - hprintln!("hello from async 2").ok(); + async fn async_task4(mut cx: async_task4::Context) { + hprintln!( + "hello from async 4 a {}", + cx.shared.a.lock(|a| { + *a += 1; + *a + }) + ) + .ok(); } } diff --git a/examples/async-task.rs b/examples/async-task.rs index 012e95e..210a865 100644 --- a/examples/async-task.rs +++ b/examples/async-task.rs @@ -34,9 +34,9 @@ mod app { #[idle(shared = [a])] fn idle(_: idle::Context) -> ! { - // debug::exit(debug::EXIT_SUCCESS); loop { - // hprintln!("idle"); + hprintln!("idle"); + debug::exit(debug::EXIT_SUCCESS); cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs } } @@ -51,8 +51,6 @@ mod app { async fn async_task(cx: async_task::Context) { let async_task::SharedResources { a: _, .. } = cx.shared; hprintln!("hello from async").ok(); - - debug::exit(debug::EXIT_SUCCESS); } #[task(priority = 2, shared = [a])] diff --git a/examples/async-timeout.no_rs b/examples/async-timeout.no_rs new file mode 100644 index 0000000..3f68df7 --- /dev/null +++ b/examples/async-timeout.no_rs @@ -0,0 +1,87 @@ +#![no_main] +#![no_std] +#![feature(type_alias_impl_trait)] + +use panic_semihosting as _; + +// NOTES: +// +// - Async tasks cannot have `#[lock_free]` resources, as they can interleve 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 core::{ + future::Future, + pin::Pin, + task::{Context, Poll}, + }; + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + hprintln!("init").unwrap(); + + foo::spawn().ok(); + bar::spawn().ok(); + + ( + Shared {}, + Local {}, + init::Monotonics(Systick::new(cx.core.SYST, 12_000_000)), + ) + } + + #[idle] + fn idle(_: idle::Context) -> ! { + loop { + cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs + } + } + + #[task] + async fn foo(_cx: foo::Context) { + hprintln!("hello from foo").ok(); + + // This will not timeout + match monotonics::timeout_after(monotonics::delay(100.millis()), 200.millis()).await { + Ok(_) => hprintln!("foo no timeout").ok(), + Err(_) => hprintln!("foo timeout").ok(), + }; + } + + #[task] + async fn bar(_cx: bar::Context) { + hprintln!("hello from bar").ok(); + + // This will timeout + match monotonics::timeout_after(NeverEndingFuture {}, 300.millis()).await { + Ok(_) => hprintln!("bar no timeout").ok(), + Err(_) => hprintln!("bar timeout").ok(), + }; + + debug::exit(debug::EXIT_SUCCESS); + } + + pub struct NeverEndingFuture {} + + impl Future for NeverEndingFuture { + type Output = (); + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + // Never finish + Poll::Pending + } + } +} diff --git a/examples/async-timeout.rs b/examples/async-timeout.rs deleted file mode 100644 index 3f68df7..0000000 --- a/examples/async-timeout.rs +++ /dev/null @@ -1,87 +0,0 @@ -#![no_main] -#![no_std] -#![feature(type_alias_impl_trait)] - -use panic_semihosting as _; - -// NOTES: -// -// - Async tasks cannot have `#[lock_free]` resources, as they can interleve 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 core::{ - future::Future, - pin::Pin, - task::{Context, Poll}, - }; - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - hprintln!("init").unwrap(); - - foo::spawn().ok(); - bar::spawn().ok(); - - ( - Shared {}, - Local {}, - init::Monotonics(Systick::new(cx.core.SYST, 12_000_000)), - ) - } - - #[idle] - fn idle(_: idle::Context) -> ! { - loop { - cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs - } - } - - #[task] - async fn foo(_cx: foo::Context) { - hprintln!("hello from foo").ok(); - - // This will not timeout - match monotonics::timeout_after(monotonics::delay(100.millis()), 200.millis()).await { - Ok(_) => hprintln!("foo no timeout").ok(), - Err(_) => hprintln!("foo timeout").ok(), - }; - } - - #[task] - async fn bar(_cx: bar::Context) { - hprintln!("hello from bar").ok(); - - // This will timeout - match monotonics::timeout_after(NeverEndingFuture {}, 300.millis()).await { - Ok(_) => hprintln!("bar no timeout").ok(), - Err(_) => hprintln!("bar timeout").ok(), - }; - - debug::exit(debug::EXIT_SUCCESS); - } - - pub struct NeverEndingFuture {} - - impl Future for NeverEndingFuture { - type Output = (); - - fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { - // Never finish - Poll::Pending - } - } -} diff --git a/examples/big-struct-opt.rs b/examples/big-struct-opt.rs index bbc2535..4bf93b2 100644 --- a/examples/big-struct-opt.rs +++ b/examples/big-struct-opt.rs @@ -5,6 +5,7 @@ #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use panic_semihosting as _; @@ -20,11 +21,12 @@ impl BigStruct { } } -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use super::BigStruct; use core::mem::MaybeUninit; - use cortex_m_semihosting::debug; + use cortex_m_semihosting::{debug, hprintln}; + use lm3s6965::Interrupt; #[shared] struct Shared { @@ -35,25 +37,43 @@ mod app { struct Local {} #[init(local = [bs: MaybeUninit = MaybeUninit::uninit()])] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + 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() }; - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - + rtic::pend(Interrupt::UART0); + async_task::spawn().unwrap(); ( Shared { // assign the reference so we can use the resource big_struct, }, Local {}, - init::Monotonics(), ) } + #[idle] + fn idle(_: idle::Context) -> ! { + loop { + hprintln!("idle"); + debug::exit(debug::EXIT_SUCCESS); + } + } + #[task(binds = UART0, shared = [big_struct])] - fn task(_: task::Context) {} + fn uart0(mut cx: uart0::Context) { + cx.shared + .big_struct + .lock(|b| hprintln!("uart0 data:{:?}", &b.data[0..5]).unwrap()); + } + + #[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]).unwrap()); + } } diff --git a/examples/binds.rs b/examples/binds.rs index 56565cb..ec25ccc 100644 --- a/examples/binds.rs +++ b/examples/binds.rs @@ -20,12 +20,12 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { rtic::pend(Interrupt::UART0); hprintln!("init").unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[idle] diff --git a/examples/cancel-reschedule.no_rs b/examples/cancel-reschedule.no_rs new file mode 100644 index 0000000..a38a9c4 --- /dev/null +++ b/examples/cancel-reschedule.no_rs @@ -0,0 +1,73 @@ +//! examples/cancel-reschedule.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let systick = cx.core.SYST; + + // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) + let mono = Systick::new(systick, 12_000_000); + + hprintln!("init").ok(); + + // Schedule `foo` to run 1 second in the future + foo::spawn_after(1.secs()).unwrap(); + + ( + Shared {}, + Local {}, + init::Monotonics(mono), // Give the monotonic to RTIC + ) + } + + #[task] + fn foo(_: foo::Context) { + hprintln!("foo").ok(); + + // Schedule `bar` to run 2 seconds in the future (1 second after foo runs) + let spawn_handle = baz::spawn_after(2.secs()).unwrap(); + bar::spawn_after(1.secs(), spawn_handle, false).unwrap(); // Change to true + } + + #[task] + fn bar(_: bar::Context, baz_handle: baz::SpawnHandle, do_reschedule: bool) { + hprintln!("bar").ok(); + + if do_reschedule { + // Reschedule baz 2 seconds from now, instead of the original 1 second + // from now. + baz_handle.reschedule_after(2.secs()).unwrap(); + // Or baz_handle.reschedule_at(/* time */) + } else { + // Or cancel it + baz_handle.cancel().unwrap(); + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + } + } + + #[task] + fn baz(_: baz::Context) { + hprintln!("baz").ok(); + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + } +} diff --git a/examples/cancel-reschedule.rs b/examples/cancel-reschedule.rs deleted file mode 100644 index a38a9c4..0000000 --- a/examples/cancel-reschedule.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! examples/cancel-reschedule.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let systick = cx.core.SYST; - - // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) - let mono = Systick::new(systick, 12_000_000); - - hprintln!("init").ok(); - - // Schedule `foo` to run 1 second in the future - foo::spawn_after(1.secs()).unwrap(); - - ( - Shared {}, - Local {}, - init::Monotonics(mono), // Give the monotonic to RTIC - ) - } - - #[task] - fn foo(_: foo::Context) { - hprintln!("foo").ok(); - - // Schedule `bar` to run 2 seconds in the future (1 second after foo runs) - let spawn_handle = baz::spawn_after(2.secs()).unwrap(); - bar::spawn_after(1.secs(), spawn_handle, false).unwrap(); // Change to true - } - - #[task] - fn bar(_: bar::Context, baz_handle: baz::SpawnHandle, do_reschedule: bool) { - hprintln!("bar").ok(); - - if do_reschedule { - // Reschedule baz 2 seconds from now, instead of the original 1 second - // from now. - baz_handle.reschedule_after(2.secs()).unwrap(); - // Or baz_handle.reschedule_at(/* time */) - } else { - // Or cancel it - baz_handle.cancel().unwrap(); - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } - } - - #[task] - fn baz(_: baz::Context) { - hprintln!("baz").ok(); - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } -} diff --git a/examples/capacity.no_rs b/examples/capacity.no_rs new file mode 100644 index 0000000..a617269 --- /dev/null +++ b/examples/capacity.no_rs @@ -0,0 +1,49 @@ +//! examples/capacity.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use lm3s6965::Interrupt; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + rtic::pend(Interrupt::UART0); + + (Shared {}, Local {}, init::Monotonics()) + } + + #[task(binds = UART0)] + fn uart0(_: uart0::Context) { + foo::spawn(0).unwrap(); + foo::spawn(1).unwrap(); + foo::spawn(2).unwrap(); + foo::spawn(3).unwrap(); + + bar::spawn().unwrap(); + } + + #[task(capacity = 4)] + fn foo(_: foo::Context, x: u32) { + hprintln!("foo({})", x).unwrap(); + } + + #[task] + fn bar(_: bar::Context) { + hprintln!("bar").unwrap(); + + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + } +} diff --git a/examples/capacity.rs b/examples/capacity.rs deleted file mode 100644 index a617269..0000000 --- a/examples/capacity.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! examples/capacity.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use lm3s6965::Interrupt; - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - rtic::pend(Interrupt::UART0); - - (Shared {}, Local {}, init::Monotonics()) - } - - #[task(binds = UART0)] - fn uart0(_: uart0::Context) { - foo::spawn(0).unwrap(); - foo::spawn(1).unwrap(); - foo::spawn(2).unwrap(); - foo::spawn(3).unwrap(); - - bar::spawn().unwrap(); - } - - #[task(capacity = 4)] - fn foo(_: foo::Context, x: u32) { - hprintln!("foo({})", x).unwrap(); - } - - #[task] - fn bar(_: bar::Context) { - hprintln!("bar").unwrap(); - - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } -} diff --git a/examples/cfg-whole-task.no_rs b/examples/cfg-whole-task.no_rs new file mode 100644 index 0000000..f41866d --- /dev/null +++ b/examples/cfg-whole-task.no_rs @@ -0,0 +1,94 @@ +//! examples/cfg-whole-task.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] +mod app { + use cortex_m_semihosting::debug; + #[cfg(debug_assertions)] + use cortex_m_semihosting::hprintln; + + #[shared] + struct Shared { + count: u32, + #[cfg(never)] + unused: u32, + } + + #[local] + struct Local {} + + #[init] + fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + foo::spawn().unwrap(); + foo::spawn().unwrap(); + + ( + Shared { + count: 0, + #[cfg(never)] + unused: 1, + }, + Local {}, + init::Monotonics(), + ) + } + + #[idle] + fn idle(_: idle::Context) -> ! { + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + + loop { + cortex_m::asm::nop(); + } + } + + #[task(capacity = 2, shared = [count])] + fn foo(mut _cx: foo::Context) { + #[cfg(debug_assertions)] + { + _cx.shared.count.lock(|count| *count += 1); + + log::spawn(_cx.shared.count.lock(|count| *count)).unwrap(); + } + + // this wouldn't compile in `release` mode + // *_cx.shared.count += 1; + + // .. + } + + // The whole task should disappear, + // currently still present in the Tasks enum + #[cfg(never)] + #[task(capacity = 2, shared = [count])] + fn foo2(mut _cx: foo2::Context) { + #[cfg(debug_assertions)] + { + _cx.shared.count.lock(|count| *count += 10); + + log::spawn(_cx.shared.count.lock(|count| *count)).unwrap(); + } + + // this wouldn't compile in `release` mode + // *_cx.shared.count += 1; + + // .. + } + + #[cfg(debug_assertions)] + #[task(capacity = 2)] + fn log(_: log::Context, n: u32) { + hprintln!( + "foo has been called {} time{}", + n, + if n == 1 { "" } else { "s" } + ) + .ok(); + } +} diff --git a/examples/cfg-whole-task.rs b/examples/cfg-whole-task.rs deleted file mode 100644 index f41866d..0000000 --- a/examples/cfg-whole-task.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! examples/cfg-whole-task.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] -mod app { - use cortex_m_semihosting::debug; - #[cfg(debug_assertions)] - use cortex_m_semihosting::hprintln; - - #[shared] - struct Shared { - count: u32, - #[cfg(never)] - unused: u32, - } - - #[local] - struct Local {} - - #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - foo::spawn().unwrap(); - foo::spawn().unwrap(); - - ( - Shared { - count: 0, - #[cfg(never)] - unused: 1, - }, - Local {}, - init::Monotonics(), - ) - } - - #[idle] - fn idle(_: idle::Context) -> ! { - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - - loop { - cortex_m::asm::nop(); - } - } - - #[task(capacity = 2, shared = [count])] - fn foo(mut _cx: foo::Context) { - #[cfg(debug_assertions)] - { - _cx.shared.count.lock(|count| *count += 1); - - log::spawn(_cx.shared.count.lock(|count| *count)).unwrap(); - } - - // this wouldn't compile in `release` mode - // *_cx.shared.count += 1; - - // .. - } - - // The whole task should disappear, - // currently still present in the Tasks enum - #[cfg(never)] - #[task(capacity = 2, shared = [count])] - fn foo2(mut _cx: foo2::Context) { - #[cfg(debug_assertions)] - { - _cx.shared.count.lock(|count| *count += 10); - - log::spawn(_cx.shared.count.lock(|count| *count)).unwrap(); - } - - // this wouldn't compile in `release` mode - // *_cx.shared.count += 1; - - // .. - } - - #[cfg(debug_assertions)] - #[task(capacity = 2)] - fn log(_: log::Context, n: u32) { - hprintln!( - "foo has been called {} time{}", - n, - if n == 1 { "" } else { "s" } - ) - .ok(); - } -} diff --git a/examples/common.no_rs b/examples/common.no_rs new file mode 100644 index 0000000..1fe671e --- /dev/null +++ b/examples/common.no_rs @@ -0,0 +1,102 @@ +//! examples/common.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; // Implements the `Monotonic` trait + + // A monotonic timer to enable scheduling in RTIC + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity + + // Resources shared between tasks + #[shared] + struct Shared { + s1: u32, + s2: i32, + } + + // Local resources to specific tasks (cannot be shared) + #[local] + struct Local { + l1: u8, + l2: i8, + } + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let systick = cx.core.SYST; + + // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) + let mono = Systick::new(systick, 12_000_000); + + // Spawn the task `foo` directly after `init` finishes + foo::spawn().unwrap(); + + // Spawn the task `bar` 1 second after `init` finishes, this is enabled + // by the `#[monotonic(..)]` above + bar::spawn_after(1.secs()).unwrap(); + + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + + ( + // Initialization of shared resources + Shared { s1: 0, s2: 1 }, + // Initialization of task local resources + Local { l1: 2, l2: 3 }, + // Move the monotonic timer to the RTIC run-time, this enables + // scheduling + init::Monotonics(mono), + ) + } + + // Background task, runs whenever no other tasks are running + #[idle] + fn idle(_: idle::Context) -> ! { + loop { + continue; + } + } + + // Software task, not bound to a hardware interrupt. + // This task takes the task local resource `l1` + // The resources `s1` and `s2` are shared between all other tasks. + #[task(shared = [s1, s2], local = [l1])] + fn foo(_: foo::Context) { + // This task is only spawned once in `init`, hence this task will run + // only once + + hprintln!("foo").ok(); + } + + // Software task, also not bound to a hardware interrupt + // This task takes the task local resource `l2` + // The resources `s1` and `s2` are shared between all other tasks. + #[task(shared = [s1, s2], local = [l2])] + fn bar(_: bar::Context) { + hprintln!("bar").ok(); + + // Run `bar` once per second + bar::spawn_after(1.secs()).unwrap(); + } + + // Hardware task, bound to a hardware interrupt + // The resources `s1` and `s2` are shared between all other tasks. + #[task(binds = UART0, priority = 3, shared = [s1, s2])] + fn uart0_interrupt(_: uart0_interrupt::Context) { + // This task is bound to the interrupt `UART0` and will run + // whenever the interrupt fires + + // Note that RTIC does NOT clear the interrupt flag, this is up to the + // user + + hprintln!("UART0 interrupt!").ok(); + } +} diff --git a/examples/common.rs b/examples/common.rs deleted file mode 100644 index 1fe671e..0000000 --- a/examples/common.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! examples/common.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; // Implements the `Monotonic` trait - - // A monotonic timer to enable scheduling in RTIC - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - - // Resources shared between tasks - #[shared] - struct Shared { - s1: u32, - s2: i32, - } - - // Local resources to specific tasks (cannot be shared) - #[local] - struct Local { - l1: u8, - l2: i8, - } - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let systick = cx.core.SYST; - - // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) - let mono = Systick::new(systick, 12_000_000); - - // Spawn the task `foo` directly after `init` finishes - foo::spawn().unwrap(); - - // Spawn the task `bar` 1 second after `init` finishes, this is enabled - // by the `#[monotonic(..)]` above - bar::spawn_after(1.secs()).unwrap(); - - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - - ( - // Initialization of shared resources - Shared { s1: 0, s2: 1 }, - // Initialization of task local resources - Local { l1: 2, l2: 3 }, - // Move the monotonic timer to the RTIC run-time, this enables - // scheduling - init::Monotonics(mono), - ) - } - - // Background task, runs whenever no other tasks are running - #[idle] - fn idle(_: idle::Context) -> ! { - loop { - continue; - } - } - - // Software task, not bound to a hardware interrupt. - // This task takes the task local resource `l1` - // The resources `s1` and `s2` are shared between all other tasks. - #[task(shared = [s1, s2], local = [l1])] - fn foo(_: foo::Context) { - // This task is only spawned once in `init`, hence this task will run - // only once - - hprintln!("foo").ok(); - } - - // Software task, also not bound to a hardware interrupt - // This task takes the task local resource `l2` - // The resources `s1` and `s2` are shared between all other tasks. - #[task(shared = [s1, s2], local = [l2])] - fn bar(_: bar::Context) { - hprintln!("bar").ok(); - - // Run `bar` once per second - bar::spawn_after(1.secs()).unwrap(); - } - - // Hardware task, bound to a hardware interrupt - // The resources `s1` and `s2` are shared between all other tasks. - #[task(binds = UART0, priority = 3, shared = [s1, s2])] - fn uart0_interrupt(_: uart0_interrupt::Context) { - // This task is bound to the interrupt `UART0` and will run - // whenever the interrupt fires - - // Note that RTIC does NOT clear the interrupt flag, this is up to the - // user - - hprintln!("UART0 interrupt!").ok(); - } -} diff --git a/examples/complex.rs b/examples/complex.rs index e5cf6db..df9c862 100644 --- a/examples/complex.rs +++ b/examples/complex.rs @@ -24,7 +24,7 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { hprintln!("init").unwrap(); ( @@ -34,7 +34,6 @@ mod app { s4: 0, }, Local {}, - init::Monotonics(), ) } diff --git a/examples/declared_locals.rs b/examples/declared_locals.rs index 52d354b..79001aa 100644 --- a/examples/declared_locals.rs +++ b/examples/declared_locals.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965, dispatchers = [UART0])] +#[rtic::app(device = lm3s6965)] mod app { use cortex_m_semihosting::debug; @@ -18,13 +18,13 @@ mod app { struct Local {} #[init(local = [a: u32 = 0])] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + 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 {}, init::Monotonics()) + (Shared {}, Local {}) } #[idle(local = [a: u32 = 0])] @@ -35,7 +35,7 @@ mod app { loop {} } - #[task(local = [a: u32 = 0])] + #[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; diff --git a/examples/destructure.rs b/examples/destructure.rs index 6019c22..89336bf 100644 --- a/examples/destructure.rs +++ b/examples/destructure.rs @@ -4,6 +4,7 @@ #![deny(warnings)] #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use panic_semihosting as _; @@ -22,11 +23,11 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { foo::spawn().unwrap(); bar::spawn().unwrap(); - (Shared { a: 0, b: 0, c: 0 }, Local {}, init::Monotonics()) + (Shared { a: 0, b: 1, c: 2 }, Local {}) } #[idle] @@ -37,7 +38,7 @@ mod app { // Direct destructure #[task(shared = [&a, &b, &c])] - fn foo(cx: foo::Context) { + async fn foo(cx: foo::Context) { let a = cx.shared.a; let b = cx.shared.b; let c = cx.shared.c; @@ -47,8 +48,8 @@ mod app { // De-structure-ing syntax #[task(shared = [&a, &b, &c])] - fn bar(cx: bar::Context) { - let bar::SharedResources { a, b, c } = cx.shared; + async fn bar(cx: bar::Context) { + let bar::SharedResources { a, b, c, .. } = cx.shared; hprintln!("bar: a = {}, b = {}, c = {}", a, b, c).unwrap(); } diff --git a/examples/extern_binds.rs b/examples/extern_binds.rs index 4dc6633..c9fc108 100644 --- a/examples/extern_binds.rs +++ b/examples/extern_binds.rs @@ -26,12 +26,12 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { rtic::pend(Interrupt::UART0); hprintln!("init").unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[idle] diff --git a/examples/extern_spawn.rs b/examples/extern_spawn.rs index 7f9b5a5..2d9d7b6 100644 --- a/examples/extern_spawn.rs +++ b/examples/extern_spawn.rs @@ -4,17 +4,16 @@ #![deny(warnings)] #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use cortex_m_semihosting::{debug, hprintln}; use panic_semihosting as _; // Free function implementing the spawnable task `foo`. -fn foo(_c: app::foo::Context, x: i32, y: u32) { - hprintln!("foo {}, {}", x, y).unwrap(); - if x == 2 { - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } - app::foo::spawn(2, 3).unwrap(); +// Notice, you need to indicate an anonymous lifetime <'a_> +async fn foo(_c: app::foo::Context<'_>) { + hprintln!("foo").unwrap(); + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator } #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] @@ -28,14 +27,14 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - foo::spawn(1, 2).unwrap(); + fn init(_: init::Context) -> (Shared, Local) { + foo::spawn().unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } extern "Rust" { #[task()] - fn foo(_c: foo::Context, _x: i32, _y: u32); + async fn foo(_c: foo::Context); } } diff --git a/examples/generics.rs b/examples/generics.rs index 72b861b..a73b00f 100644 --- a/examples/generics.rs +++ b/examples/generics.rs @@ -23,11 +23,11 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { rtic::pend(Interrupt::UART0); rtic::pend(Interrupt::UART1); - (Shared { shared: 0 }, Local {}, init::Monotonics()) + (Shared { shared: 0 }, Local {}) } #[task(binds = UART0, shared = [shared], local = [state: u32 = 0])] diff --git a/examples/hardware.rs b/examples/hardware.rs index 6063224..8e4f423 100644 --- a/examples/hardware.rs +++ b/examples/hardware.rs @@ -19,14 +19,14 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + 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").unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[idle] diff --git a/examples/not-sync.rs b/examples/not-sync.rs index aa79ad5..eb5c9f8 100644 --- a/examples/not-sync.rs +++ b/examples/not-sync.rs @@ -4,12 +4,14 @@ #![deny(warnings)] #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use core::marker::PhantomData; use panic_semihosting as _; pub struct NotSync { _0: PhantomData<*const ()>, + data: u32, } unsafe impl Send for NotSync {} @@ -18,7 +20,7 @@ unsafe impl Send for NotSync {} mod app { use super::NotSync; use core::marker::PhantomData; - use cortex_m_semihosting::debug; + use cortex_m_semihosting::{debug, hprintln}; #[shared] struct Shared { @@ -29,25 +31,37 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + fn init(_: init::Context) -> (Shared, Local) { + hprintln!("init").unwrap(); + foo::spawn().unwrap(); + bar::spawn().unwrap(); ( Shared { - shared: NotSync { _0: PhantomData }, + shared: NotSync { + _0: PhantomData, + data: 13, + }, }, Local {}, - init::Monotonics(), ) } + #[idle] + fn idle(_: idle::Context) -> ! { + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + loop {} + } + #[task(shared = [&shared])] - fn foo(c: foo::Context) { - let _: &NotSync = c.shared.shared; + async fn foo(c: foo::Context) { + let shared: &NotSync = c.shared.shared; + hprintln!("foo a {}", shared.data).unwrap(); } #[task(shared = [&shared])] - fn bar(c: bar::Context) { - let _: &NotSync = c.shared.shared; + async fn bar(c: bar::Context) { + let shared: &NotSync = c.shared.shared; + hprintln!("foo a {}", shared.data).unwrap(); } } diff --git a/examples/only-shared-access.rs b/examples/only-shared-access.rs index 8b0a77e..b506e44 100644 --- a/examples/only-shared-access.rs +++ b/examples/only-shared-access.rs @@ -4,6 +4,7 @@ #![deny(warnings)] #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use panic_semihosting as _; @@ -20,15 +21,15 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { foo::spawn().unwrap(); bar::spawn().unwrap(); - (Shared { key: 0xdeadbeef }, Local {}, init::Monotonics()) + (Shared { key: 0xdeadbeef }, Local {}) } #[task(shared = [&key])] - fn foo(cx: foo::Context) { + async fn foo(cx: foo::Context) { let key: &u32 = cx.shared.key; hprintln!("foo(key = {:#x})", key).unwrap(); @@ -36,7 +37,7 @@ mod app { } #[task(priority = 2, shared = [&key])] - fn bar(cx: bar::Context) { + async fn bar(cx: bar::Context) { hprintln!("bar(key = {:#x})", cx.shared.key).unwrap(); } } diff --git a/examples/periodic-at.no_rs b/examples/periodic-at.no_rs new file mode 100644 index 0000000..ca68ed5 --- /dev/null +++ b/examples/periodic-at.no_rs @@ -0,0 +1,49 @@ +//! examples/periodic-at.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let systick = cx.core.SYST; + + // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) + let mut mono = Systick::new(systick, 12_000_000); + + foo::spawn_after(1.secs(), mono.now()).unwrap(); + + (Shared {}, Local {}, init::Monotonics(mono)) + } + + #[task(local = [cnt: u32 = 0])] + fn foo(cx: foo::Context, instant: fugit::TimerInstantU64<100>) { + hprintln!("foo {:?}", instant).ok(); + *cx.local.cnt += 1; + + if *cx.local.cnt == 4 { + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + } + + // Periodic every 100 milliseconds + let next_instant = instant + 100.millis(); + foo::spawn_at(next_instant, next_instant).unwrap(); + } +} diff --git a/examples/periodic-at.rs b/examples/periodic-at.rs deleted file mode 100644 index ca68ed5..0000000 --- a/examples/periodic-at.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! examples/periodic-at.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let systick = cx.core.SYST; - - // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) - let mut mono = Systick::new(systick, 12_000_000); - - foo::spawn_after(1.secs(), mono.now()).unwrap(); - - (Shared {}, Local {}, init::Monotonics(mono)) - } - - #[task(local = [cnt: u32 = 0])] - fn foo(cx: foo::Context, instant: fugit::TimerInstantU64<100>) { - hprintln!("foo {:?}", instant).ok(); - *cx.local.cnt += 1; - - if *cx.local.cnt == 4 { - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } - - // Periodic every 100 milliseconds - let next_instant = instant + 100.millis(); - foo::spawn_at(next_instant, next_instant).unwrap(); - } -} diff --git a/examples/periodic-at2.no_rs b/examples/periodic-at2.no_rs new file mode 100644 index 0000000..ec9adcc --- /dev/null +++ b/examples/periodic-at2.no_rs @@ -0,0 +1,61 @@ +//! examples/periodic-at2.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let systick = cx.core.SYST; + + // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) + let mut mono = Systick::new(systick, 12_000_000); + + foo::spawn_after(200.millis(), mono.now()).unwrap(); + + (Shared {}, Local {}, init::Monotonics(mono)) + } + + // Using the explicit type of the timer implementation + #[task(local = [cnt: u32 = 0])] + fn foo(cx: foo::Context, instant: fugit::TimerInstantU64<100>) { + hprintln!("foo {:?}", instant).ok(); + *cx.local.cnt += 1; + + if *cx.local.cnt == 4 { + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + } + + // Spawn a new message with 100 ms offset to spawned time + let next_instant = instant + 100.millis(); + bar::spawn_at(next_instant, next_instant).unwrap(); + } + + // Using the Instant from the Monotonic trait + // This remains agnostic to the timer implementation + #[task(local = [cnt: u32 = 0])] + fn bar(_cx: bar::Context, instant: ::Instant) { + hprintln!("bar {:?}", instant).ok(); + + // Spawn a new message with 200ms offset to spawned time + let next_instant = instant + 200.millis(); + foo::spawn_at(next_instant, next_instant).unwrap(); + } +} diff --git a/examples/periodic-at2.rs b/examples/periodic-at2.rs deleted file mode 100644 index ec9adcc..0000000 --- a/examples/periodic-at2.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! examples/periodic-at2.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let systick = cx.core.SYST; - - // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) - let mut mono = Systick::new(systick, 12_000_000); - - foo::spawn_after(200.millis(), mono.now()).unwrap(); - - (Shared {}, Local {}, init::Monotonics(mono)) - } - - // Using the explicit type of the timer implementation - #[task(local = [cnt: u32 = 0])] - fn foo(cx: foo::Context, instant: fugit::TimerInstantU64<100>) { - hprintln!("foo {:?}", instant).ok(); - *cx.local.cnt += 1; - - if *cx.local.cnt == 4 { - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } - - // Spawn a new message with 100 ms offset to spawned time - let next_instant = instant + 100.millis(); - bar::spawn_at(next_instant, next_instant).unwrap(); - } - - // Using the Instant from the Monotonic trait - // This remains agnostic to the timer implementation - #[task(local = [cnt: u32 = 0])] - fn bar(_cx: bar::Context, instant: ::Instant) { - hprintln!("bar {:?}", instant).ok(); - - // Spawn a new message with 200ms offset to spawned time - let next_instant = instant + 200.millis(); - foo::spawn_at(next_instant, next_instant).unwrap(); - } -} diff --git a/examples/periodic.no_rs b/examples/periodic.no_rs new file mode 100644 index 0000000..2f9e8e6 --- /dev/null +++ b/examples/periodic.no_rs @@ -0,0 +1,48 @@ +//! examples/periodic.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let systick = cx.core.SYST; + + // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) + let mono = Systick::new(systick, 12_000_000); + + foo::spawn_after(100.millis()).unwrap(); + + (Shared {}, Local {}, init::Monotonics(mono)) + } + + #[task(local = [cnt: u32 = 0])] + fn foo(cx: foo::Context) { + hprintln!("foo").ok(); + *cx.local.cnt += 1; + + if *cx.local.cnt == 4 { + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + } + + // Periodic every 100ms + foo::spawn_after(100.millis()).unwrap(); + } +} diff --git a/examples/periodic.rs b/examples/periodic.rs deleted file mode 100644 index 2f9e8e6..0000000 --- a/examples/periodic.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! examples/periodic.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let systick = cx.core.SYST; - - // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) - let mono = Systick::new(systick, 12_000_000); - - foo::spawn_after(100.millis()).unwrap(); - - (Shared {}, Local {}, init::Monotonics(mono)) - } - - #[task(local = [cnt: u32 = 0])] - fn foo(cx: foo::Context) { - hprintln!("foo").ok(); - *cx.local.cnt += 1; - - if *cx.local.cnt == 4 { - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } - - // Periodic every 100ms - foo::spawn_after(100.millis()).unwrap(); - } -} diff --git a/examples/peripherals-taken.rs b/examples/peripherals-taken.rs index d542c0e..9b01466 100644 --- a/examples/peripherals-taken.rs +++ b/examples/peripherals-taken.rs @@ -16,10 +16,10 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { assert!(cortex_m::Peripherals::take().is_none()); debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } } diff --git a/examples/pool.no_rs b/examples/pool.no_rs new file mode 100644 index 0000000..fb8589a --- /dev/null +++ b/examples/pool.no_rs @@ -0,0 +1,70 @@ +//! examples/pool.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +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)] + async 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

) { + // 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

) { + // this is done automatically so we can omit the call to `drop` + // drop(_x); + } +} diff --git a/examples/pool.rs b/examples/pool.rs deleted file mode 100644 index 5aadd24..0000000 --- a/examples/pool.rs +++ /dev/null @@ -1,70 +0,0 @@ -//! examples/pool.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -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, init::Monotonics) { - // Increase the capacity of the memory pool by ~4 - P::grow(cx.local.memory); - - rtic::pend(Interrupt::I2C0); - - (Shared {}, Local {}, init::Monotonics()) - } - - #[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] - fn foo(_: foo::Context, _x: Box

) { - // explicitly return the block to the pool - drop(_x); - - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } - - #[task(priority = 2)] - fn bar(_: bar::Context, _x: Box

) { - // this is done automatically so we can omit the call to `drop` - // drop(x); - } -} diff --git a/examples/preempt.rs b/examples/preempt.rs index d0c8cc7..aad9125 100644 --- a/examples/preempt.rs +++ b/examples/preempt.rs @@ -2,6 +2,7 @@ #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use panic_semihosting as _; use rtic::app; @@ -17,14 +18,14 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { foo::spawn().unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[task(priority = 1)] - fn foo(_: foo::Context) { + async fn foo(_: foo::Context) { hprintln!("foo - start").unwrap(); baz::spawn().unwrap(); hprintln!("foo - end").unwrap(); @@ -32,12 +33,12 @@ mod app { } #[task(priority = 2)] - fn bar(_: bar::Context) { + async fn bar(_: bar::Context) { hprintln!(" bar").unwrap(); } #[task(priority = 2)] - fn baz(_: baz::Context) { + async fn baz(_: baz::Context) { hprintln!(" baz - start").unwrap(); bar::spawn().unwrap(); hprintln!(" baz - end").unwrap(); diff --git a/examples/ramfunc.rs b/examples/ramfunc.rs index b3b8012..dd1f76e 100644 --- a/examples/ramfunc.rs +++ b/examples/ramfunc.rs @@ -3,7 +3,7 @@ #![deny(warnings)] #![no_main] #![no_std] - +#![feature(type_alias_impl_trait)] use panic_semihosting as _; #[rtic::app( @@ -24,15 +24,15 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { foo::spawn().unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[inline(never)] #[task] - fn foo(_: foo::Context) { + async fn foo(_: foo::Context) { hprintln!("foo").unwrap(); debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator @@ -42,7 +42,7 @@ mod app { #[inline(never)] #[link_section = ".data.bar"] #[task(priority = 2)] - fn bar(_: bar::Context) { + async fn bar(_: bar::Context) { foo::spawn().unwrap(); } } diff --git a/examples/resource-user-struct.rs b/examples/resource-user-struct.rs index ae1918d..a4478ce 100644 --- a/examples/resource-user-struct.rs +++ b/examples/resource-user-struct.rs @@ -29,11 +29,11 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { rtic::pend(Interrupt::UART0); rtic::pend(Interrupt::UART1); - (Shared { shared: 0 }, Local {}, init::Monotonics()) + (Shared { shared: 0 }, Local {}) } // `shared` cannot be accessed from this context diff --git a/examples/schedule.no_rs b/examples/schedule.no_rs new file mode 100644 index 0000000..5bad5a3 --- /dev/null +++ b/examples/schedule.no_rs @@ -0,0 +1,64 @@ +//! examples/schedule.rs + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::{debug, hprintln}; + use systick_monotonic::*; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let systick = cx.core.SYST; + + // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) + let mono = Systick::new(systick, 12_000_000); + + hprintln!("init").ok(); + + // Schedule `foo` to run 1 second in the future + foo::spawn_after(1.secs()).unwrap(); + + ( + Shared {}, + Local {}, + init::Monotonics(mono), // Give the monotonic to RTIC + ) + } + + #[task] + fn foo(_: foo::Context) { + hprintln!("foo").ok(); + + // Schedule `bar` to run 2 seconds in the future (1 second after foo runs) + bar::spawn_after(1.secs()).unwrap(); + } + + #[task] + fn bar(_: bar::Context) { + hprintln!("bar").ok(); + + // Schedule `baz` to run 1 seconds from now, but with a specific time instant. + baz::spawn_at(monotonics::now() + 1.secs()).unwrap(); + } + + #[task] + fn baz(_: baz::Context) { + hprintln!("baz").ok(); + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + } +} diff --git a/examples/schedule.rs b/examples/schedule.rs deleted file mode 100644 index 5bad5a3..0000000 --- a/examples/schedule.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! examples/schedule.rs - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::{debug, hprintln}; - use systick_monotonic::*; - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let systick = cx.core.SYST; - - // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) - let mono = Systick::new(systick, 12_000_000); - - hprintln!("init").ok(); - - // Schedule `foo` to run 1 second in the future - foo::spawn_after(1.secs()).unwrap(); - - ( - Shared {}, - Local {}, - init::Monotonics(mono), // Give the monotonic to RTIC - ) - } - - #[task] - fn foo(_: foo::Context) { - hprintln!("foo").ok(); - - // Schedule `bar` to run 2 seconds in the future (1 second after foo runs) - bar::spawn_after(1.secs()).unwrap(); - } - - #[task] - fn bar(_: bar::Context) { - hprintln!("bar").ok(); - - // Schedule `baz` to run 1 seconds from now, but with a specific time instant. - baz::spawn_at(monotonics::now() + 1.secs()).unwrap(); - } - - #[task] - fn baz(_: baz::Context) { - hprintln!("baz").ok(); - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - } -} diff --git a/examples/shared.rs b/examples/shared.rs index d87dca5..fdc1b1c 100644 --- a/examples/shared.rs +++ b/examples/shared.rs @@ -23,11 +23,11 @@ mod app { struct Local {} #[init(local = [q: Queue = Queue::new()])] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(cx: init::Context) -> (Shared, Local) { let (p, c) = cx.local.q.split(); // Initialization of shared resources - (Shared { p, c }, Local {}, init::Monotonics()) + (Shared { p, c }, Local {}) } #[idle(shared = [c])] diff --git a/examples/smallest.rs b/examples/smallest.rs index b121fcf..5071392 100644 --- a/examples/smallest.rs +++ b/examples/smallest.rs @@ -17,8 +17,8 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } } diff --git a/examples/spawn.rs b/examples/spawn.rs index 2db1ab8..266ace8 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -4,6 +4,7 @@ #![deny(warnings)] #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use panic_semihosting as _; @@ -18,15 +19,15 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { hprintln!("init").unwrap(); foo::spawn().unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[task] - fn foo(_: foo::Context) { + async fn foo(_: foo::Context) { hprintln!("foo").unwrap(); debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator diff --git a/examples/static.rs b/examples/static.rs index c9aa604..9c981db 100644 --- a/examples/static.rs +++ b/examples/static.rs @@ -4,6 +4,7 @@ #![deny(warnings)] #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use panic_semihosting as _; @@ -22,14 +23,14 @@ mod app { } #[init(local = [q: Queue = Queue::new()])] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + 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 }, init::Monotonics()) + (Shared {}, Local { p, c }) } #[idle(local = [c])] @@ -50,7 +51,7 @@ mod app { } #[task(local = [p, state: u32 = 0])] - fn foo(c: foo::Context) { + async fn foo(c: foo::Context) { *c.local.state += 1; // Lock-free access to the same underlying queue! diff --git a/examples/t-binds.rs b/examples/t-binds.rs index 12479c0..785348b 100644 --- a/examples/t-binds.rs +++ b/examples/t-binds.rs @@ -18,10 +18,10 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } // Cortex-M exception diff --git a/examples/t-cfg-resources.rs b/examples/t-cfg-resources.rs index 99c97ba..0174f33 100644 --- a/examples/t-cfg-resources.rs +++ b/examples/t-cfg-resources.rs @@ -20,7 +20,7 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator ( @@ -29,7 +29,6 @@ mod app { x: 0, }, Local {}, - init::Monotonics(), ) } diff --git a/examples/t-htask-main.rs b/examples/t-htask-main.rs index 37189fa..0595e9f 100644 --- a/examples/t-htask-main.rs +++ b/examples/t-htask-main.rs @@ -16,10 +16,10 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { rtic::pend(lm3s6965::Interrupt::UART0); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[task(binds = UART0)] diff --git a/examples/t-idle-main.rs b/examples/t-idle-main.rs index 1adc9bf..307ccb2 100644 --- a/examples/t-idle-main.rs +++ b/examples/t-idle-main.rs @@ -16,8 +16,8 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - (Shared {}, Local {}, init::Monotonics()) + fn init(_: init::Context) -> (Shared, Local) { + (Shared {}, Local {}) } #[idle] diff --git a/examples/t-late-not-send.rs b/examples/t-late-not-send.rs index 06aedaa..0fbf237 100644 --- a/examples/t-late-not-send.rs +++ b/examples/t-late-not-send.rs @@ -27,14 +27,13 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { ( Shared { x: NotSend { _0: PhantomData }, y: None, }, Local {}, - init::Monotonics(), ) } diff --git a/examples/t-schedule.no_rs b/examples/t-schedule.no_rs new file mode 100644 index 0000000..5ec4208 --- /dev/null +++ b/examples/t-schedule.no_rs @@ -0,0 +1,136 @@ +//! [compile-pass] Check `schedule` code generation + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::debug; + use systick_monotonic::*; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + let systick = cx.core.SYST; + + // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) + let mono = Systick::new(systick, 12_000_000); + + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + + (Shared {}, Local {}, init::Monotonics(mono)) + } + + #[idle] + fn idle(_: idle::Context) -> ! { + // Task without message passing + + // Not default + let _: Result = + foo::MyMono::spawn_at(monotonics::MyMono::now()); + let handle: Result = foo::MyMono::spawn_after(1.secs()); + let _: Result = handle.unwrap().reschedule_after(1.secs()); + + let handle: Result = foo::MyMono::spawn_after(1.secs()); + let _: Result = + handle.unwrap().reschedule_at(monotonics::MyMono::now()); + + let handle: Result = foo::MyMono::spawn_after(1.secs()); + let _: Result<(), ()> = handle.unwrap().cancel(); + + // Using default + let _: Result = foo::spawn_at(monotonics::now()); + let handle: Result = foo::spawn_after(1.secs()); + let _: Result = handle.unwrap().reschedule_after(1.secs()); + + let handle: Result = foo::spawn_after(1.secs()); + let _: Result = + handle.unwrap().reschedule_at(monotonics::MyMono::now()); + + let handle: Result = foo::spawn_after(1.secs()); + let _: Result<(), ()> = handle.unwrap().cancel(); + + // Task with single message passing + + // Not default + let _: Result = + bar::MyMono::spawn_at(monotonics::MyMono::now(), 0); + let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); + let _: Result = handle.unwrap().reschedule_after(1.secs()); + + let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); + let _: Result = + handle.unwrap().reschedule_at(monotonics::MyMono::now()); + + let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); + let _: Result = handle.unwrap().cancel(); + + // Using default + let _: Result = bar::spawn_at(monotonics::MyMono::now(), 0); + let handle: Result = bar::spawn_after(1.secs(), 1); + let _: Result = handle.unwrap().reschedule_after(1.secs()); + + let handle: Result = bar::spawn_after(1.secs(), 1); + let _: Result = + handle.unwrap().reschedule_at(monotonics::MyMono::now()); + + let handle: Result = bar::spawn_after(1.secs(), 1); + let _: Result = handle.unwrap().cancel(); + + // Task with multiple message passing + + // Not default + let _: Result = + baz::MyMono::spawn_at(monotonics::MyMono::now(), 0, 1); + let handle: Result = + baz::MyMono::spawn_after(1.secs(), 1, 2); + let _: Result = handle.unwrap().reschedule_after(1.secs()); + + let handle: Result = + baz::MyMono::spawn_after(1.secs(), 1, 2); + let _: Result = + handle.unwrap().reschedule_at(monotonics::MyMono::now()); + + let handle: Result = + baz::MyMono::spawn_after(1.secs(), 1, 2); + let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); + + // Using default + let _: Result = + baz::spawn_at(monotonics::MyMono::now(), 0, 1); + let handle: Result = baz::spawn_after(1.secs(), 1, 2); + let _: Result = handle.unwrap().reschedule_after(1.secs()); + + let handle: Result = baz::spawn_after(1.secs(), 1, 2); + let _: Result = + handle.unwrap().reschedule_at(monotonics::MyMono::now()); + + let handle: Result = baz::spawn_after(1.secs(), 1, 2); + let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); + + loop { + cortex_m::asm::nop(); + } + } + + #[task] + fn foo(_: foo::Context) {} + + #[task] + fn bar(_: bar::Context, _x: u32) {} + + #[task] + fn baz(_: baz::Context, _x: u32, _y: u32) {} +} diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs deleted file mode 100644 index 5ec4208..0000000 --- a/examples/t-schedule.rs +++ /dev/null @@ -1,136 +0,0 @@ -//! [compile-pass] Check `schedule` code generation - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::debug; - use systick_monotonic::*; - - #[monotonic(binds = SysTick, default = true)] - type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { - let systick = cx.core.SYST; - - // Initialize the monotonic (SysTick rate in QEMU is 12 MHz) - let mono = Systick::new(systick, 12_000_000); - - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - - (Shared {}, Local {}, init::Monotonics(mono)) - } - - #[idle] - fn idle(_: idle::Context) -> ! { - // Task without message passing - - // Not default - let _: Result = - foo::MyMono::spawn_at(monotonics::MyMono::now()); - let handle: Result = foo::MyMono::spawn_after(1.secs()); - let _: Result = handle.unwrap().reschedule_after(1.secs()); - - let handle: Result = foo::MyMono::spawn_after(1.secs()); - let _: Result = - handle.unwrap().reschedule_at(monotonics::MyMono::now()); - - let handle: Result = foo::MyMono::spawn_after(1.secs()); - let _: Result<(), ()> = handle.unwrap().cancel(); - - // Using default - let _: Result = foo::spawn_at(monotonics::now()); - let handle: Result = foo::spawn_after(1.secs()); - let _: Result = handle.unwrap().reschedule_after(1.secs()); - - let handle: Result = foo::spawn_after(1.secs()); - let _: Result = - handle.unwrap().reschedule_at(monotonics::MyMono::now()); - - let handle: Result = foo::spawn_after(1.secs()); - let _: Result<(), ()> = handle.unwrap().cancel(); - - // Task with single message passing - - // Not default - let _: Result = - bar::MyMono::spawn_at(monotonics::MyMono::now(), 0); - let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); - let _: Result = handle.unwrap().reschedule_after(1.secs()); - - let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); - let _: Result = - handle.unwrap().reschedule_at(monotonics::MyMono::now()); - - let handle: Result = bar::MyMono::spawn_after(1.secs(), 1); - let _: Result = handle.unwrap().cancel(); - - // Using default - let _: Result = bar::spawn_at(monotonics::MyMono::now(), 0); - let handle: Result = bar::spawn_after(1.secs(), 1); - let _: Result = handle.unwrap().reschedule_after(1.secs()); - - let handle: Result = bar::spawn_after(1.secs(), 1); - let _: Result = - handle.unwrap().reschedule_at(monotonics::MyMono::now()); - - let handle: Result = bar::spawn_after(1.secs(), 1); - let _: Result = handle.unwrap().cancel(); - - // Task with multiple message passing - - // Not default - let _: Result = - baz::MyMono::spawn_at(monotonics::MyMono::now(), 0, 1); - let handle: Result = - baz::MyMono::spawn_after(1.secs(), 1, 2); - let _: Result = handle.unwrap().reschedule_after(1.secs()); - - let handle: Result = - baz::MyMono::spawn_after(1.secs(), 1, 2); - let _: Result = - handle.unwrap().reschedule_at(monotonics::MyMono::now()); - - let handle: Result = - baz::MyMono::spawn_after(1.secs(), 1, 2); - let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); - - // Using default - let _: Result = - baz::spawn_at(monotonics::MyMono::now(), 0, 1); - let handle: Result = baz::spawn_after(1.secs(), 1, 2); - let _: Result = handle.unwrap().reschedule_after(1.secs()); - - let handle: Result = baz::spawn_after(1.secs(), 1, 2); - let _: Result = - handle.unwrap().reschedule_at(monotonics::MyMono::now()); - - let handle: Result = baz::spawn_after(1.secs(), 1, 2); - let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); - - loop { - cortex_m::asm::nop(); - } - } - - #[task] - fn foo(_: foo::Context) {} - - #[task] - fn bar(_: bar::Context, _x: u32) {} - - #[task] - fn baz(_: baz::Context, _x: u32, _y: u32) {} -} diff --git a/examples/t-spawn.no_rs b/examples/t-spawn.no_rs new file mode 100644 index 0000000..dad0c83 --- /dev/null +++ b/examples/t-spawn.no_rs @@ -0,0 +1,69 @@ +//! [compile-pass] Check code generation of `spawn` + +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] +#![feature(type_alias_impl_trait)] + +use panic_semihosting as _; + +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] +mod app { + use cortex_m_semihosting::debug; + + #[shared] + struct Shared {} + + #[local] + struct Local {} + + #[init] + fn init(_: init::Context) -> (Shared, Local) { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); + + debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator + + (Shared {}, Local {}) + } + + #[idle] + fn idle(_: idle::Context) -> ! { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); + + loop { + cortex_m::asm::nop(); + } + } + + #[task(binds = SVCall)] + fn svcall(_: svcall::Context) { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); + } + + #[task(binds = UART0)] + fn uart0(_: uart0::Context) { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); + } + + #[task] + async fn foo(_: foo::Context) { + let _: Result<(), ()> = foo::spawn(); + let _: Result<(), u32> = bar::spawn(0); + let _: Result<(), (u32, u32)> = baz::spawn(0, 1); + } + + #[task] + async fn bar(_: bar::Context, _x: u32) {} + + #[task] + async fn baz(_: baz::Context, _x: u32, _y: u32) {} +} diff --git a/examples/t-spawn.rs b/examples/t-spawn.rs deleted file mode 100644 index 2bd771d..0000000 --- a/examples/t-spawn.rs +++ /dev/null @@ -1,68 +0,0 @@ -//! [compile-pass] Check code generation of `spawn` - -#![deny(unsafe_code)] -#![deny(warnings)] -#![no_main] -#![no_std] - -use panic_semihosting as _; - -#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] -mod app { - use cortex_m_semihosting::debug; - - #[shared] - struct Shared {} - - #[local] - struct Local {} - - #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { - let _: Result<(), ()> = foo::spawn(); - let _: Result<(), u32> = bar::spawn(0); - let _: Result<(), (u32, u32)> = baz::spawn(0, 1); - - debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator - - (Shared {}, Local {}, init::Monotonics()) - } - - #[idle] - fn idle(_: idle::Context) -> ! { - let _: Result<(), ()> = foo::spawn(); - let _: Result<(), u32> = bar::spawn(0); - let _: Result<(), (u32, u32)> = baz::spawn(0, 1); - - loop { - cortex_m::asm::nop(); - } - } - - #[task(binds = SVCall)] - fn svcall(_: svcall::Context) { - let _: Result<(), ()> = foo::spawn(); - let _: Result<(), u32> = bar::spawn(0); - let _: Result<(), (u32, u32)> = baz::spawn(0, 1); - } - - #[task(binds = UART0)] - fn uart0(_: uart0::Context) { - let _: Result<(), ()> = foo::spawn(); - let _: Result<(), u32> = bar::spawn(0); - let _: Result<(), (u32, u32)> = baz::spawn(0, 1); - } - - #[task] - fn foo(_: foo::Context) { - let _: Result<(), ()> = foo::spawn(); - let _: Result<(), u32> = bar::spawn(0); - let _: Result<(), (u32, u32)> = baz::spawn(0, 1); - } - - #[task] - fn bar(_: bar::Context, _x: u32) {} - - #[task] - fn baz(_: baz::Context, _x: u32, _y: u32) {} -} diff --git a/examples/task.rs b/examples/task.rs index 2c53aa2..fe1408b 100644 --- a/examples/task.rs +++ b/examples/task.rs @@ -4,6 +4,7 @@ #![deny(warnings)] #![no_main] #![no_std] +#![feature(type_alias_impl_trait)] use panic_semihosting as _; @@ -18,14 +19,14 @@ mod app { struct Local {} #[init] - fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { + fn init(_: init::Context) -> (Shared, Local) { foo::spawn().unwrap(); - (Shared {}, Local {}, init::Monotonics()) + (Shared {}, Local {}) } #[task] - fn foo(_: foo::Context) { + async fn foo(_: foo::Context) { hprintln!("foo - start").unwrap(); // spawns `bar` onto the task scheduler @@ -43,14 +44,14 @@ mod app { } #[task] - fn bar(_: bar::Context) { + async fn bar(_: bar::Context) { hprintln!("bar").unwrap(); debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator } #[task(priority = 2)] - fn baz(_: baz::Context) { + async fn baz(_: baz::Context) { hprintln!("baz").unwrap(); } } -- cgit v1.2.3