Skip to content
Snippets Groups Projects
Commit d396da59 authored by Jorge Aparicio's avatar Jorge Aparicio
Browse files

make task.$T.enabled optional

and move the logic that differentiates interrupts from exceptions from the crate
to the procedural macro logic
parent ad2a523c
No related branches found
No related tags found
No related merge requests found
...@@ -37,7 +37,9 @@ app! { ...@@ -37,7 +37,9 @@ app! {
}, },
TIM2: { 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, path: tim2,
priority: 1, priority: 1,
resources: [CO_OWNED], resources: [CO_OWNED],
......
...@@ -15,14 +15,12 @@ app! { ...@@ -15,14 +15,12 @@ app! {
tasks: { tasks: {
EXTI0: { EXTI0: {
enabled: true,
path: exti0, path: exti0,
priority: 1, priority: 1,
resources: [GPIOA, SPI1], resources: [GPIOA, SPI1],
}, },
EXTI1: { EXTI1: {
enabled: true,
path: exti1, path: exti1,
priority: 2, priority: 2,
resources: [GPIOA, SPI1], resources: [GPIOA, SPI1],
......
...@@ -31,14 +31,11 @@ app! { ...@@ -31,14 +31,11 @@ app! {
tasks: { tasks: {
SYS_TICK: { SYS_TICK: {
path: tasks::sys_tick, path: tasks::sys_tick,
priority: 1,
resources: [CO_OWNED, ON, SHARED], resources: [CO_OWNED, ON, SHARED],
}, },
TIM2: { TIM2: {
enabled: true,
path: tasks::tim2, path: tasks::tim2,
priority: 1,
resources: [CO_OWNED], resources: [CO_OWNED],
}, },
}, },
......
...@@ -24,21 +24,18 @@ app! { ...@@ -24,21 +24,18 @@ app! {
tasks: { tasks: {
EXTI0: { EXTI0: {
enabled: true,
path: exti0, path: exti0,
priority: 1, priority: 1,
resources: [LOW, HIGH], resources: [LOW, HIGH],
}, },
EXTI1: { EXTI1: {
enabled: true,
path: exti1, path: exti1,
priority: 2, priority: 2,
resources: [LOW], resources: [LOW],
}, },
EXTI2: { EXTI2: {
enabled: true,
path: exti2, path: exti2,
priority: 3, priority: 3,
resources: [HIGH], resources: [HIGH],
......
...@@ -25,7 +25,6 @@ app! { ...@@ -25,7 +25,6 @@ app! {
}, },
TIM2: { TIM2: {
enabled: true,
path: tim2, path: tim2,
priority: 1, priority: 1,
resources: [COUNTER], resources: [COUNTER],
......
...@@ -33,7 +33,6 @@ app! { ...@@ -33,7 +33,6 @@ app! {
// For interrupts the `enabled` field must be specified. It // For interrupts the `enabled` field must be specified. It
// indicates if the interrupt will be enabled or disabled once // indicates if the interrupt will be enabled or disabled once
// `idle` starts // `idle` starts
enabled: true,
path: tim2, path: tim2,
priority: 1, priority: 1,
resources: [COUNTER], resources: [COUNTER],
......
...@@ -16,8 +16,39 @@ pub struct App { ...@@ -16,8 +16,39 @@ pub struct App {
pub type Tasks = HashMap<Ident, Task>; 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 struct Task {
pub enabled: Option<bool>, pub kind: Kind,
pub path: Option<Path>, pub path: Option<Path>,
pub priority: u8, pub priority: u8,
pub resources: Idents, pub resources: Idents,
...@@ -31,8 +62,13 @@ pub fn app(app: check::App) -> Result<App> { ...@@ -31,8 +62,13 @@ pub fn app(app: check::App) -> Result<App> {
resources: app.resources, resources: app.resources,
tasks: app.tasks tasks: app.tasks
.into_iter() .into_iter()
.map(|(k, v)| (k, ::check::task(v))) .map(|(k, v)| {
.collect(), let v = ::check::task(k.as_ref(), v)
.chain_err(|| format!("checking task `{}`", k))?;
Ok((k, v))
})
.collect::<Result<_>>()?,
}; };
::check::resources(&app) ::check::resources(&app)
...@@ -60,11 +96,34 @@ fn resources(app: &App) -> Result<()> { ...@@ -60,11 +96,34 @@ fn resources(app: &App) -> Result<()> {
Ok(()) Ok(())
} }
fn task(task: syntax::check::Task) -> Task { fn task(name: &str, task: syntax::check::Task) -> Result<Task> {
Task { let kind = match Exception::from(name) {
enabled: task.enabled, 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, path: task.path,
priority: task.priority.unwrap_or(1), priority: task.priority.unwrap_or(1),
resources: task.resources, resources: task.resources,
} })
} }
...@@ -2,7 +2,7 @@ use quote::{Ident, Tokens}; ...@@ -2,7 +2,7 @@ use quote::{Ident, Tokens};
use syn::{Lit, StrStyle}; use syn::{Lit, StrStyle};
use analyze::{Ownership, Ownerships}; use analyze::{Ownership, Ownerships};
use check::App; use check::{App, Kind};
fn krate() -> Ident { fn krate() -> Ident {
Ident::from("rtfm") Ident::from("rtfm")
...@@ -236,7 +236,23 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) { ...@@ -236,7 +236,23 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
let mut exceptions = vec![]; let mut exceptions = vec![];
let mut interrupts = vec![]; let mut interrupts = vec![];
for (name, task) in &app.tasks { 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 // Interrupt. These can be enabled / disabled through the NVIC
if interrupts.is_empty() { if interrupts.is_empty() {
interrupts.push(quote! { interrupts.push(quote! {
...@@ -260,20 +276,7 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) { ...@@ -260,20 +276,7 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
nvic.disable(#device::Interrupt::#name); 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);
});
} }
} }
......
...@@ -140,25 +140,3 @@ where ...@@ -140,25 +140,3 @@ where
let nvic = unsafe { &*cortex_m::peripheral::NVIC.get() }; let nvic = unsafe { &*cortex_m::peripheral::NVIC.get() };
nvic.set_pending(interrupt); 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! { ...@@ -21,7 +21,6 @@ app! {
tasks: { tasks: {
EXTI0: { EXTI0: {
enabled: true,
path: exti0, path: exti0,
priority: 1, priority: 1,
resources: [ON], resources: [ON],
......
...@@ -9,7 +9,6 @@ use rtfm::app; ...@@ -9,7 +9,6 @@ use rtfm::app;
app! { app! {
//~^ error proc macro panicked //~^ error proc macro panicked
//~| help parsing
device: stm32f103xx, device: stm32f103xx,
tasks: { tasks: {
......
...@@ -7,9 +7,7 @@ extern crate stm32f103xx; ...@@ -7,9 +7,7 @@ extern crate stm32f103xx;
use rtfm::app; use rtfm::app;
app! { app! { //~ error proc macro panicked
//~^ error no associated item named `SYS_TICK` found for type
//~| error no associated item named `SYS_TICK` found for type
device: stm32f103xx, device: stm32f103xx,
tasks: { tasks: {
......
...@@ -7,14 +7,14 @@ extern crate stm32f103xx; ...@@ -7,14 +7,14 @@ extern crate stm32f103xx;
use rtfm::app; 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, device: stm32f103xx,
tasks: { tasks: {
// ERROR `enabled` needs to be specified for interrupts // ERROR this interrupt doesn't exist
EXTI0: { EXTI33: {},
priority: 1,
},
}, },
} }
......
...@@ -18,21 +18,18 @@ app! { ...@@ -18,21 +18,18 @@ app! {
tasks: { tasks: {
EXTI0: { EXTI0: {
enabled: true,
path: exti0, path: exti0,
priority: 1, priority: 1,
resources: [MAX, ON], resources: [MAX, ON],
}, },
EXTI1: { EXTI1: {
enabled: true,
path: exti1, path: exti1,
priority: 2, priority: 2,
resources: [ON], resources: [ON],
}, },
EXTI2: { EXTI2: {
enabled: true,
path: exti2, path: exti2,
priority: 16, priority: 16,
resources: [MAX], resources: [MAX],
......
...@@ -17,14 +17,12 @@ app! { ...@@ -17,14 +17,12 @@ app! {
tasks: { tasks: {
EXTI0: { EXTI0: {
enabled: true,
path: exti0, path: exti0,
priority: 1, priority: 1,
resources: [STATE], resources: [STATE],
}, },
EXTI1: { EXTI1: {
enabled: true,
path: exti1, path: exti1,
priority: 2, priority: 2,
resources: [STATE], resources: [STATE],
......
...@@ -17,7 +17,6 @@ app! { //~ error bound `rtfm::Threshold: core::marker::Send` is not satisfied ...@@ -17,7 +17,6 @@ app! { //~ error bound `rtfm::Threshold: core::marker::Send` is not satisfied
tasks: { tasks: {
EXTI0: { EXTI0: {
enabled: true,
path: exti0, path: exti0,
priority: 1, priority: 1,
resources: [TOKEN], resources: [TOKEN],
......
...@@ -18,14 +18,12 @@ app! { ...@@ -18,14 +18,12 @@ app! {
tasks: { tasks: {
EXTI0: { EXTI0: {
enabled: true,
path: exti0, path: exti0,
priority: 1, priority: 1,
resources: [A, B], resources: [A, B],
}, },
EXTI1: { EXTI1: {
enabled: true,
path: exti1, path: exti1,
priority: 2, priority: 2,
resources: [A, B], resources: [A, B],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment