diff options
Diffstat (limited to 'macros')
-rw-r--r-- | macros/src/analyze.rs | 24 | ||||
-rw-r--r-- | macros/src/check.rs | 79 | ||||
-rw-r--r-- | macros/src/codegen.rs | 2 | ||||
-rw-r--r-- | macros/src/codegen/dispatchers.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/hardware_tasks.rs | 2 | ||||
-rw-r--r-- | macros/src/codegen/module.rs | 20 | ||||
-rw-r--r-- | macros/src/codegen/pre_init.rs | 24 | ||||
-rw-r--r-- | macros/src/codegen/software_tasks.rs | 2 | ||||
-rw-r--r-- | macros/src/codegen/timer_queue.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/util.rs | 2 | ||||
-rw-r--r-- | macros/src/tests/single.rs | 13 |
11 files changed, 60 insertions, 116 deletions
diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index 2301167b..6b261388 100644 --- a/macros/src/analyze.rs +++ b/macros/src/analyze.rs @@ -3,7 +3,7 @@ use std::collections::{BTreeMap, BTreeSet}; use rtic_syntax::{ analyze::{self, Priority}, - ast::App, + ast::{App, ExternInterrupt}, P, }; use syn::Ident; @@ -11,7 +11,7 @@ use syn::Ident; /// Extend the upstream `Analysis` struct with our field pub struct Analysis { parent: P<analyze::Analysis>, - pub interrupts: BTreeMap<Priority, Ident>, + pub interrupts: BTreeMap<Priority, (Ident, ExternInterrupt)>, } impl ops::Deref for Analysis { @@ -22,23 +22,23 @@ impl ops::Deref for Analysis { } } -// Assign an `extern` interrupt to each priority level +// Assign an interrupt to each priority level pub fn app(analysis: P<analyze::Analysis>, app: &App) -> P<Analysis> { - let mut interrupts = BTreeMap::new(); + // the set of priorities (each priority only once) let priorities = app .software_tasks .values() .map(|task| task.args.priority) .collect::<BTreeSet<_>>(); - if !priorities.is_empty() { - interrupts = priorities - .iter() - .cloned() - .rev() - .zip(app.extern_interrupts.keys().cloned()) - .collect(); - } + // map from priorities to interrupts (holding name and attributes) + let interrupts: BTreeMap<Priority, _> = priorities + .iter() + .cloned() + .rev() + .zip(&app.args.extern_interrupts) + .map(|(p, (id, ext))| (p, (id.clone(), ext.clone()))) + .collect(); P::new(Analysis { parent: analysis, diff --git a/macros/src/check.rs b/macros/src/check.rs index cfc18d3d..e3161cb9 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -1,28 +1,19 @@ use std::collections::HashSet; use proc_macro2::Span; -use rtic_syntax::{ - analyze::Analysis, - ast::{App, CustomArg}, -}; +use rtic_syntax::{analyze::Analysis, ast::App}; use syn::{parse, Path}; -pub struct Extra<'a> { - pub device: &'a Path, - pub monotonic: Option<&'a Path>, +pub struct Extra { + pub device: Path, + pub monotonic: Option<Path>, pub peripherals: bool, } -impl<'a> Extra<'a> { - pub fn monotonic(&self) -> &'a Path { - self.monotonic.expect("UNREACHABLE") - } -} - -pub fn app<'a>(app: &'a App, _analysis: &Analysis) -> parse::Result<Extra<'a>> { +pub fn app(app: &App, _analysis: &Analysis) -> parse::Result<Extra> { // Check that external (device-specific) interrupts are not named after known (Cortex-M) // exceptions - for name in app.extern_interrupts.keys() { + for name in app.args.extern_interrupts.keys() { let name_s = name.to_string(); match &*name_s { @@ -51,11 +42,11 @@ pub fn app<'a>(app: &'a App, _analysis: &Analysis) -> parse::Result<Extra<'a>> { .collect::<HashSet<_>>(); let need = priorities.len(); - let given = app.extern_interrupts.len(); + let given = app.args.extern_interrupts.len(); if need > given { let s = { format!( - "not enough `extern` interrupts to dispatch \ + "not enough interrupts to dispatch \ all software tasks (need: {}; given: {})", need, given ) @@ -66,52 +57,6 @@ pub fn app<'a>(app: &'a App, _analysis: &Analysis) -> parse::Result<Extra<'a>> { return Err(parse::Error::new(first.unwrap().span(), &s)); } - let mut device = None; - let mut monotonic = None; - let mut peripherals = false; - - for (k, v) in &app.args.custom { - let ks = k.to_string(); - - match &*ks { - "device" => match v { - CustomArg::Path(p) => device = Some(p), - - _ => { - return Err(parse::Error::new( - k.span(), - "unexpected argument value; this should be a path", - )); - } - }, - - "monotonic" => match v { - CustomArg::Path(p) => monotonic = Some(p), - - _ => { - return Err(parse::Error::new( - k.span(), - "unexpected argument value; this should be a path", - )); - } - }, - - "peripherals" => match v { - CustomArg::Bool(x) => peripherals = *x, - _ => { - return Err(parse::Error::new( - k.span(), - "unexpected argument value; this should be a boolean", - )); - } - }, - - _ => { - return Err(parse::Error::new(k.span(), "unexpected argument")); - } - } - } - // Check that all exceptions are valid; only exceptions with configurable priorities are // accepted for (name, task) in &app.hardware_tasks { @@ -119,7 +64,7 @@ pub fn app<'a>(app: &'a App, _analysis: &Analysis) -> parse::Result<Extra<'a>> { match &*name_s { "SysTick" => { // If the timer queue is used, then SysTick is unavailable - if monotonic.is_some() { + if app.args.monotonic.is_some() { return Err(parse::Error::new( name.span(), "this exception can't be used because it's being used by the runtime", @@ -140,11 +85,11 @@ pub fn app<'a>(app: &'a App, _analysis: &Analysis) -> parse::Result<Extra<'a>> { } } - if let Some(device) = device { + if let Some(device) = app.args.device.clone() { Ok(Extra { device, - monotonic, - peripherals, + monotonic: app.args.monotonic.clone(), + peripherals: app.args.peripherals, }) } else { Err(parse::Error::new( diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index b9755368..8309473a 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -86,7 +86,7 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let user_imports = &app.user_imports; let user_code = &app.user_code; let name = &app.name; - let device = extra.device; + let device = &extra.device; // Get the list of all tasks // Currently unused, might be useful diff --git a/macros/src/codegen/dispatchers.rs b/macros/src/codegen/dispatchers.rs index a76f622e..a6c695f1 100644 --- a/macros/src/codegen/dispatchers.rs +++ b/macros/src/codegen/dispatchers.rs @@ -119,11 +119,13 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream )); let doc = format!("Interrupt handler to dispatch tasks at priority {}", level); - let interrupt = util::suffixed(&interrupts[&level].to_string()); + let interrupt = util::suffixed(&interrupts[&level].0.to_string()); + let attribute = &interrupts[&level].1.attrs; items.push(quote!( #[allow(non_snake_case)] #[doc = #doc] #[no_mangle] + #(#attribute)* unsafe fn #interrupt() { /// The priority of this interrupt handler const PRIORITY: u8 = #level; diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs index bc2e1203..e5a8deb9 100644 --- a/macros/src/codegen/hardware_tasks.rs +++ b/macros/src/codegen/hardware_tasks.rs @@ -29,7 +29,7 @@ pub fn codegen( let mut user_tasks = vec![]; for (name, task) in &app.hardware_tasks { - let (let_instant, instant) = if let Some(m) = extra.monotonic { + let (let_instant, instant) = if let Some(ref m) = extra.monotonic { ( Some(quote!(let instant = <#m as rtic::Monotonic>::now();)), Some(quote!(, instant)), diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index a5b61394..838a989f 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -23,7 +23,7 @@ pub fn codegen( let mut lt = None; match ctxt { Context::Init => { - if let Some(m) = extra.monotonic { + if let Some(m) = &extra.monotonic { fields.push(quote!( /// System start time = `Instant(0 /* cycles */)` pub start: <#m as rtic::Monotonic>::Instant @@ -43,7 +43,7 @@ pub fn codegen( } if extra.peripherals { - let device = extra.device; + let device = &extra.device; fields.push(quote!( /// Device peripherals @@ -67,7 +67,7 @@ pub fn codegen( Context::Idle => {} Context::HardwareTask(..) => { - if let Some(m) = extra.monotonic { + if let Some(m) = &extra.monotonic { fields.push(quote!( /// Time at which this handler started executing pub start: <#m as rtic::Monotonic>::Instant @@ -80,7 +80,7 @@ pub fn codegen( } Context::SoftwareTask(..) => { - if let Some(m) = extra.monotonic { + if let Some(m) = &extra.monotonic { fields.push(quote!( /// The time at which this task was scheduled to run pub scheduled: <#m as rtic::Monotonic>::Instant @@ -162,7 +162,7 @@ pub fn codegen( }; let instant = if needs_instant { - let m = extra.monotonic(); + let m = extra.monotonic.clone().expect("RTIC-ICE: UNREACHABLE"); Some(quote!(, instant: <#m as rtic::Monotonic>::Instant)) } else { @@ -205,9 +205,13 @@ pub fn codegen( let app_name = &app.name; let app_path = quote! {crate::#app_name}; - let device = extra.device; + let device = &extra.device; let enum_ = util::interrupt_ident(); - let interrupt = &analysis.interrupts.get(&priority); + let interrupt = &analysis + .interrupts + .get(&priority) + .expect("RTIC-ICE: interrupt identifer not found") + .0; // Spawn caller items.push(quote!( @@ -240,7 +244,7 @@ pub fn codegen( })); // Schedule caller - if let Some(m) = extra.monotonic { + if let Some(m) = &extra.monotonic { let instants = util::instants_ident(name); let tq = util::tq_ident(); diff --git a/macros/src/codegen/pre_init.rs b/macros/src/codegen/pre_init.rs index 17c9c2f4..969de84a 100644 --- a/macros/src/codegen/pre_init.rs +++ b/macros/src/codegen/pre_init.rs @@ -26,22 +26,20 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream let mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().into(); )); - let device = extra.device; + let device = &extra.device; let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS); + let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); + // Unmask interrupts and set their priorities - for (&priority, name) in analysis - .interrupts - .iter() - .chain(app.hardware_tasks.values().flat_map(|task| { - if !util::is_exception(&task.args.binds) { - Some((&task.args.priority, &task.args.binds)) - } else { - // We do exceptions in another pass - None - } - })) - { + for (&priority, name) in interrupt_ids.chain(app.hardware_tasks.values().flat_map(|task| { + if !util::is_exception(&task.args.binds) { + Some((&task.args.priority, &task.args.binds)) + } else { + // We do exceptions in another pass + None + } + })) { // Compile time assert that this priority is supported by the device stmts.push(quote!(let _ = [(); ((1 << #nvic_prio_bits) - #priority as usize)];)); diff --git a/macros/src/codegen/software_tasks.rs b/macros/src/codegen/software_tasks.rs index 7cccd8c4..dfba193b 100644 --- a/macros/src/codegen/software_tasks.rs +++ b/macros/src/codegen/software_tasks.rs @@ -57,7 +57,7 @@ pub fn codegen( .map(|_| quote!(core::mem::MaybeUninit::uninit())) .collect::<Vec<_>>(); - if let Some(m) = extra.monotonic { + if let Some(m) = &extra.monotonic { let instants = util::instants_ident(name); let uninit = mk_uninit(); diff --git a/macros/src/codegen/timer_queue.rs b/macros/src/codegen/timer_queue.rs index 0dd98f01..fa2c7b36 100644 --- a/macros/src/codegen/timer_queue.rs +++ b/macros/src/codegen/timer_queue.rs @@ -8,7 +8,7 @@ use crate::{analyze::Analysis, check::Extra, codegen::util}; pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream2> { let mut items = vec![]; - if let Some(m) = extra.monotonic { + if let Some(m) = &extra.monotonic { let t = util::schedule_t_ident(); // Enumeration of `schedule`-able tasks @@ -71,7 +71,7 @@ pub fn codegen(app: &App, analysis: &Analysis, extra: &Extra) -> Vec<TokenStream let rq = util::rq_ident(priority); let rqt = util::spawn_t_ident(priority); let enum_ = util::interrupt_ident(); - let interrupt = &analysis.interrupts.get(&priority); + let interrupt = &analysis.interrupts.get(&priority).expect("RTIC-ICE: interrupt not found").0; let pend = { quote!( diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index 0625e49d..fb8f1a84 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -46,7 +46,7 @@ pub fn impl_mutex( (quote!(#name), quote!(self.priority)) }; - let device = extra.device; + let device = &extra.device; quote!( #(#cfgs)* impl<'a> rtic::Mutex for #path<'a> { diff --git a/macros/src/tests/single.rs b/macros/src/tests/single.rs index 97cbbb3f..8c026e99 100644 --- a/macros/src/tests/single.rs +++ b/macros/src/tests/single.rs @@ -6,7 +6,8 @@ fn analyze() { let mut settings = Settings::default(); settings.parse_extern_interrupt = true; let (app, analysis) = rtic_syntax::parse2( - quote!(device = pac), + // First interrupt is assigned to the highest priority dispatcher + quote!(device = pac, dispatchers = [B, A]), quote!( mod app { #[task(priority = 1)] @@ -14,12 +15,6 @@ fn analyze() { #[task(priority = 2)] fn b(_: b::Context) {} - - // First interrupt is assigned to the highest priority dispatcher - extern "C" { - fn B(); - fn A(); - } } ), settings, @@ -29,6 +24,6 @@ fn analyze() { let analysis = crate::analyze::app(analysis, &app); let interrupts = &analysis.interrupts; assert_eq!(interrupts.len(), 2); - assert_eq!(interrupts[&2].to_string(), "B"); - assert_eq!(interrupts[&1].to_string(), "A"); + assert_eq!(interrupts[&2].0.to_string(), "B"); + assert_eq!(interrupts[&1].0.to_string(), "A"); } |