mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-29 06:54:33 +01:00
make task.$T.enabled optional
and move the logic that differentiates interrupts from exceptions from the crate to the procedural macro logic
This commit is contained in:
parent
ad2a523cf9
commit
d396da5950
17 changed files with 112 additions and 92 deletions
|
@ -37,7 +37,9 @@ app! {
|
|||
},
|
||||
|
||||
TIM2: {
|
||||
enabled: true,
|
||||
// tasks are enabled, between `init` and `idle`, by default but they
|
||||
// can start disabled if `false` is specified here
|
||||
enabled: false,
|
||||
path: tim2,
|
||||
priority: 1,
|
||||
resources: [CO_OWNED],
|
||||
|
|
|
@ -15,14 +15,12 @@ app! {
|
|||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
enabled: true,
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [GPIOA, SPI1],
|
||||
},
|
||||
|
||||
EXTI1: {
|
||||
enabled: true,
|
||||
path: exti1,
|
||||
priority: 2,
|
||||
resources: [GPIOA, SPI1],
|
||||
|
|
|
@ -31,14 +31,11 @@ app! {
|
|||
tasks: {
|
||||
SYS_TICK: {
|
||||
path: tasks::sys_tick,
|
||||
priority: 1,
|
||||
resources: [CO_OWNED, ON, SHARED],
|
||||
},
|
||||
|
||||
TIM2: {
|
||||
enabled: true,
|
||||
path: tasks::tim2,
|
||||
priority: 1,
|
||||
resources: [CO_OWNED],
|
||||
},
|
||||
},
|
||||
|
|
|
@ -24,21 +24,18 @@ app! {
|
|||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
enabled: true,
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [LOW, HIGH],
|
||||
},
|
||||
|
||||
EXTI1: {
|
||||
enabled: true,
|
||||
path: exti1,
|
||||
priority: 2,
|
||||
resources: [LOW],
|
||||
},
|
||||
|
||||
EXTI2: {
|
||||
enabled: true,
|
||||
path: exti2,
|
||||
priority: 3,
|
||||
resources: [HIGH],
|
||||
|
|
|
@ -25,7 +25,6 @@ app! {
|
|||
},
|
||||
|
||||
TIM2: {
|
||||
enabled: true,
|
||||
path: tim2,
|
||||
priority: 1,
|
||||
resources: [COUNTER],
|
||||
|
|
|
@ -33,7 +33,6 @@ app! {
|
|||
// For interrupts the `enabled` field must be specified. It
|
||||
// indicates if the interrupt will be enabled or disabled once
|
||||
// `idle` starts
|
||||
enabled: true,
|
||||
path: tim2,
|
||||
priority: 1,
|
||||
resources: [COUNTER],
|
||||
|
|
|
@ -16,8 +16,39 @@ pub struct App {
|
|||
|
||||
pub type Tasks = HashMap<Ident, Task>;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum Exception {
|
||||
PENDSV,
|
||||
SVCALL,
|
||||
SYS_TICK,
|
||||
}
|
||||
|
||||
impl Exception {
|
||||
pub fn from(s: &str) -> Option<Self> {
|
||||
Some(match s {
|
||||
"PENDSV" => Exception::PENDSV,
|
||||
"SVCALL" => Exception::SVCALL,
|
||||
"SYS_TICK" => Exception::SYS_TICK,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn nr(&self) -> usize {
|
||||
match *self {
|
||||
Exception::PENDSV => 14,
|
||||
Exception::SVCALL => 11,
|
||||
Exception::SYS_TICK => 15,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Kind {
|
||||
Exception(Exception),
|
||||
Interrupt { enabled: bool },
|
||||
}
|
||||
|
||||
pub struct Task {
|
||||
pub enabled: Option<bool>,
|
||||
pub kind: Kind,
|
||||
pub path: Option<Path>,
|
||||
pub priority: u8,
|
||||
pub resources: Idents,
|
||||
|
@ -31,8 +62,13 @@ pub fn app(app: check::App) -> Result<App> {
|
|||
resources: app.resources,
|
||||
tasks: app.tasks
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k, ::check::task(v)))
|
||||
.collect(),
|
||||
.map(|(k, v)| {
|
||||
let v = ::check::task(k.as_ref(), v)
|
||||
.chain_err(|| format!("checking task `{}`", k))?;
|
||||
|
||||
Ok((k, v))
|
||||
})
|
||||
.collect::<Result<_>>()?,
|
||||
};
|
||||
|
||||
::check::resources(&app)
|
||||
|
@ -60,11 +96,34 @@ fn resources(app: &App) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn task(task: syntax::check::Task) -> Task {
|
||||
Task {
|
||||
enabled: task.enabled,
|
||||
fn task(name: &str, task: syntax::check::Task) -> Result<Task> {
|
||||
let kind = match Exception::from(name) {
|
||||
Some(e) => {
|
||||
ensure!(
|
||||
task.enabled.is_none(),
|
||||
"`enabled` field is not valid for exceptions"
|
||||
);
|
||||
|
||||
Kind::Exception(e)
|
||||
}
|
||||
None => {
|
||||
if task.enabled == Some(true) {
|
||||
bail!(
|
||||
"`enabled: true` is the default value; this line can be \
|
||||
omitted"
|
||||
);
|
||||
}
|
||||
|
||||
Kind::Interrupt {
|
||||
enabled: task.enabled.unwrap_or(true),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Task {
|
||||
kind,
|
||||
path: task.path,
|
||||
priority: task.priority.unwrap_or(1),
|
||||
resources: task.resources,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use quote::{Ident, Tokens};
|
|||
use syn::{Lit, StrStyle};
|
||||
|
||||
use analyze::{Ownership, Ownerships};
|
||||
use check::App;
|
||||
use check::{App, Kind};
|
||||
|
||||
fn krate() -> Ident {
|
||||
Ident::from("rtfm")
|
||||
|
@ -236,7 +236,23 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
|
|||
let mut exceptions = vec![];
|
||||
let mut interrupts = vec![];
|
||||
for (name, task) in &app.tasks {
|
||||
if let Some(enabled) = task.enabled {
|
||||
match task.kind {
|
||||
Kind::Exception(ref e) => {
|
||||
if exceptions.is_empty() {
|
||||
exceptions.push(quote! {
|
||||
let scb = &*#device::SCB.get();
|
||||
});
|
||||
}
|
||||
|
||||
let nr = e.nr();
|
||||
let priority = task.priority;
|
||||
exceptions.push(quote! {
|
||||
let prio_bits = #device::NVIC_PRIO_BITS;
|
||||
let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits);
|
||||
scb.shpr[#nr - 4].write(hw);
|
||||
});
|
||||
}
|
||||
Kind::Interrupt { enabled } => {
|
||||
// Interrupt. These can be enabled / disabled through the NVIC
|
||||
if interrupts.is_empty() {
|
||||
interrupts.push(quote! {
|
||||
|
@ -260,20 +276,7 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
|
|||
nvic.disable(#device::Interrupt::#name);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Exception
|
||||
if exceptions.is_empty() {
|
||||
exceptions.push(quote! {
|
||||
let scb = &*#device::SCB.get();
|
||||
});
|
||||
}
|
||||
|
||||
let priority = task.priority;
|
||||
exceptions.push(quote! {
|
||||
let prio_bits = #device::NVIC_PRIO_BITS;
|
||||
let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits);
|
||||
scb.shpr[#krate::Exception::#name.nr() - 4].write(hw);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
22
src/lib.rs
22
src/lib.rs
|
@ -140,25 +140,3 @@ where
|
|||
let nvic = unsafe { &*cortex_m::peripheral::NVIC.get() };
|
||||
nvic.set_pending(interrupt);
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[doc(hidden)]
|
||||
pub enum Exception {
|
||||
/// System service call via SWI instruction
|
||||
SVCALL,
|
||||
/// Pendable request for system service
|
||||
PENDSV,
|
||||
/// System tick timer
|
||||
SYS_TICK,
|
||||
}
|
||||
|
||||
impl Exception {
|
||||
#[doc(hidden)]
|
||||
pub fn nr(&self) -> usize {
|
||||
match *self {
|
||||
Exception::SVCALL => 11,
|
||||
Exception::PENDSV => 14,
|
||||
Exception::SYS_TICK => 15,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ app! {
|
|||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
enabled: true,
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [ON],
|
||||
|
|
|
@ -9,7 +9,6 @@ use rtfm::app;
|
|||
|
||||
app! {
|
||||
//~^ error proc macro panicked
|
||||
//~| help parsing
|
||||
device: stm32f103xx,
|
||||
|
||||
tasks: {
|
||||
|
|
|
@ -7,9 +7,7 @@ extern crate stm32f103xx;
|
|||
|
||||
use rtfm::app;
|
||||
|
||||
app! {
|
||||
//~^ error no associated item named `SYS_TICK` found for type
|
||||
//~| error no associated item named `SYS_TICK` found for type
|
||||
app! { //~ error proc macro panicked
|
||||
device: stm32f103xx,
|
||||
|
||||
tasks: {
|
||||
|
|
|
@ -7,14 +7,14 @@ extern crate stm32f103xx;
|
|||
|
||||
use rtfm::app;
|
||||
|
||||
app! { //~ error no associated item named `EXTI0` found for type
|
||||
app! {
|
||||
//~^ error no associated item named `EXTI33` found for type
|
||||
//~| error no associated item named `EXTI33` found for type
|
||||
device: stm32f103xx,
|
||||
|
||||
tasks: {
|
||||
// ERROR `enabled` needs to be specified for interrupts
|
||||
EXTI0: {
|
||||
priority: 1,
|
||||
},
|
||||
// ERROR this interrupt doesn't exist
|
||||
EXTI33: {},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -18,21 +18,18 @@ app! {
|
|||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
enabled: true,
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [MAX, ON],
|
||||
},
|
||||
|
||||
EXTI1: {
|
||||
enabled: true,
|
||||
path: exti1,
|
||||
priority: 2,
|
||||
resources: [ON],
|
||||
},
|
||||
|
||||
EXTI2: {
|
||||
enabled: true,
|
||||
path: exti2,
|
||||
priority: 16,
|
||||
resources: [MAX],
|
||||
|
|
|
@ -17,14 +17,12 @@ app! {
|
|||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
enabled: true,
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [STATE],
|
||||
},
|
||||
|
||||
EXTI1: {
|
||||
enabled: true,
|
||||
path: exti1,
|
||||
priority: 2,
|
||||
resources: [STATE],
|
||||
|
|
|
@ -17,7 +17,6 @@ app! { //~ error bound `rtfm::Threshold: core::marker::Send` is not satisfied
|
|||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
enabled: true,
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [TOKEN],
|
||||
|
|
|
@ -18,14 +18,12 @@ app! {
|
|||
|
||||
tasks: {
|
||||
EXTI0: {
|
||||
enabled: true,
|
||||
path: exti0,
|
||||
priority: 1,
|
||||
resources: [A, B],
|
||||
},
|
||||
|
||||
EXTI1: {
|
||||
enabled: true,
|
||||
path: exti1,
|
||||
priority: 2,
|
||||
resources: [A, B],
|
||||
|
|
Loading…
Reference in a new issue