Merge branch 'master' into spawn_experiment

This commit is contained in:
Emil Fresk 2020-10-15 18:27:48 +02:00
commit 6808cc7cdf
10 changed files with 443 additions and 3 deletions

View file

@ -119,10 +119,13 @@ The static priority of each handler can be declared in the `task` attribute
using the `priority` argument. Tasks can have priorities in the range `1..=(1 << using the `priority` argument. Tasks can have priorities in the range `1..=(1 <<
NVIC_PRIO_BITS)` where `NVIC_PRIO_BITS` is a constant defined in the `device` NVIC_PRIO_BITS)` where `NVIC_PRIO_BITS` is a constant defined in the `device`
crate. When the `priority` argument is omitted, the priority is assumed to be crate. When the `priority` argument is omitted, the priority is assumed to be
`1`. The `idle` task has a non-configurable static priority of `0`, the lowest `1`. The `idle` task has a non-configurable static priority of `0`, the lowest priority.
priority.
When several tasks are ready to be executed the one with *highest* static > A higher number means a higher priority in RTIC, which is the opposite from what
> Cortex-M does in the NVIC peripheral.
> Explicitly, this means that number `10` has a **higher** priority than number `9`.
When several tasks are ready to be executed the one with highest static
priority will be executed first. Task prioritization can be observed in the priority will be executed first. Task prioritization can be observed in the
following scenario: an interrupt signal arrives during the execution of a low following scenario: an interrupt signal arrives during the execution of a low
priority task; the signal puts the higher priority task in the pending state. priority task; the signal puts the higher priority task in the pending state.

59
examples/static.rs Normal file
View file

@ -0,0 +1,59 @@
//! examples/static.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_semihosting::{debug, hprintln};
use heapless::{
consts::*,
i,
spsc::{Consumer, Producer, Queue},
};
use lm3s6965::Interrupt;
use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
use crate::U4;
use crate::{Consumer, Producer};
// Late resources
#[resources]
struct Resources {
p: Producer<'static, u32, U4>,
c: Consumer<'static, u32, U4>,
}
#[init]
fn init(_: init::Context) -> init::LateResources {
static mut Q: Queue<u32, U4> = Queue(i::Queue::new());
let (p, c) = Q.split();
// Initialization of late resources
init::LateResources { p, c }
}
#[idle(resources = [c])]
fn idle(c: idle::Context) -> ! {
loop {
if let Some(byte) = c.resources.c.dequeue() {
hprintln!("received message: {}", byte).unwrap();
debug::exit(debug::EXIT_SUCCESS);
} else {
rtic::pend(Interrupt::UART0);
}
}
}
#[task(binds = UART0, resources = [p])]
fn uart0(c: uart0::Context) {
static mut KALLE: u32 = 0;
*KALLE += 1;
c.resources.p.enqueue(42).unwrap();
}
}

View file

@ -0,0 +1,33 @@
//! examples/task-local_minimal.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_semihosting::{debug, hprintln};
use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[resources]
struct Resources {
// A local (move), late resource
#[task_local]
l: u32,
}
#[init]
fn init(_: init::Context) -> init::LateResources {
init::LateResources { l: 42 }
}
// l is task_local
#[idle(resources =[l])]
fn idle(cx: idle::Context) -> ! {
hprintln!("IDLE:l = {}", cx.resources.l).unwrap();
debug::exit(debug::EXIT_SUCCESS);
loop {
cortex_m::asm::nop();
}
}
}

82
examples/task-local.rs Normal file
View file

@ -0,0 +1,82 @@
//! examples/task-local.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[resources]
struct Resources {
// An early resource
#[init(0)]
shared: u32,
// A local (move), early resource
#[task_local]
#[init(1)]
l1: u32,
// An exclusive, early resource
#[lock_free]
#[init(1)]
e1: u32,
// A local (move), late resource
#[task_local]
l2: u32,
// An exclusive, late resource
#[lock_free]
e2: u32,
}
#[init]
fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
init::LateResources { e2: 2, l2: 2 }
}
// `shared` cannot be accessed from this context
// l1 ok (task_local)
// e2 ok (lock_free)
#[idle(resources =[l1, e2])]
fn idle(cx: idle::Context) -> ! {
hprintln!("IDLE:l1 = {}", cx.resources.l1).unwrap();
hprintln!("IDLE:e2 = {}", cx.resources.e2).unwrap();
debug::exit(debug::EXIT_SUCCESS);
loop {
cortex_m::asm::nop();
}
}
// `shared` can be accessed from this context
// l2 ok (task_local)
// e1 ok (lock_free)
#[task(priority = 1, binds = UART0, resources = [shared, l2, e1])]
fn uart0(cx: uart0::Context) {
let shared: &mut u32 = cx.resources.shared;
*shared += 1;
*cx.resources.e1 += 10;
hprintln!("UART0: shared = {}", shared).unwrap();
hprintln!("UART0:l2 = {}", cx.resources.l2).unwrap();
hprintln!("UART0:e1 = {}", cx.resources.e1).unwrap();
}
// `shared` can be accessed from this context
// e1 ok (lock_free)
#[task(priority = 1, binds = UART1, resources = [shared, e1])]
fn uart1(cx: uart1::Context) {
let shared: &mut u32 = cx.resources.shared;
*shared += 1;
hprintln!("UART1: shared = {}", shared).unwrap();
hprintln!("UART1:e1 = {}", cx.resources.e1).unwrap();
}
}

View file

@ -19,6 +19,7 @@ proc-macro = true
[dependencies] [dependencies]
proc-macro2 = "1" proc-macro2 = "1"
proc-macro-error = "1"
quote = "1" quote = "1"
syn = "1" syn = "1"
rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "master", version = "0.5.0-alpha.0" } rtic-syntax = { git = "https://github.com/rtic-rs/rtic-syntax", branch = "master", version = "0.5.0-alpha.0" }

View file

@ -117,6 +117,19 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
let name = &app.name; let name = &app.name;
let device = extra.device; let device = extra.device;
// Get the list of all tasks
// Currently unused, might be useful
let task_list = analysis.tasks.clone();
let mut tasks = vec![];
if !task_list.is_empty() {
tasks.push(quote!(
enum Tasks {
#(#task_list),*
}
));
}
quote!( quote!(
#(#user)* #(#user)*
@ -132,6 +145,9 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
#(#root_software_tasks)* #(#root_software_tasks)*
/// Unused
#(#tasks)*
/// Implementation details /// Implementation details
mod #name { mod #name {
/// Always include the device crate which contains the vector table /// Always include the device crate which contains the vector table

View file

@ -0,0 +1,66 @@
//! examples/local-cfg-task-local.rs
#![deny(unsafe_code)]
//#![deny(warnings)]
#![no_main]
#![no_std]
use cortex_m_semihosting::debug;
use cortex_m_semihosting::hprintln;
use lm3s6965::Interrupt;
use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[resources]
struct Resources {
// A local (move), early resource
#[cfg(feature = "feature_l1")]
#[task_local]
#[init(1)]
l1: u32,
// A local (move), late resource
#[task_local]
l2: u32,
}
#[init]
fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
init::LateResources {
#[cfg(feature = "feature_l2")]
l2: 2,
#[cfg(not(feature = "feature_l2"))]
l2: 5,
}
}
// l1 ok (task_local)
#[idle(resources =[#[cfg(feature = "feature_l1")]l1])]
fn idle(_cx: idle::Context) -> ! {
#[cfg(feature = "feature_l1")]
hprintln!("IDLE:l1 = {}", _cx.resources.l1).unwrap();
debug::exit(debug::EXIT_SUCCESS);
loop {}
}
// l2 ok (task_local)
#[task(priority = 1, binds = UART0, resources = [
#[cfg(feature = "feature_l2")]l2,
])]
fn uart0(_cx: uart0::Context) {
#[cfg(feature = "feature_l2")]
hprintln!("UART0:l2 = {}", _cx.resources.l2).unwrap();
}
// l2 error, conflicting with uart0 for l2 (task_local)
#[task(priority = 1, binds = UART1, resources = [
#[cfg(not(feature = "feature_l2"))]l2
])]
fn uart1(_cx: uart1::Context) {
#[cfg(not(feature = "feature_l2"))]
hprintln!("UART0:l2 = {}", _cx.resources.l2).unwrap();
}
}

View file

@ -0,0 +1,37 @@
error: task local resource "l2" is used by multiple tasks
--> $DIR/local-cfg-task-local-err.rs:25:9
|
25 | l2: u32,
| ^^
error: task local resource "l2" is used by task "uart0" with priority 1
--> $DIR/local-cfg-task-local-err.rs:51:39
|
51 | #[cfg(feature = "feature_l2")]l2,
| ^^
error: task local resource "l2" is used by task "uart1" with priority 1
--> $DIR/local-cfg-task-local-err.rs:60:44
|
60 | #[cfg(not(feature = "feature_l2"))]l2
| ^^
warning: unused import: `cortex_m_semihosting::debug`
--> $DIR/local-cfg-task-local-err.rs:8:5
|
8 | use cortex_m_semihosting::debug;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unused import: `cortex_m_semihosting::hprintln`
--> $DIR/local-cfg-task-local-err.rs:9:5
|
9 | use cortex_m_semihosting::hprintln;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: unused import: `lm3s6965::Interrupt`
--> $DIR/local-cfg-task-local-err.rs:10:5
|
10 | use lm3s6965::Interrupt;
| ^^^^^^^^^^^^^^^^^^^

83
ui/single/local-err.rs Normal file
View file

@ -0,0 +1,83 @@
//! examples/local_err.rs
#![deny(unsafe_code)]
#![deny(warnings)]
#![no_main]
#![no_std]
// errors here, since we cannot bail compilation or generate stubs
// run cargo expand, then you see the root of the problem...
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
use panic_semihosting as _;
#[rtic::app(device = lm3s6965)]
mod app {
#[resources]
struct Resources {
// An early resource
#[init(0)]
shared: u32,
// A local (move), early resource
#[task_local]
#[init(1)]
l1: u32,
// An exclusive, early resource
#[lock_free]
#[init(1)]
e1: u32,
// A local (move), late resource
#[task_local]
l2: u32,
// An exclusive, late resource
#[lock_free]
e2: u32,
}
#[init]
fn init(_: init::Context) -> init::LateResources {
rtic::pend(Interrupt::UART0);
rtic::pend(Interrupt::UART1);
init::LateResources { e2: 2, l2: 2 }
}
// `shared` cannot be accessed from this context
// l1 ok
// l2 rejeceted (not task_local)
// e2 ok
#[idle(resources =[l1, l2, e2])]
fn idle(cx: idle::Context) -> ! {
hprintln!("IDLE:l1 = {}", cx.resources.l1).unwrap();
hprintln!("IDLE:e2 = {}", cx.resources.e2).unwrap();
debug::exit(debug::EXIT_SUCCESS);
loop {}
}
// `shared` can be accessed from this context
// l2 rejected (not task_local)
// e1 rejected (not lock_free)
#[task(priority = 1, binds = UART0, resources = [shared, l2, e1])]
fn uart0(cx: uart0::Context) {
let shared: &mut u32 = cx.resources.shared;
*shared += 1;
*cx.resources.e1 += 10;
hprintln!("UART0: shared = {}", shared).unwrap();
hprintln!("UART0:l2 = {}", cx.resources.l2).unwrap();
hprintln!("UART0:e1 = {}", cx.resources.e1).unwrap();
}
// l2 rejected (not task_local)
#[task(priority = 2, binds = UART1, resources = [shared, l2, e1])]
fn uart1(cx: uart1::Context) {
let shared: &mut u32 = cx.resources.shared;
*shared += 1;
hprintln!("UART1: shared = {}", shared).unwrap();
hprintln!("UART1:l2 = {}", cx.resources.l2).unwrap();
hprintln!("UART1:e1 = {}", cx.resources.e1).unwrap();
}
}

View file

@ -0,0 +1,60 @@
error: task local resource "l2" is used by multiple tasks
--> $DIR/local-err.rs:34:9
|
34 | l2: u32,
| ^^
error: task local resource "l2" is used by task "idle" with priority 0
--> $DIR/local-err.rs:52:28
|
52 | #[idle(resources =[l1, l2, e2])]
| ^^
error: task local resource "l2" is used by task "uart0" with priority 1
--> $DIR/local-err.rs:63:62
|
63 | #[task(priority = 1, binds = UART0, resources = [shared, l2, e1])]
| ^^
error: task local resource "l2" is used by task "uart1" with priority 2
--> $DIR/local-err.rs:74:62
|
74 | #[task(priority = 2, binds = UART1, resources = [shared, l2, e1])]
| ^^
error: Lock free resource "e1" is used by tasks at different priorities
--> $DIR/local-err.rs:30:9
|
30 | e1: u32,
| ^^
error: Resource "e1" is declared lock free but used by tasks at different priorities
--> $DIR/local-err.rs:63:66
|
63 | #[task(priority = 1, binds = UART0, resources = [shared, l2, e1])]
| ^^
error: Resource "e1" is declared lock free but used by tasks at different priorities
--> $DIR/local-err.rs:74:66
|
74 | #[task(priority = 2, binds = UART1, resources = [shared, l2, e1])]
| ^^
error: unused imports: `debug`, `hprintln`
--> $DIR/local-err.rs:10:28
|
10 | use cortex_m_semihosting::{debug, hprintln};
| ^^^^^ ^^^^^^^^
|
note: the lint level is defined here
--> $DIR/local-err.rs:4:9
|
4 | #![deny(warnings)]
| ^^^^^^^^
= note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]`
error: unused import: `lm3s6965::Interrupt`
--> $DIR/local-err.rs:11:5
|
11 | use lm3s6965::Interrupt;
| ^^^^^^^^^^^^^^^^^^^