diff options
Diffstat (limited to 'macros/src')
-rw-r--r-- | macros/src/check.rs | 73 | ||||
-rw-r--r-- | macros/src/trans.rs | 69 |
2 files changed, 102 insertions, 40 deletions
diff --git a/macros/src/check.rs b/macros/src/check.rs index 571f2351..e4a716bc 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -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, - } + }) } diff --git a/macros/src/trans.rs b/macros/src/trans.rs index 468d9675..02b5e8cd 100644 --- a/macros/src/trans.rs +++ b/macros/src/trans.rs @@ -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,44 +236,47 @@ 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 { - // Interrupt. These can be enabled / disabled through the NVIC - if interrupts.is_empty() { - interrupts.push(quote! { - let nvic = &*#device::NVIC.get(); + 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! { + let nvic = &*#device::NVIC.get(); + }); + } - let priority = task.priority; - interrupts.push(quote! { - let prio_bits = #device::NVIC_PRIO_BITS; - let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits); - nvic.set_priority(#device::Interrupt::#name, hw); - }); - - if enabled { - interrupts.push(quote! { - nvic.enable(#device::Interrupt::#name); - }); - } else { + let priority = task.priority; interrupts.push(quote! { - nvic.disable(#device::Interrupt::#name); + let prio_bits = #device::NVIC_PRIO_BITS; + let hw = ((1 << prio_bits) - #priority) << (8 - prio_bits); + nvic.set_priority(#device::Interrupt::#name, hw); }); - } - } 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); - }); + if enabled { + interrupts.push(quote! { + nvic.enable(#device::Interrupt::#name); + }); + } else { + interrupts.push(quote! { + nvic.disable(#device::Interrupt::#name); + }); + } + } } } |