mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-01 16:04:33 +01:00
RFC #207
This commit is contained in:
parent
b150ab29e2
commit
4e51bb68b9
33 changed files with 143 additions and 142 deletions
|
@ -35,8 +35,8 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(spawn = [foo])]
|
#[task(binds = UART0, spawn = [foo])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
hprintln!("UART0(baseline = {:?})", c.start).unwrap();
|
hprintln!("UART0(baseline = {:?})", c.start).unwrap();
|
||||||
|
|
||||||
// `foo` inherits the baseline of `UART0`: its `start` time
|
// `foo` inherits the baseline of `UART0`: its `start` time
|
||||||
|
|
|
@ -30,7 +30,7 @@ const APP: () = {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(binds = UART0)]
|
#[task(binds = UART0)]
|
||||||
fn foo(_: foo::Context) {
|
fn foo(_: foo::Context) {
|
||||||
static mut TIMES: u32 = 0;
|
static mut TIMES: u32 = 0;
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ const APP: () = {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtfm::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(spawn = [foo, bar])]
|
#[task(binds = UART0, spawn = [foo, bar])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
c.spawn.foo(0).unwrap();
|
c.spawn.foo(0).unwrap();
|
||||||
c.spawn.foo(1).unwrap();
|
c.spawn.foo(1).unwrap();
|
||||||
c.spawn.foo(2).unwrap();
|
c.spawn.foo(2).unwrap();
|
||||||
|
|
|
@ -20,8 +20,8 @@ const APP: () = {
|
||||||
rtfm::pend(Interrupt::UART1);
|
rtfm::pend(Interrupt::UART1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [SHARED])]
|
#[task(binds = UART0, resources = [SHARED])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
static mut STATE: u32 = 0;
|
static mut STATE: u32 = 0;
|
||||||
|
|
||||||
hprintln!("UART0(STATE = {})", *STATE).unwrap();
|
hprintln!("UART0(STATE = {})", *STATE).unwrap();
|
||||||
|
@ -33,8 +33,8 @@ const APP: () = {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(priority = 2, resources = [SHARED])]
|
#[task(binds = UART1, priority = 2, resources = [SHARED])]
|
||||||
fn UART1(c: UART1::Context) {
|
fn uart1(c: uart1::Context) {
|
||||||
static mut STATE: u32 = 0;
|
static mut STATE: u32 = 0;
|
||||||
|
|
||||||
hprintln!("UART1(STATE = {})", *STATE).unwrap();
|
hprintln!("UART1(STATE = {})", *STATE).unwrap();
|
||||||
|
|
|
@ -33,8 +33,8 @@ const APP: () = {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt]
|
#[task(binds = UART0)]
|
||||||
fn UART0(_: UART0::Context) {
|
fn uart0(_: uart0::Context) {
|
||||||
static mut TIMES: u32 = 0;
|
static mut TIMES: u32 = 0;
|
||||||
|
|
||||||
// Safe access to local `static mut` variable
|
// Safe access to local `static mut` variable
|
||||||
|
|
|
@ -47,8 +47,8 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [P])]
|
#[task(binds = UART0, resources = [P])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
c.resources.P.enqueue(42).unwrap();
|
c.resources.P.enqueue(42).unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,8 +19,8 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// when omitted priority is assumed to be `1`
|
// when omitted priority is assumed to be `1`
|
||||||
#[interrupt(resources = [SHARED])]
|
#[task(binds = GPIOA, resources = [SHARED])]
|
||||||
fn GPIOA(mut c: GPIOA::Context) {
|
fn gpioa(mut c: gpioa::Context) {
|
||||||
hprintln!("A").unwrap();
|
hprintln!("A").unwrap();
|
||||||
|
|
||||||
// the lower priority task requires a critical section to access the data
|
// the lower priority task requires a critical section to access the data
|
||||||
|
@ -44,16 +44,16 @@ const APP: () = {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(priority = 2, resources = [SHARED])]
|
#[task(binds = GPIOB, priority = 2, resources = [SHARED])]
|
||||||
fn GPIOB(c: GPIOB::Context) {
|
fn gpiob(c: gpiob::Context) {
|
||||||
// the higher priority task does *not* need a critical section
|
// the higher priority task does *not* need a critical section
|
||||||
*c.resources.SHARED += 1;
|
*c.resources.SHARED += 1;
|
||||||
|
|
||||||
hprintln!("D - SHARED = {}", *c.resources.SHARED).unwrap();
|
hprintln!("D - SHARED = {}", *c.resources.SHARED).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(priority = 3)]
|
#[task(binds = GPIOC, priority = 3)]
|
||||||
fn GPIOC(_: GPIOC::Context) {
|
fn gpioc(_: gpioc::Context) {
|
||||||
hprintln!("C").unwrap();
|
hprintln!("C").unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,8 +29,8 @@ const APP: () = {
|
||||||
rtfm::pend(Interrupt::I2C0);
|
rtfm::pend(Interrupt::I2C0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(priority = 2, spawn = [foo, bar])]
|
#[task(binds = I2C0, priority = 2, spawn = [foo, bar])]
|
||||||
fn I2C0(c: I2C0::Context) {
|
fn i2c0(c: i2c0::Context) {
|
||||||
// claim a memory block, leave it uninitialized and ..
|
// claim a memory block, leave it uninitialized and ..
|
||||||
let x = P::alloc().unwrap().freeze();
|
let x = P::alloc().unwrap().freeze();
|
||||||
|
|
||||||
|
|
|
@ -31,16 +31,16 @@ const APP: () = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// `SHARED` can be access from this context
|
// `SHARED` can be access from this context
|
||||||
#[interrupt(resources = [SHARED])]
|
#[task(binds = UART0, resources = [SHARED])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
*c.resources.SHARED += 1;
|
*c.resources.SHARED += 1;
|
||||||
|
|
||||||
hprintln!("UART0: SHARED = {}", c.resources.SHARED).unwrap();
|
hprintln!("UART0: SHARED = {}", c.resources.SHARED).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// `SHARED` can be access from this context
|
// `SHARED` can be access from this context
|
||||||
#[interrupt(resources = [SHARED])]
|
#[task(binds = UART1, resources = [SHARED])]
|
||||||
fn UART1(c: UART1::Context) {
|
fn uart1(c: uart1::Context) {
|
||||||
*c.resources.SHARED += 1;
|
*c.resources.SHARED += 1;
|
||||||
|
|
||||||
hprintln!("UART1: SHARED = {}", c.resources.SHARED).unwrap();
|
hprintln!("UART1: SHARED = {}", c.resources.SHARED).unwrap();
|
||||||
|
|
|
@ -25,8 +25,8 @@ const APP: () = {
|
||||||
rtfm::pend(Interrupt::UART0);
|
rtfm::pend(Interrupt::UART0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [SHARED])]
|
#[task(binds = UART0, resources = [SHARED])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
if let Some(message) = c.resources.SHARED.take() {
|
if let Some(message) = c.resources.SHARED.take() {
|
||||||
// `message` has been received
|
// `message` has been received
|
||||||
drop(message);
|
drop(message);
|
||||||
|
|
|
@ -23,15 +23,15 @@ const APP: () = {
|
||||||
init::LateResources { KEY: 0xdeadbeef }
|
init::LateResources { KEY: 0xdeadbeef }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [KEY])]
|
#[task(binds = UART0, resources = [KEY])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
hprintln!("UART0(KEY = {:#x})", c.resources.KEY).unwrap();
|
hprintln!("UART0(KEY = {:#x})", c.resources.KEY).unwrap();
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(priority = 2, resources = [KEY])]
|
#[task(binds = UART1, priority = 2, resources = [KEY])]
|
||||||
fn UART1(c: UART1::Context) {
|
fn uart1(c: uart1::Context) {
|
||||||
hprintln!("UART1(KEY = {:#x})", c.resources.KEY).unwrap();
|
hprintln!("UART1(KEY = {:#x})", c.resources.KEY).unwrap();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,12 +12,14 @@ const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) {}
|
||||||
|
|
||||||
#[exception(binds = SVCall)]
|
// Cortex-M exception
|
||||||
|
#[task(binds = SVCall)]
|
||||||
fn foo(c: foo::Context) {
|
fn foo(c: foo::Context) {
|
||||||
foo_trampoline(c)
|
foo_trampoline(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(binds = UART0)]
|
// LM3S6965 interrupt
|
||||||
|
#[task(binds = UART0)]
|
||||||
fn bar(c: bar::Context) {
|
fn bar(c: bar::Context) {
|
||||||
bar_trampoline(c)
|
bar_trampoline(c)
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,8 @@ const APP: () = {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [O3, S1, S2, S3])]
|
#[task(binds = UART0, resources = [O3, S1, S2, S3])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
// owned by interrupt == `&mut`
|
// owned by interrupt == `&mut`
|
||||||
let _: &mut u32 = c.resources.O3;
|
let _: &mut u32 = c.resources.O3;
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ const APP: () = {
|
||||||
let _: &u32 = c.resources.S3;
|
let _: &u32 = c.resources.S3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [S2, O5])]
|
#[task(binds = UART1, resources = [S2, O5])]
|
||||||
fn UART1(c: UART1::Context) {
|
fn uart1(c: uart1::Context) {
|
||||||
// owned by interrupt == `&` if read-only
|
// owned by interrupt == `&` if read-only
|
||||||
let _: &u32 = c.resources.O5;
|
let _: &u32 = c.resources.O5;
|
||||||
|
|
||||||
|
|
|
@ -26,15 +26,15 @@ const APP: () = {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[exception(schedule = [foo, bar, baz])]
|
#[task(binds = SVCall, schedule = [foo, bar, baz])]
|
||||||
fn SVCall(c: SVCall::Context) {
|
fn svcall(c: svcall::Context) {
|
||||||
let _: Result<(), ()> = c.schedule.foo(c.start + 70.cycles());
|
let _: Result<(), ()> = c.schedule.foo(c.start + 70.cycles());
|
||||||
let _: Result<(), u32> = c.schedule.bar(c.start + 80.cycles(), 0);
|
let _: Result<(), u32> = c.schedule.bar(c.start + 80.cycles(), 0);
|
||||||
let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 90.cycles(), 0, 1);
|
let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 90.cycles(), 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(schedule = [foo, bar, baz])]
|
#[task(binds = UART0, schedule = [foo, bar, baz])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
let _: Result<(), ()> = c.schedule.foo(c.start + 100.cycles());
|
let _: Result<(), ()> = c.schedule.foo(c.start + 100.cycles());
|
||||||
let _: Result<(), u32> = c.schedule.bar(c.start + 110.cycles(), 0);
|
let _: Result<(), u32> = c.schedule.bar(c.start + 110.cycles(), 0);
|
||||||
let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 120.cycles(), 0, 1);
|
let _: Result<(), (u32, u32)> = c.schedule.baz(c.start + 120.cycles(), 0, 1);
|
||||||
|
|
|
@ -25,15 +25,15 @@ const APP: () = {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[exception(spawn = [foo, bar, baz])]
|
#[task(binds = SVCall, spawn = [foo, bar, baz])]
|
||||||
fn SVCall(c: SVCall::Context) {
|
fn svcall(c: svcall::Context) {
|
||||||
let _: Result<(), ()> = c.spawn.foo();
|
let _: Result<(), ()> = c.spawn.foo();
|
||||||
let _: Result<(), u32> = c.spawn.bar(0);
|
let _: Result<(), u32> = c.spawn.bar(0);
|
||||||
let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
|
let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(spawn = [foo, bar, baz])]
|
#[task(binds = UART0, spawn = [foo, bar, baz])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
let _: Result<(), ()> = c.spawn.foo();
|
let _: Result<(), ()> = c.spawn.foo();
|
||||||
let _: Result<(), u32> = c.spawn.bar(0);
|
let _: Result<(), u32> = c.spawn.bar(0);
|
||||||
let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
|
let _: Result<(), (u32, u32)> = c.spawn.baz(0, 1);
|
||||||
|
|
|
@ -24,19 +24,19 @@ const APP: () = {
|
||||||
debug::exit(debug::EXIT_SUCCESS);
|
debug::exit(debug::EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[exception(schedule = [foo], spawn = [foo])]
|
#[task(binds = SVCall, schedule = [foo], spawn = [foo])]
|
||||||
fn SVCall(c: SVCall::Context) {
|
fn svcall(c: svcall::Context) {
|
||||||
let _: Instant = c.start;
|
let _: Instant = c.start;
|
||||||
let _: SVCall::Schedule = c.schedule;
|
let _: svcall::Schedule = c.schedule;
|
||||||
let _: SVCall::Spawn = c.spawn;
|
let _: svcall::Spawn = c.spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [SHARED], schedule = [foo], spawn = [foo])]
|
#[task(binds = UART0, resources = [SHARED], schedule = [foo], spawn = [foo])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
let _: Instant = c.start;
|
let _: Instant = c.start;
|
||||||
let _: resources::SHARED = c.resources.SHARED;
|
let _: resources::SHARED = c.resources.SHARED;
|
||||||
let _: UART0::Schedule = c.schedule;
|
let _: uart0::Schedule = c.schedule;
|
||||||
let _: UART0::Spawn = c.spawn;
|
let _: uart0::Spawn = c.spawn;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task(priority = 2, resources = [SHARED], schedule = [foo], spawn = [foo])]
|
#[task(priority = 2, resources = [SHARED], schedule = [foo], spawn = [foo])]
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashSet;
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use rtfm_syntax::{
|
use rtfm_syntax::{
|
||||||
analyze::Analysis,
|
analyze::Analysis,
|
||||||
ast::{App, CustomArg, HardwareTaskKind},
|
ast::{App, CustomArg},
|
||||||
};
|
};
|
||||||
use syn::{parse, Path};
|
use syn::{parse, Path};
|
||||||
|
|
||||||
|
@ -44,18 +44,9 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
|
|
||||||
// check that all exceptions are valid; only exceptions with configurable priorities are
|
// check that all exceptions are valid; only exceptions with configurable priorities are
|
||||||
// accepted
|
// accepted
|
||||||
for (name, task) in app
|
for (name, task) in &app.hardware_tasks {
|
||||||
.hardware_tasks
|
let name_s = task.args.binds.to_string();
|
||||||
.iter()
|
|
||||||
.filter(|(_, task)| task.kind == HardwareTaskKind::Exception)
|
|
||||||
{
|
|
||||||
let name_s = task.args.binds(name).to_string();
|
|
||||||
match &*name_s {
|
match &*name_s {
|
||||||
// NOTE that some of these don't exist on ARMv6-M but we don't check that here -- the
|
|
||||||
// code we generate will check that the exception actually exists on ARMv6-M
|
|
||||||
"MemoryManagement" | "BusFault" | "UsageFault" | "SecureFault" | "SVCall"
|
|
||||||
| "DebugMonitor" | "PendSV" => {} // OK
|
|
||||||
|
|
||||||
"SysTick" => {
|
"SysTick" => {
|
||||||
if analysis.timer_queues.get(&task.args.core).is_some() {
|
if analysis.timer_queues.get(&task.args.core).is_some() {
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
|
@ -67,12 +58,14 @@ pub fn app<'a>(app: &'a App, analysis: &Analysis) -> parse::Result<Extra<'a>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
"NonMaskableInt" | "HardFault" => {
|
||||||
return Err(parse::Error::new(
|
return Err(parse::Error::new(
|
||||||
name.span(),
|
name.span(),
|
||||||
"only exceptions with configurable priority can be used as hardware tasks",
|
"only exceptions with configurable priority can be used as hardware tasks",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,9 +50,9 @@ pub fn codegen(
|
||||||
};
|
};
|
||||||
|
|
||||||
let symbol = if cfg!(feature = "homogeneous") {
|
let symbol = if cfg!(feature = "homogeneous") {
|
||||||
util::suffixed(&task.args.binds(name).to_string(), core)
|
util::suffixed(&task.args.binds.to_string(), core)
|
||||||
} else {
|
} else {
|
||||||
task.args.binds(name).clone()
|
task.args.binds.clone()
|
||||||
};
|
};
|
||||||
let priority = task.args.priority;
|
let priority = task.args.priority;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use proc_macro2::TokenStream as TokenStream2;
|
use proc_macro2::TokenStream as TokenStream2;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use rtfm_syntax::ast::{App, HardwareTaskKind};
|
use rtfm_syntax::ast::App;
|
||||||
|
|
||||||
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
use crate::{analyze::Analysis, check::Extra, codegen::util};
|
||||||
|
|
||||||
|
@ -52,9 +52,9 @@ pub fn codegen(
|
||||||
.get(&core)
|
.get(&core)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|interrupts| *interrupts)
|
.flat_map(|interrupts| *interrupts)
|
||||||
.chain(app.hardware_tasks.iter().flat_map(|(name, task)| {
|
.chain(app.hardware_tasks.values().flat_map(|task| {
|
||||||
if task.kind == HardwareTaskKind::Interrupt {
|
if !util::is_exception(&task.args.binds) {
|
||||||
Some((&task.args.priority, task.args.binds(name)))
|
Some((&task.args.priority, &task.args.binds))
|
||||||
} else {
|
} else {
|
||||||
// we do exceptions in another pass
|
// we do exceptions in another pass
|
||||||
None
|
None
|
||||||
|
@ -102,9 +102,9 @@ pub fn codegen(
|
||||||
}
|
}
|
||||||
|
|
||||||
// set exception priorities
|
// set exception priorities
|
||||||
for (name, priority) in app.hardware_tasks.iter().filter_map(|(name, task)| {
|
for (name, priority) in app.hardware_tasks.values().filter_map(|task| {
|
||||||
if task.kind == HardwareTaskKind::Exception {
|
if util::is_exception(&task.args.binds) {
|
||||||
Some((task.args.binds(name), task.args.priority))
|
Some((&task.args.binds, task.args.priority))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,6 +113,18 @@ pub fn interrupt_ident(core: Core, cores: u8) -> Ident {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whether `name` is an exception with configurable priority
|
||||||
|
pub fn is_exception(name: &Ident) -> bool {
|
||||||
|
let s = name.to_string();
|
||||||
|
|
||||||
|
match &*s {
|
||||||
|
"MemoryManagement" | "BusFault" | "UsageFault" | "SecureFault" | "SVCall"
|
||||||
|
| "DebugMonitor" | "PendSV" | "SysTick" => true,
|
||||||
|
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generates a pre-reexport identifier for the "late resources" struct
|
/// Generates a pre-reexport identifier for the "late resources" struct
|
||||||
pub fn late_resources_ident(init: &Ident) -> Ident {
|
pub fn late_resources_ident(init: &Ident) -> Ident {
|
||||||
Ident::new(
|
Ident::new(
|
||||||
|
|
|
@ -16,19 +16,14 @@ mod tests;
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn app(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn app(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let (app, analysis) = match rtfm_syntax::parse(
|
let mut settings = Settings::default();
|
||||||
args,
|
settings.optimize_priorities = true;
|
||||||
input,
|
settings.parse_binds = true;
|
||||||
Settings {
|
settings.parse_cores = cfg!(feature = "heterogeneous") || cfg!(feature = "homogeneous");
|
||||||
parse_cores: cfg!(feature = "heterogeneous") || cfg!(feature = "homogeneous"),
|
settings.parse_extern_interrupt = true;
|
||||||
parse_exception: true,
|
settings.parse_schedule = true;
|
||||||
parse_extern_interrupt: true,
|
|
||||||
parse_interrupt: true,
|
let (app, analysis) = match rtfm_syntax::parse(args, input, settings) {
|
||||||
parse_schedule: true,
|
|
||||||
optimize_priorities: true,
|
|
||||||
..Settings::default()
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Err(e) => return e.to_compile_error().into(),
|
Err(e) => return e.to_compile_error().into(),
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,10 @@ use rtfm_syntax::Settings;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn analyze() {
|
fn analyze() {
|
||||||
|
let mut settings = Settings::default();
|
||||||
|
settings.parse_cores = true;
|
||||||
|
settings.parse_extern_interrupt = true;
|
||||||
|
|
||||||
let (app, analysis) = rtfm_syntax::parse2(
|
let (app, analysis) = rtfm_syntax::parse2(
|
||||||
quote!(device = pac, cores = 2),
|
quote!(device = pac, cores = 2),
|
||||||
quote!(
|
quote!(
|
||||||
|
@ -35,13 +39,9 @@ fn analyze() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
),
|
),
|
||||||
Settings {
|
settings,
|
||||||
parse_cores: true,
|
|
||||||
parse_extern_interrupt: true,
|
|
||||||
..Settings::default()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let analysis = crate::analyze::app(analysis, &app);
|
let analysis = crate::analyze::app(analysis, &app);
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ use rtfm_syntax::Settings;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn analyze() {
|
fn analyze() {
|
||||||
|
let mut settings = Settings::default();
|
||||||
|
settings.parse_extern_interrupt = true;
|
||||||
let (app, analysis) = rtfm_syntax::parse2(
|
let (app, analysis) = rtfm_syntax::parse2(
|
||||||
quote!(device = pac),
|
quote!(device = pac),
|
||||||
quote!(
|
quote!(
|
||||||
|
@ -20,10 +22,7 @@ fn analyze() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
),
|
),
|
||||||
Settings {
|
settings,
|
||||||
parse_extern_interrupt: true,
|
|
||||||
..Settings::default()
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtfm::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[exception]
|
#[task(binds = NonMaskableInt)]
|
||||||
fn NonMaskableInt(_: NonMaskableInt::Context) {}
|
fn nmi(_: nmi::Context) {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: only exceptions with configurable priority can be used as hardware tasks
|
error: only exceptions with configurable priority can be used as hardware tasks
|
||||||
--> $DIR/exception-invalid.rs:6:8
|
--> $DIR/exception-invalid.rs:6:8
|
||||||
|
|
|
|
||||||
6 | fn NonMaskableInt(_: NonMaskableInt::Context) {}
|
6 | fn nmi(_: nmi::Context) {}
|
||||||
| ^^^^^^^^^^^^^^
|
| ^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtfm::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[exception]
|
#[task(binds = SysTick)]
|
||||||
fn SysTick(_: SysTick::Context) {}
|
fn sys_tick(_: sys_tick::Context) {}
|
||||||
|
|
||||||
#[task(schedule = [foo])]
|
#[task(schedule = [foo])]
|
||||||
fn foo(_: foo::Context) {}
|
fn foo(_: foo::Context) {}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: this exception can't be used because it's being used by the runtime
|
error: this exception can't be used because it's being used by the runtime
|
||||||
--> $DIR/exception-systick-used.rs:6:8
|
--> $DIR/exception-systick-used.rs:6:8
|
||||||
|
|
|
|
||||||
6 | fn SysTick(_: SysTick::Context) {}
|
6 | fn sys_tick(_: sys_tick::Context) {}
|
||||||
| ^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#[rtfm::app(device = lm3s6965)]
|
#[rtfm::app(device = lm3s6965)]
|
||||||
const APP: () = {
|
const APP: () = {
|
||||||
#[interrupt(binds = UART0)]
|
#[task(binds = UART0)]
|
||||||
fn a(_: a::Context) {}
|
fn a(_: a::Context) {}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: `extern` interrupts can't be used as hardware tasks
|
error: `extern` interrupts can't be used as hardware tasks
|
||||||
--> $DIR/extern-interrupt-used.rs:5:25
|
--> $DIR/extern-interrupt-used.rs:5:20
|
||||||
|
|
|
|
||||||
5 | #[interrupt(binds = UART0)]
|
5 | #[task(binds = UART0)]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -20,16 +20,16 @@ const APP: () = {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[exception]
|
#[task(binds = SVCall)]
|
||||||
fn SVCall(_: SVCall::Context) {
|
fn svcall(_: svcall::Context) {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
static mut FOO: u32 = 0;
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
FOO;
|
FOO;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt]
|
#[task(binds = UART0)]
|
||||||
fn UART0(_: UART0::Context) {
|
fn uart0(_: uart0::Context) {
|
||||||
#[cfg(never)]
|
#[cfg(never)]
|
||||||
static mut FOO: u32 = 0;
|
static mut FOO: u32 = 0;
|
||||||
|
|
||||||
|
|
|
@ -41,16 +41,16 @@ const APP: () = {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [O3, S1, S2, S3])]
|
#[task(binds = UART0, resources = [O3, S1, S2, S3])]
|
||||||
fn UART0(c: UART0::Context) {
|
fn uart0(c: uart0::Context) {
|
||||||
c.resources.O3;
|
c.resources.O3;
|
||||||
c.resources.S1;
|
c.resources.S1;
|
||||||
c.resources.S2;
|
c.resources.S2;
|
||||||
c.resources.S3;
|
c.resources.S3;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[interrupt(resources = [S2, O5])]
|
#[task(binds = UART1, resources = [S2, O5])]
|
||||||
fn UART1(c: UART1::Context) {
|
fn uart1(c: uart1::Context) {
|
||||||
c.resources.S2;
|
c.resources.S2;
|
||||||
c.resources.O5;
|
c.resources.O5;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ error[E0609]: no field `S3` on type `idleResources<'_>`
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `O3` on type `UART0Resources<'_>`
|
error[E0609]: no field `O3` on type `uart0Resources<'_>`
|
||||||
--> $DIR/resources-cfg.rs:46:21
|
--> $DIR/resources-cfg.rs:46:21
|
||||||
|
|
|
|
||||||
46 | c.resources.O3;
|
46 | c.resources.O3;
|
||||||
|
@ -78,7 +78,7 @@ error[E0609]: no field `O3` on type `UART0Resources<'_>`
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `S1` on type `UART0Resources<'_>`
|
error[E0609]: no field `S1` on type `uart0Resources<'_>`
|
||||||
--> $DIR/resources-cfg.rs:47:21
|
--> $DIR/resources-cfg.rs:47:21
|
||||||
|
|
|
|
||||||
47 | c.resources.S1;
|
47 | c.resources.S1;
|
||||||
|
@ -86,7 +86,7 @@ error[E0609]: no field `S1` on type `UART0Resources<'_>`
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `S2` on type `UART0Resources<'_>`
|
error[E0609]: no field `S2` on type `uart0Resources<'_>`
|
||||||
--> $DIR/resources-cfg.rs:48:21
|
--> $DIR/resources-cfg.rs:48:21
|
||||||
|
|
|
|
||||||
48 | c.resources.S2;
|
48 | c.resources.S2;
|
||||||
|
@ -94,7 +94,7 @@ error[E0609]: no field `S2` on type `UART0Resources<'_>`
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `S3` on type `UART0Resources<'_>`
|
error[E0609]: no field `S3` on type `uart0Resources<'_>`
|
||||||
--> $DIR/resources-cfg.rs:49:21
|
--> $DIR/resources-cfg.rs:49:21
|
||||||
|
|
|
|
||||||
49 | c.resources.S3;
|
49 | c.resources.S3;
|
||||||
|
@ -102,7 +102,7 @@ error[E0609]: no field `S3` on type `UART0Resources<'_>`
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `S2` on type `UART1Resources<'_>`
|
error[E0609]: no field `S2` on type `uart1Resources<'_>`
|
||||||
--> $DIR/resources-cfg.rs:54:21
|
--> $DIR/resources-cfg.rs:54:21
|
||||||
|
|
|
|
||||||
54 | c.resources.S2;
|
54 | c.resources.S2;
|
||||||
|
@ -110,7 +110,7 @@ error[E0609]: no field `S2` on type `UART1Resources<'_>`
|
||||||
|
|
|
|
||||||
= note: available fields are: `__marker__`
|
= note: available fields are: `__marker__`
|
||||||
|
|
||||||
error[E0609]: no field `O5` on type `UART1Resources<'_>`
|
error[E0609]: no field `O5` on type `uart1Resources<'_>`
|
||||||
--> $DIR/resources-cfg.rs:55:21
|
--> $DIR/resources-cfg.rs:55:21
|
||||||
|
|
|
|
||||||
55 | c.resources.O5;
|
55 | c.resources.O5;
|
||||||
|
|
|
@ -7,32 +7,32 @@ const APP: () = {
|
||||||
#[init]
|
#[init]
|
||||||
fn init(_: init::Context) {}
|
fn init(_: init::Context) {}
|
||||||
|
|
||||||
#[interrupt(priority = 1)]
|
#[task(binds = GPIOA, priority = 1)]
|
||||||
fn GPIOA(_: GPIOA::Context) {}
|
fn gpioa(_: gpioa::Context) {}
|
||||||
|
|
||||||
#[interrupt(priority = 2)]
|
#[task(binds = GPIOB, priority = 2)]
|
||||||
fn GPIOB(_: GPIOB::Context) {}
|
fn gpiob(_: gpiob::Context) {}
|
||||||
|
|
||||||
#[interrupt(priority = 3)]
|
#[task(binds = GPIOC, priority = 3)]
|
||||||
fn GPIOC(_: GPIOC::Context) {}
|
fn gpioc(_: gpioc::Context) {}
|
||||||
|
|
||||||
#[interrupt(priority = 4)]
|
#[task(binds = GPIOD, priority = 4)]
|
||||||
fn GPIOD(_: GPIOD::Context) {}
|
fn gpiod(_: gpiod::Context) {}
|
||||||
|
|
||||||
#[interrupt(priority = 5)]
|
#[task(binds = GPIOE, priority = 5)]
|
||||||
fn GPIOE(_: GPIOE::Context) {}
|
fn gpioe(_: gpioe::Context) {}
|
||||||
|
|
||||||
#[interrupt(priority = 6)]
|
#[task(binds = UART0, priority = 6)]
|
||||||
fn UART0(_: UART0::Context) {}
|
fn uart0(_: uart0::Context) {}
|
||||||
|
|
||||||
#[interrupt(priority = 7)]
|
#[task(binds = UART1, priority = 7)]
|
||||||
fn UART1(_: UART1::Context) {}
|
fn uart1(_: uart1::Context) {}
|
||||||
|
|
||||||
// OK, this is the maximum priority supported by the device
|
// OK, this is the maximum priority supported by the device
|
||||||
#[interrupt(priority = 8)]
|
#[task(binds = SSI0, priority = 8)]
|
||||||
fn SSI0(_: SSI0::Context) {}
|
fn ssi0(_: ssi0::Context) {}
|
||||||
|
|
||||||
// this value is too high!
|
// this value is too high!
|
||||||
#[interrupt(priority = 9)]
|
#[task(binds = I2C0, priority = 9)]
|
||||||
fn I2C0(_: I2C0::Context) {}
|
fn i2c0(_: i2c0::Context) {}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue