mirror of
https://github.com/rtic-rs/rtic.git
synced 2025-12-16 21:05:35 +01:00
Add rtic-timer (timerqueue + monotonic) and rtic-monotonics (systick-monotonic)
This commit is contained in:
parent
b8b881f446
commit
306aa47170
276 changed files with 607 additions and 713 deletions
|
|
@ -1,63 +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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
//! examples/async-task-multiple-prios.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
// NOTES:
|
||||
//
|
||||
// - Async tasks cannot have `#[lock_free]` resources, as they can interleave and each async
|
||||
// task can have a mutable reference stored.
|
||||
// - Spawning an async task equates to it being polled once.
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
async_task1::spawn().ok();
|
||||
async_task2::spawn().ok();
|
||||
async_task3::spawn().ok();
|
||||
async_task4::spawn().ok();
|
||||
|
||||
(Shared { a: 0, b: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
hprintln!("idle");
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
#[task(priority = 1, shared = [a, b])]
|
||||
async fn async_task1(mut cx: async_task1::Context) {
|
||||
hprintln!(
|
||||
"hello from async 1 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += 1;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[task(priority = 1, shared = [a, b])]
|
||||
async fn async_task2(mut cx: async_task2::Context) {
|
||||
hprintln!(
|
||||
"hello from async 2 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += 1;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [a, b])]
|
||||
async fn async_task3(mut cx: async_task3::Context) {
|
||||
hprintln!(
|
||||
"hello from async 3 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += 1;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [a, b])]
|
||||
async fn async_task4(mut cx: async_task4::Context) {
|
||||
hprintln!(
|
||||
"hello from async 4 a {}",
|
||||
cx.shared.a.lock(|a| {
|
||||
*a += 1;
|
||||
*a
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
//! examples/async-task.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
// NOTES:
|
||||
//
|
||||
// - Async tasks cannot have `#[lock_free]` resources, as they can interleave and each async
|
||||
// task can have a mutable reference stored.
|
||||
// - Spawning an async task equates to it being polled once.
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
a: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
async_task::spawn().unwrap();
|
||||
async_task_args::spawn(1, 2).unwrap();
|
||||
async_task2::spawn().unwrap();
|
||||
|
||||
(Shared { a: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[idle(shared = [a])]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
hprintln!("idle");
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
cortex_m::asm::wfi(); // put the MCU in sleep mode until interrupt occurs
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART1, shared = [a])]
|
||||
fn hw_task(cx: hw_task::Context) {
|
||||
let hw_task::SharedResources { a: _, .. } = cx.shared;
|
||||
hprintln!("hello from hw");
|
||||
}
|
||||
|
||||
#[task(shared = [a])]
|
||||
async fn async_task(cx: async_task::Context) {
|
||||
let async_task::SharedResources { a: _, .. } = cx.shared;
|
||||
hprintln!("hello from async");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn async_task_args(_cx: async_task_args::Context, a: u32, b: i32) {
|
||||
hprintln!("hello from async with args a: {}, b: {}", a, b);
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [a])]
|
||||
async fn async_task2(cx: async_task2::Context) {
|
||||
let async_task2::SharedResources { a: _, .. } = cx.shared;
|
||||
hprintln!("hello from async2");
|
||||
}
|
||||
}
|
||||
|
|
@ -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<Self::Output> {
|
||||
// Never finish
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
//! examples/big-struct-opt.rs
|
||||
//!
|
||||
//! Example on how to initialize a large struct without needing to copy it via `LateResources`,
|
||||
//! effectively saving stack space needed for the copies.
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Some big struct
|
||||
pub struct BigStruct {
|
||||
/// Big content
|
||||
pub data: [u8; 2048],
|
||||
}
|
||||
|
||||
impl BigStruct {
|
||||
fn new() -> Self {
|
||||
BigStruct { data: [22; 2048] }
|
||||
}
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use super::BigStruct;
|
||||
use core::mem::MaybeUninit;
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
big_struct: &'static mut BigStruct,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [bs: MaybeUninit<BigStruct> = MaybeUninit::uninit()])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
let big_struct = unsafe {
|
||||
// write directly into the static storage
|
||||
cx.local.bs.as_mut_ptr().write(BigStruct::new());
|
||||
&mut *cx.local.bs.as_mut_ptr()
|
||||
};
|
||||
|
||||
rtic::pend(Interrupt::UART0);
|
||||
async_task::spawn().unwrap();
|
||||
(
|
||||
Shared {
|
||||
// assign the reference so we can use the resource
|
||||
big_struct,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
loop {
|
||||
hprintln!("idle");
|
||||
debug::exit(debug::EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, shared = [big_struct])]
|
||||
fn uart0(mut cx: uart0::Context) {
|
||||
cx.shared
|
||||
.big_struct
|
||||
.lock(|b| hprintln!("uart0 data:{:?}", &b.data[0..5]));
|
||||
}
|
||||
|
||||
#[task(shared = [big_struct], priority = 2)]
|
||||
async fn async_task(mut cx: async_task::Context) {
|
||||
cx.shared
|
||||
.big_struct
|
||||
.lock(|b| hprintln!("async_task data:{:?}", &b.data[0..5]));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
//! examples/binds.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
// `examples/interrupt.rs` rewritten to use `binds`
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
hprintln!("idle");
|
||||
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, local = [times: u32 = 0])]
|
||||
fn foo(cx: foo::Context) {
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"foo called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,121 +0,0 @@
|
|||
//! examples/cfg-monotonic.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![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
|
||||
#[cfg(feature = "killmono")]
|
||||
#[monotonic(binds = SysTick, default = true)]
|
||||
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
||||
|
||||
// Not allowed by current rtic-syntax:
|
||||
// error: `#[monotonic(...)]` on a specific type must appear at most once
|
||||
// --> examples/cfg-monotonic.rs:23:10
|
||||
// |
|
||||
// 23 | type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
||||
// | ^^^^^^
|
||||
// #[monotonic(binds = SysTick, default = true)]
|
||||
// type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
||||
|
||||
// Not allowed by current rtic-syntax:
|
||||
// error: this interrupt is already bound
|
||||
// --> examples/cfg-monotonic.rs:31:25
|
||||
// |
|
||||
// 31 | #[monotonic(binds = SysTick, default = true)]
|
||||
// | ^^^^^^^
|
||||
// #[monotonic(binds = SysTick, default = true)]
|
||||
// type MyMono2 = DwtSystick<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)
|
||||
#[cfg(feature = "killmono")]
|
||||
let mono = Systick::new(systick, 12_000_000);
|
||||
|
||||
// Spawn the task `foo` directly after `init` finishes
|
||||
foo::spawn().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
|
||||
#[cfg(feature = "killmono")]
|
||||
init::Monotonics(mono),
|
||||
init::Monotonics(),
|
||||
)
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
// 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");
|
||||
|
||||
// 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!");
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
//! examples/complex.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
s2: u32, // shared with ceiling 2
|
||||
s3: u32, // shared with ceiling 3
|
||||
s4: u32, // shared with ceiling 4
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
(
|
||||
Shared {
|
||||
s2: 0,
|
||||
s3: 0,
|
||||
s4: 0,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle(shared = [s2, s3])]
|
||||
fn idle(mut cx: idle::Context) -> ! {
|
||||
hprintln!("idle p0 started");
|
||||
rtic::pend(Interrupt::GPIOC);
|
||||
cx.shared.s3.lock(|s| {
|
||||
hprintln!("idle enter lock s3 {}", s);
|
||||
hprintln!("idle pend t0");
|
||||
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 3
|
||||
hprintln!("idle pend t1");
|
||||
rtic::pend(Interrupt::GPIOB); // t1 p3, with shared ceiling 3
|
||||
hprintln!("idle pend t2");
|
||||
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
|
||||
hprintln!("idle still in lock s3 {}", s);
|
||||
});
|
||||
hprintln!("\nback in idle");
|
||||
|
||||
cx.shared.s2.lock(|s| {
|
||||
hprintln!("enter lock s2 {}", s);
|
||||
hprintln!("idle pend t0");
|
||||
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 2
|
||||
hprintln!("idle pend t1");
|
||||
rtic::pend(Interrupt::GPIOB); // t1 p3, no sharing
|
||||
hprintln!("idle pend t2");
|
||||
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
|
||||
hprintln!("idle still in lock s2 {}", s);
|
||||
});
|
||||
hprintln!("\nidle exit");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = GPIOA, priority = 2, local = [times: u32 = 0], shared = [s2, s3])]
|
||||
fn t0(cx: t0::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"t0 p2 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
hprintln!("t0 p2 exit");
|
||||
}
|
||||
|
||||
#[task(binds = GPIOB, priority = 3, local = [times: u32 = 0], shared = [s3, s4])]
|
||||
fn t1(mut cx: t1::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"t1 p3 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
|
||||
cx.shared.s4.lock(|s| {
|
||||
hprintln!("t1 enter lock s4 {}", s);
|
||||
hprintln!("t1 pend t0");
|
||||
rtic::pend(Interrupt::GPIOA); // t0 p2, with shared ceiling 2
|
||||
hprintln!("t1 pend t2");
|
||||
rtic::pend(Interrupt::GPIOC); // t2 p4, no sharing
|
||||
hprintln!("t1 still in lock s4 {}", s);
|
||||
});
|
||||
|
||||
hprintln!("t1 p3 exit");
|
||||
}
|
||||
|
||||
#[task(binds = GPIOC, priority = 4, local = [times: u32 = 0], shared = [s4])]
|
||||
fn t2(mut cx: t2::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"t2 p4 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
|
||||
cx.shared.s4.lock(|s| {
|
||||
hprintln!("enter lock s4 {}", s);
|
||||
*s += 1;
|
||||
});
|
||||
hprintln!("t3 p4 exit");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
//! examples/declared_locals.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [a: u32 = 0])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// Locals in `#[init]` have 'static lifetime
|
||||
let _a: &'static mut u32 = cx.local.a;
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle(local = [a: u32 = 0])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
// Locals in `#[idle]` have 'static lifetime
|
||||
let _a: &'static mut u32 = cx.local.a;
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, local = [a: u32 = 0])]
|
||||
fn foo(cx: foo::Context) {
|
||||
// Locals in `#[task]`s have a local lifetime
|
||||
let _a: &mut u32 = cx.local.a;
|
||||
|
||||
// error: explicit lifetime required in the type of `cx`
|
||||
// let _a: &'static mut u32 = cx.local.a;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
//! examples/destructure.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
a: u32,
|
||||
b: u32,
|
||||
c: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
|
||||
(Shared { a: 0, b: 1, c: 2 }, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {}
|
||||
}
|
||||
|
||||
// Direct destructure
|
||||
#[task(shared = [&a, &b, &c])]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let a = cx.shared.a;
|
||||
let b = cx.shared.b;
|
||||
let c = cx.shared.c;
|
||||
|
||||
hprintln!("foo: a = {}, b = {}, c = {}", a, b, c);
|
||||
}
|
||||
|
||||
// De-structure-ing syntax
|
||||
#[task(shared = [&a, &b, &c])]
|
||||
async fn bar(cx: bar::Context) {
|
||||
let bar::SharedResources { a, b, c, .. } = cx.shared;
|
||||
|
||||
hprintln!("bar: a = {}, b = {}, c = {}", a, b, c);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
//! examples/extern_binds.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_semihosting::hprintln;
|
||||
use panic_semihosting as _;
|
||||
|
||||
// Free function implementing the interrupt bound task `foo`.
|
||||
fn foo(_: app::foo::Context) {
|
||||
hprintln!("foo called");
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use crate::foo;
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
hprintln!("idle");
|
||||
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
#[task(binds = UART0)]
|
||||
fn foo(_: foo::Context);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
//! examples/extern_spawn.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![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`.
|
||||
// Notice, you need to indicate an anonymous lifetime <'a_>
|
||||
async fn foo(_c: app::foo::Context<'_>) {
|
||||
hprintln!("foo");
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use crate::foo;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
#[task()]
|
||||
async fn foo(_c: foo::Context);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
//! examples/generics.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use cortex_m_semihosting::hprintln;
|
||||
use panic_semihosting as _;
|
||||
use rtic::Mutex;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
(Shared { shared: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[task(binds = UART0, shared = [shared], local = [state: u32 = 0])]
|
||||
fn uart0(c: uart0::Context) {
|
||||
hprintln!("UART0(STATE = {})", *c.local.state);
|
||||
|
||||
// second argument has type `shared::shared`
|
||||
super::advance(c.local.state, c.shared.shared);
|
||||
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(binds = UART1, priority = 2, shared = [shared], local = [state: u32 = 0])]
|
||||
fn uart1(c: uart1::Context) {
|
||||
hprintln!("UART1(STATE = {})", *c.local.state);
|
||||
|
||||
// second argument has type `shared::shared`
|
||||
super::advance(c.local.state, c.shared.shared);
|
||||
}
|
||||
}
|
||||
|
||||
// the second parameter is generic: it can be any type that implements the `Mutex` trait
|
||||
fn advance(state: &mut u32, mut shared: impl Mutex<T = u32>) {
|
||||
*state += 1;
|
||||
|
||||
let (old, new) = shared.lock(|shared: &mut u32| {
|
||||
let old = *shared;
|
||||
*shared += *state;
|
||||
(old, *shared)
|
||||
});
|
||||
|
||||
hprintln!("shared: {} -> {}", old, new);
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
//! examples/hardware.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
// Pends the UART0 interrupt but its handler won't run until *after*
|
||||
// `init` returns because interrupts are disabled
|
||||
rtic::pend(Interrupt::UART0); // equivalent to NVIC::pend
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
// interrupts are enabled again; the `UART0` handler runs at this point
|
||||
|
||||
hprintln!("idle");
|
||||
|
||||
rtic::pend(Interrupt::UART0);
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, local = [times: u32 = 0])]
|
||||
fn uart0(cx: uart0::Context) {
|
||||
// Safe access to local `static mut` variable
|
||||
*cx.local.times += 1;
|
||||
|
||||
hprintln!(
|
||||
"UART0 called {} time{}",
|
||||
*cx.local.times,
|
||||
if *cx.local.times > 1 { "s" } else { "" }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
//! examples/idle-wfi.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(mut cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
// Set the ARM SLEEPONEXIT bit to go to sleep after handling interrupts
|
||||
// See https://developer.arm.com/docs/100737/0100/power-management/sleep-mode/sleep-on-exit-bit
|
||||
cx.core.SCB.set_sleepdeep();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle(local = [x: u32 = 0])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
// Locals in idle have lifetime 'static
|
||||
let _x: &'static mut u32 = cx.local.x;
|
||||
|
||||
hprintln!("idle");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
loop {
|
||||
// Now Wait For Interrupt is used instead of a busy-wait loop
|
||||
// to allow MCU to sleep between interrupts
|
||||
// https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/WFI
|
||||
rtic::export::wfi()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
//! examples/idle.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle(local = [x: u32 = 0])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
// Locals in idle have lifetime 'static
|
||||
let _x: &'static mut u32 = cx.local.x;
|
||||
|
||||
hprintln!("idle");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
//! examples/init.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [x: u32 = 0])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// Cortex-M peripherals
|
||||
let _core: cortex_m::Peripherals = cx.core;
|
||||
|
||||
// Device specific peripherals
|
||||
let _device: lm3s6965::Peripherals = cx.device;
|
||||
|
||||
// Locals in `init` have 'static lifetime
|
||||
let _x: &'static mut u32 = cx.local.x;
|
||||
|
||||
// Access to the critical section token,
|
||||
// to indicate that this is a critical section
|
||||
let _cs_token: bare_metal::CriticalSection = cx.cs;
|
||||
|
||||
hprintln!("init");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
//! examples/locals.rs
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(missing_docs)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0, UART1])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
local_to_foo: i64,
|
||||
local_to_bar: i64,
|
||||
local_to_idle: i64,
|
||||
}
|
||||
|
||||
// `#[init]` cannot access locals from the `#[local]` struct as they are initialized here.
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {},
|
||||
// initial values for the `#[local]` resources
|
||||
Local {
|
||||
local_to_foo: 0,
|
||||
local_to_bar: 0,
|
||||
local_to_idle: 0,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// `local_to_idle` can only be accessed from this context
|
||||
#[idle(local = [local_to_idle])]
|
||||
fn idle(cx: idle::Context) -> ! {
|
||||
let local_to_idle = cx.local.local_to_idle;
|
||||
*local_to_idle += 1;
|
||||
|
||||
hprintln!("idle: local_to_idle = {}", local_to_idle);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
// error: no `local_to_foo` field in `idle::LocalResources`
|
||||
// _cx.local.local_to_foo += 1;
|
||||
|
||||
// error: no `local_to_bar` field in `idle::LocalResources`
|
||||
// _cx.local.local_to_bar += 1;
|
||||
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
|
||||
// `local_to_foo` can only be accessed from this context
|
||||
#[task(local = [local_to_foo])]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let local_to_foo = cx.local.local_to_foo;
|
||||
*local_to_foo += 1;
|
||||
|
||||
// error: no `local_to_bar` field in `foo::LocalResources`
|
||||
// cx.local.local_to_bar += 1;
|
||||
|
||||
hprintln!("foo: local_to_foo = {}", local_to_foo);
|
||||
}
|
||||
|
||||
// `local_to_bar` can only be accessed from this context
|
||||
#[task(local = [local_to_bar])]
|
||||
async fn bar(cx: bar::Context) {
|
||||
let local_to_bar = cx.local.local_to_bar;
|
||||
*local_to_bar += 1;
|
||||
|
||||
// error: no `local_to_foo` field in `bar::LocalResources`
|
||||
// cx.local.local_to_foo += 1;
|
||||
|
||||
hprintln!("bar: local_to_bar = {}", local_to_bar);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
//! examples/lock-free.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [GPIOA])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
#[lock_free] // <- lock-free shared resource
|
||||
counter: u64,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared { counter: 0 }, Local {})
|
||||
}
|
||||
|
||||
#[task(shared = [counter])] // <- same priority
|
||||
async fn foo(c: foo::Context) {
|
||||
bar::spawn().unwrap();
|
||||
|
||||
*c.shared.counter += 1; // <- no lock API required
|
||||
let counter = *c.shared.counter;
|
||||
hprintln!(" foo = {}", counter).unwrap();
|
||||
}
|
||||
|
||||
#[task(shared = [counter])] // <- same priority
|
||||
async fn bar(c: bar::Context) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
*c.shared.counter += 1; // <- no lock API required
|
||||
let counter = *c.shared.counter;
|
||||
hprintln!(" bar = {}", counter).unwrap();
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
//! examples/lock.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [GPIOA, GPIOB, GPIOC])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared { shared: 0 }, Local {})
|
||||
}
|
||||
|
||||
// when omitted priority is assumed to be `1`
|
||||
#[task(shared = [shared])]
|
||||
async fn foo(mut c: foo::Context) {
|
||||
hprintln!("A");
|
||||
|
||||
// the lower priority task requires a critical section to access the data
|
||||
c.shared.shared.lock(|shared| {
|
||||
// data can only be modified within this critical section (closure)
|
||||
*shared += 1;
|
||||
|
||||
// bar will *not* run right now due to the critical section
|
||||
bar::spawn().unwrap();
|
||||
|
||||
hprintln!("B - shared = {}", *shared);
|
||||
|
||||
// baz does not contend for `shared` so it's allowed to run now
|
||||
baz::spawn().unwrap();
|
||||
});
|
||||
|
||||
// critical section is over: bar can now start
|
||||
|
||||
hprintln!("E");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [shared])]
|
||||
async fn bar(mut c: bar::Context) {
|
||||
// the higher priority task does still need a critical section
|
||||
let shared = c.shared.shared.lock(|shared| {
|
||||
*shared += 1;
|
||||
|
||||
*shared
|
||||
});
|
||||
|
||||
hprintln!("D - shared = {}", shared);
|
||||
}
|
||||
|
||||
#[task(priority = 3)]
|
||||
async fn baz(_: baz::Context) {
|
||||
hprintln!("C");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
//! examples/message.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};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
|
||||
foo::spawn(/* no message */).unwrap();
|
||||
|
||||
(Shared {}, Local {}, init::Monotonics())
|
||||
}
|
||||
|
||||
#[task(local = [count: u32 = 0])]
|
||||
fn foo(cx: foo::Context) {
|
||||
hprintln!("foo").unwrap();
|
||||
|
||||
bar::spawn(*cx.local.count).unwrap();
|
||||
*cx.local.count += 1;
|
||||
}
|
||||
|
||||
#[task]
|
||||
fn bar(_: bar::Context, x: u32) {
|
||||
hprintln!("bar({})", x).unwrap();
|
||||
|
||||
baz::spawn(x + 1, x + 2).unwrap();
|
||||
}
|
||||
|
||||
#[task]
|
||||
fn baz(_: baz::Context, x: u32, y: u32) {
|
||||
hprintln!("baz({}, {})", x, y).unwrap();
|
||||
|
||||
if x + y > 4 {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
foo::spawn().unwrap();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
//! examples/message_passing.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};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local, init::Monotonics) {
|
||||
foo::spawn(1, 1).unwrap();
|
||||
foo::spawn(1, 2).unwrap();
|
||||
foo::spawn(2, 3).unwrap();
|
||||
assert!(foo::spawn(1, 4).is_err()); // The capacity of `foo` is reached
|
||||
|
||||
(Shared {}, Local {}, init::Monotonics())
|
||||
}
|
||||
|
||||
#[task(capacity = 3)]
|
||||
fn foo(_c: foo::Context, x: i32, y: u32) {
|
||||
hprintln!("foo {}, {}", x, y).unwrap();
|
||||
if x == 2 {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
//! examples/mutlilock.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [GPIOA])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared1: u32,
|
||||
shared2: u32,
|
||||
shared3: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
locks::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {
|
||||
shared1: 0,
|
||||
shared2: 0,
|
||||
shared3: 0,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
// when omitted priority is assumed to be `1`
|
||||
#[task(shared = [shared1, shared2, shared3])]
|
||||
async fn locks(c: locks::Context) {
|
||||
let s1 = c.shared.shared1;
|
||||
let s2 = c.shared.shared2;
|
||||
let s3 = c.shared.shared3;
|
||||
|
||||
(s1, s2, s3).lock(|s1, s2, s3| {
|
||||
*s1 += 1;
|
||||
*s2 += 1;
|
||||
*s3 += 1;
|
||||
|
||||
hprintln!("Multiple locks, s1: {}, s2: {}, s3: {}", *s1, *s2, *s3);
|
||||
});
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
//! `examples/not-sync.rs`
|
||||
|
||||
// #![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Not sync
|
||||
pub struct NotSync {
|
||||
_0: PhantomData<*const ()>,
|
||||
data: u32,
|
||||
}
|
||||
|
||||
unsafe impl Send for NotSync {}
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||
mod app {
|
||||
use super::NotSync;
|
||||
use core::marker::PhantomData;
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
shared: NotSync,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
(
|
||||
Shared {
|
||||
shared: NotSync {
|
||||
_0: PhantomData,
|
||||
data: 13,
|
||||
},
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[task(shared = [&shared])]
|
||||
async fn foo(c: foo::Context) {
|
||||
let shared: &NotSync = c.shared.shared;
|
||||
hprintln!("foo a {}", shared.data);
|
||||
}
|
||||
|
||||
#[task(shared = [&shared])]
|
||||
async fn bar(c: bar::Context) {
|
||||
let shared: &NotSync = c.shared.shared;
|
||||
hprintln!("bar a {}", shared.data);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
//! examples/only-shared-access.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0, UART1])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
key: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
bar::spawn().unwrap();
|
||||
|
||||
(Shared { key: 0xdeadbeef }, Local {})
|
||||
}
|
||||
|
||||
#[task(shared = [&key])]
|
||||
async fn foo(cx: foo::Context) {
|
||||
let key: &u32 = cx.shared.key;
|
||||
hprintln!("foo(key = {:#x})", key);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2, shared = [&key])]
|
||||
async fn bar(cx: bar::Context) {
|
||||
hprintln!("bar(key = {:#x})", cx.shared.key);
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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: <MyMono as rtic_monotonic::Monotonic>::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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
//! examples/peripherals-taken.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
assert!(cortex_m::Peripherals::take().is_none());
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
// 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<P>) {
|
||||
// explicitly return the block to the pool
|
||||
drop(_x);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn bar(_: bar::Context, _x: Box<P>) {
|
||||
// this is done automatically so we can omit the call to `drop`
|
||||
// drop(_x);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
//! examples/preempt.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
use rtic::app;
|
||||
|
||||
#[app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task(priority = 1)]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo - start");
|
||||
baz::spawn().unwrap();
|
||||
hprintln!("foo - end");
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn bar(_: bar::Context) {
|
||||
hprintln!(" bar");
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn baz(_: baz::Context) {
|
||||
hprintln!(" baz - start");
|
||||
bar::spawn().unwrap();
|
||||
hprintln!(" baz - end");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
//! examples/ramfunc.rs
|
||||
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(
|
||||
device = lm3s6965,
|
||||
dispatchers = [
|
||||
UART0,
|
||||
#[link_section = ".data.UART1"]
|
||||
UART1
|
||||
])
|
||||
]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
// run this task from RAM
|
||||
#[inline(never)]
|
||||
#[link_section = ".data.bar"]
|
||||
#[task(priority = 2)]
|
||||
async fn bar(_: bar::Context) {
|
||||
foo::spawn().unwrap();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
//! examples/resource.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
// A resource
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
// Should not collide with the struct above
|
||||
#[allow(dead_code)]
|
||||
struct Shared2 {
|
||||
// A resource
|
||||
shared: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
rtic::pend(Interrupt::UART1);
|
||||
|
||||
(Shared { shared: 0 }, Local {})
|
||||
}
|
||||
|
||||
// `shared` cannot be accessed from this context
|
||||
#[idle]
|
||||
fn idle(_cx: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
// error: no `shared` field in `idle::Context`
|
||||
// _cx.shared.shared += 1;
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
// `shared` can be accessed from this context
|
||||
#[task(binds = UART0, shared = [shared])]
|
||||
fn uart0(mut cx: uart0::Context) {
|
||||
let shared = cx.shared.shared.lock(|shared| {
|
||||
*shared += 1;
|
||||
*shared
|
||||
});
|
||||
|
||||
hprintln!("UART0: shared = {}", shared);
|
||||
}
|
||||
|
||||
// `shared` can be accessed from this context
|
||||
#[task(binds = UART1, shared = [shared])]
|
||||
fn uart1(mut cx: uart1::Context) {
|
||||
let shared = cx.shared.shared.lock(|shared| {
|
||||
*shared += 1;
|
||||
*shared
|
||||
});
|
||||
|
||||
hprintln!("UART1: shared = {}", shared);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
//! examples/late.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use heapless::spsc::{Consumer, Producer, Queue};
|
||||
use lm3s6965::Interrupt;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
p: Producer<'static, u32, 5>,
|
||||
c: Consumer<'static, u32, 5>,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init(local = [q: Queue<u32, 5> = Queue::new()])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
let (p, c) = cx.local.q.split();
|
||||
|
||||
// Initialization of shared resources
|
||||
(Shared { p, c }, Local {})
|
||||
}
|
||||
|
||||
#[idle(shared = [c])]
|
||||
fn idle(mut c: idle::Context) -> ! {
|
||||
loop {
|
||||
if let Some(byte) = c.shared.c.lock(|c| c.dequeue()) {
|
||||
hprintln!("received message: {}", byte);
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
} else {
|
||||
rtic::pend(Interrupt::UART0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[task(binds = UART0, shared = [p])]
|
||||
fn uart0(mut c: uart0::Context) {
|
||||
c.shared.p.lock(|p| p.enqueue(42).unwrap());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
//! examples/smallest.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _; // panic handler
|
||||
use rtic::app;
|
||||
|
||||
#[app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
//! examples/spawn.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![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, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
//! examples/static.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [UART0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
use heapless::spsc::{Consumer, Producer, Queue};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
p: Producer<'static, u32, 5>,
|
||||
c: Consumer<'static, u32, 5>,
|
||||
}
|
||||
|
||||
#[init(local = [q: Queue<u32, 5> = Queue::new()])]
|
||||
fn init(cx: init::Context) -> (Shared, Local) {
|
||||
// q has 'static life-time so after the split and return of `init`
|
||||
// it will continue to exist and be allocated
|
||||
let (p, c) = cx.local.q.split();
|
||||
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local { p, c })
|
||||
}
|
||||
|
||||
#[idle(local = [c])]
|
||||
fn idle(c: idle::Context) -> ! {
|
||||
loop {
|
||||
// Lock-free access to the same underlying queue!
|
||||
if let Some(data) = c.local.c.dequeue() {
|
||||
hprintln!("received message: {}", data);
|
||||
|
||||
// Run foo until data
|
||||
if data == 3 {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
} else {
|
||||
foo::spawn().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[task(local = [p, state: u32 = 0])]
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
//! [compile-pass] Check that `binds` works as advertised
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
// Cortex-M exception
|
||||
#[task(binds = SVCall)]
|
||||
fn foo(c: foo::Context) {
|
||||
crate::foo_trampoline(c)
|
||||
}
|
||||
|
||||
// LM3S6965 interrupt
|
||||
#[task(binds = UART0)]
|
||||
fn bar(c: bar::Context) {
|
||||
crate::bar_trampoline(c)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn foo_trampoline(_: app::foo::Context) {}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn bar_trampoline(_: app::bar::Context) {}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
//! [compile-pass] check that `#[cfg]` attributes applied on resources work
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
// A conditionally compiled resource behind feature_x
|
||||
#[cfg(feature = "feature_x")]
|
||||
x: u32,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
|
||||
(
|
||||
Shared {
|
||||
#[cfg(feature = "feature_x")]
|
||||
x: 0,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn idle(_cx: idle::Context) -> ! {
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
//! examples/h-task-main.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
rtic::pend(lm3s6965::Interrupt::UART0);
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task(binds = UART0)]
|
||||
fn taskmain(_: taskmain::Context) {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
//! examples/t-idle-main.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[idle]
|
||||
fn taskmain(_: taskmain::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
//! [compile-pass] shared resources don't need to be `Send` if they are owned by `idle`
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Not send
|
||||
pub struct NotSend {
|
||||
_0: PhantomData<*const ()>,
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965)]
|
||||
mod app {
|
||||
use super::NotSend;
|
||||
use core::marker::PhantomData;
|
||||
use cortex_m_semihosting::debug;
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
x: NotSend,
|
||||
y: Option<NotSend>,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
(
|
||||
Shared {
|
||||
x: NotSend { _0: PhantomData },
|
||||
y: None,
|
||||
},
|
||||
Local {},
|
||||
)
|
||||
}
|
||||
|
||||
#[idle(shared = [x, y])]
|
||||
fn idle(_: idle::Context) -> ! {
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
loop {
|
||||
cortex_m::asm::nop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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::SpawnHandle, ()> =
|
||||
foo::MyMono::spawn_at(monotonics::MyMono::now());
|
||||
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(1.secs());
|
||||
let _: Result<foo::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||
|
||||
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(1.secs());
|
||||
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||
|
||||
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(1.secs());
|
||||
let _: Result<(), ()> = handle.unwrap().cancel();
|
||||
|
||||
// Using default
|
||||
let _: Result<foo::SpawnHandle, ()> = foo::spawn_at(monotonics::now());
|
||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
|
||||
let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||
|
||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
|
||||
let _: Result<foo::SpawnHandle, ()> =
|
||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||
|
||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
|
||||
let _: Result<(), ()> = handle.unwrap().cancel();
|
||||
|
||||
// Task with single message passing
|
||||
|
||||
// Not default
|
||||
let _: Result<bar::MyMono::SpawnHandle, u32> =
|
||||
bar::MyMono::spawn_at(monotonics::MyMono::now(), 0);
|
||||
let handle: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_after(1.secs(), 1);
|
||||
let _: Result<bar::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||
|
||||
let handle: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_after(1.secs(), 1);
|
||||
let _: Result<bar::MyMono::SpawnHandle, ()> =
|
||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||
|
||||
let handle: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_after(1.secs(), 1);
|
||||
let _: Result<u32, ()> = handle.unwrap().cancel();
|
||||
|
||||
// Using default
|
||||
let _: Result<bar::SpawnHandle, u32> = bar::spawn_at(monotonics::MyMono::now(), 0);
|
||||
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(1.secs(), 1);
|
||||
let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||
|
||||
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(1.secs(), 1);
|
||||
let _: Result<bar::SpawnHandle, ()> =
|
||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||
|
||||
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(1.secs(), 1);
|
||||
let _: Result<u32, ()> = handle.unwrap().cancel();
|
||||
|
||||
// Task with multiple message passing
|
||||
|
||||
// Not default
|
||||
let _: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||
baz::MyMono::spawn_at(monotonics::MyMono::now(), 0, 1);
|
||||
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||
baz::MyMono::spawn_after(1.secs(), 1, 2);
|
||||
let _: Result<baz::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||
|
||||
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||
baz::MyMono::spawn_after(1.secs(), 1, 2);
|
||||
let _: Result<baz::MyMono::SpawnHandle, ()> =
|
||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||
|
||||
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||
baz::MyMono::spawn_after(1.secs(), 1, 2);
|
||||
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
||||
|
||||
// Using default
|
||||
let _: Result<baz::SpawnHandle, (u32, u32)> =
|
||||
baz::spawn_at(monotonics::MyMono::now(), 0, 1);
|
||||
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(1.secs(), 1, 2);
|
||||
let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||
|
||||
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(1.secs(), 1, 2);
|
||||
let _: Result<baz::SpawnHandle, ()> =
|
||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||
|
||||
let handle: Result<baz::SpawnHandle, (u32, u32)> = 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) {}
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
//! [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) {}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
//! examples/task.rs
|
||||
|
||||
#![deny(unsafe_code)]
|
||||
#![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use panic_semihosting as _;
|
||||
|
||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||
mod app {
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {}
|
||||
|
||||
#[local]
|
||||
struct Local {}
|
||||
|
||||
#[init]
|
||||
fn init(_: init::Context) -> (Shared, Local) {
|
||||
foo::spawn().unwrap();
|
||||
|
||||
(Shared {}, Local {})
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn foo(_: foo::Context) {
|
||||
hprintln!("foo - start");
|
||||
|
||||
// spawns `bar` onto the task scheduler
|
||||
// `foo` and `bar` have the same priority so `bar` will not run until
|
||||
// after `foo` terminates
|
||||
bar::spawn().unwrap();
|
||||
|
||||
hprintln!("foo - middle");
|
||||
|
||||
// spawns `baz` onto the task scheduler
|
||||
// `baz` has higher priority than `foo` so it immediately preempts `foo`
|
||||
baz::spawn().unwrap();
|
||||
|
||||
hprintln!("foo - end");
|
||||
}
|
||||
|
||||
#[task]
|
||||
async fn bar(_: bar::Context) {
|
||||
hprintln!("bar");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
|
||||
#[task(priority = 2)]
|
||||
async fn baz(_: baz::Context) {
|
||||
hprintln!("baz");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
//! examples/zero-prio-task.rs
|
||||
|
||||
#![no_main]
|
||||
#![no_std]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use panic_semihosting as _;
|
||||
|
||||
/// Does not impl send
|
||||
pub struct NotSend {
|
||||
_0: PhantomData<*const ()>,
|
||||
}
|
||||
|
||||
#[rtic::app(device = lm3s6965, peripherals = true)]
|
||||
mod app {
|
||||
use super::NotSend;
|
||||
use core::marker::PhantomData;
|
||||
use cortex_m_semihosting::{debug, hprintln};
|
||||
|
||||
#[shared]
|
||||
struct Shared {
|
||||
x: NotSend,
|
||||
}
|
||||
|
||||
#[local]
|
||||
struct Local {
|
||||
y: NotSend,
|
||||
}
|
||||
|
||||
#[init]
|
||||
fn init(_cx: init::Context) -> (Shared, Local) {
|
||||
hprintln!("init");
|
||||
|
||||
async_task::spawn().unwrap();
|
||||
async_task2::spawn().unwrap();
|
||||
|
||||
(
|
||||
Shared {
|
||||
x: NotSend { _0: PhantomData },
|
||||
},
|
||||
Local {
|
||||
y: NotSend { _0: PhantomData },
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[task(priority = 0, shared = [x], local = [y])]
|
||||
async fn async_task(_: async_task::Context) {
|
||||
hprintln!("hello from async");
|
||||
}
|
||||
|
||||
#[task(priority = 0, shared = [x])]
|
||||
async fn async_task2(_: async_task2::Context) {
|
||||
hprintln!("hello from async2");
|
||||
|
||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue