diff --git a/CHANGELOG.md b/CHANGELOG.md index faecd10dc5..bb8f6ef99d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +- Move dispatchers from extern block to app argument. + ## [v0.5.5] - 2020-08-27 - Includes the previous soundness fix. diff --git a/book/en/src/migration/migration_v5.md b/book/en/src/migration/migration_v5.md index 1d83444e09..5cf818c516 100644 --- a/book/en/src/migration/migration_v5.md +++ b/book/en/src/migration/migration_v5.md @@ -6,6 +6,37 @@ This section describes how to upgrade from v0.5.x to v0.6.0 of the RTIC framewor Change the version of `cortex-m-rtic` to `"0.6.0"`. +## Move Dispatchers from `extern "C"` to app arguments. + +Change + +``` rust +#[rtic::app(/* .. */)] +const APP: () = { + [code here] + + // RTIC requires that unused interrupts are declared in an extern block when + // using software tasks; these free interrupts will be used to dispatch the + // software tasks. + extern "C" { + fn SSI0(); + fn QEI0(); + } +}; +``` + +into + +``` rust +#[rtic::app(/* .. */, dispatchers = [SSI0, QEI0])] +mod app { + [code here] +} +``` + +This works also for ram functions, see examples/ramfunc.rs + + ## Module instead of Const With the support of attributes on modules the `const APP` workaround is not needed. diff --git a/examples/baseline.rs b/examples/baseline.rs index 82f1887e65..17278748d5 100644 --- a/examples/baseline.rs +++ b/examples/baseline.rs @@ -8,7 +8,7 @@ use panic_semihosting as _; // NOTE: does NOT properly work on QEMU -#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; use lm3s6965::Interrupt; @@ -47,11 +47,4 @@ mod app { // `foo` inherits the baseline of `UART0`: its `start` time foo::spawn().unwrap(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/capacity.rs b/examples/capacity.rs index 29b4f04e26..b25a758446 100644 --- a/examples/capacity.rs +++ b/examples/capacity.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; use lm3s6965::Interrupt; @@ -40,11 +40,4 @@ mod app { debug::exit(debug::EXIT_SUCCESS); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/cfg-whole-task.rs b/examples/cfg-whole-task.rs index e225da3312..b19c280c9b 100644 --- a/examples/cfg-whole-task.rs +++ b/examples/cfg-whole-task.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] mod app { use cortex_m_semihosting::debug; #[cfg(debug_assertions)] @@ -83,12 +83,4 @@ mod app { ) .ok(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - fn QEI0(); - } } diff --git a/examples/cfg.rs b/examples/cfg.rs index fae13e5bcf..d3f2cea126 100644 --- a/examples/cfg.rs +++ b/examples/cfg.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] mod app { use cortex_m_semihosting::debug; #[cfg(debug_assertions)] @@ -62,12 +62,4 @@ mod app { ) .ok(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - fn QEI0(); - } } diff --git a/examples/double_schedule.rs b/examples/double_schedule.rs index 78eaac4996..32477efe9b 100644 --- a/examples/double_schedule.rs +++ b/examples/double_schedule.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])] mod app { use rtic::cyccnt::U32Ext; @@ -32,8 +32,4 @@ mod app { fn task2(_cx: task2::Context) { task1::schedule(_cx.scheduled + 100.cycles()).ok(); } - - extern "C" { - fn SSI0(); - } } diff --git a/examples/message.rs b/examples/message.rs index 4306430ffa..4c5d8997b0 100644 --- a/examples/message.rs +++ b/examples/message.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; @@ -45,11 +45,4 @@ mod app { foo::spawn().unwrap(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/not-sync.rs b/examples/not-sync.rs index d2616ee935..21c316ae14 100644 --- a/examples/not-sync.rs +++ b/examples/not-sync.rs @@ -12,7 +12,7 @@ pub struct NotSync { _0: PhantomData<*const ()>, } -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use super::NotSync; use core::marker::PhantomData; @@ -40,11 +40,4 @@ mod app { fn bar(c: bar::Context) { let _: &NotSync = c.resources.shared; } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/periodic.rs b/examples/periodic.rs index eedf720c53..3ff9c907cb 100644 --- a/examples/periodic.rs +++ b/examples/periodic.rs @@ -8,7 +8,7 @@ use panic_semihosting as _; // NOTE: does NOT work on QEMU! -#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::hprintln; use rtic::cyccnt::{Instant, U32Ext}; @@ -31,11 +31,4 @@ mod app { foo::schedule(cx.scheduled + PERIOD.cycles()).unwrap(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/pool.rs b/examples/pool.rs index fc740feafc..eaad9c09d6 100644 --- a/examples/pool.rs +++ b/examples/pool.rs @@ -15,7 +15,7 @@ use rtic::app; // Declare a pool of 128-byte memory blocks pool!(P: [u8; 128]); -#[app(device = lm3s6965)] +#[app(device = lm3s6965, dispatchers = [SSI0, QEI0])] mod app { use crate::{Box, Pool}; use cortex_m_semihosting::{debug, hprintln}; @@ -65,12 +65,4 @@ mod app { // this is done automatically so we can omit the call to `drop` // drop(x); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - fn QEI0(); - } } diff --git a/examples/ramfunc.rs b/examples/ramfunc.rs index 4d46c6dd38..b5aa17b949 100644 --- a/examples/ramfunc.rs +++ b/examples/ramfunc.rs @@ -7,7 +7,14 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app( + device = lm3s6965, + dispatchers = [ + UART0, + #[link_section = ".data.UART1"] + UART1 + ]) +] mod app { use cortex_m_semihosting::{debug, hprintln}; @@ -33,12 +40,4 @@ mod app { fn bar(_: bar::Context) { foo::spawn().unwrap(); } - - extern "C" { - fn UART0(); - - // run the task dispatcher from RAM - #[link_section = ".data.UART1"] - fn UART1(); - } } diff --git a/examples/schedule.rs b/examples/schedule.rs index f57f53f521..5f73c5003f 100644 --- a/examples/schedule.rs +++ b/examples/schedule.rs @@ -8,7 +8,7 @@ use panic_halt as _; // NOTE: does NOT work on QEMU! -#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])] mod app { use cortex_m::peripheral::DWT; use cortex_m_semihosting::hprintln; @@ -46,11 +46,4 @@ mod app { fn bar(_: bar::Context) { hprintln!("bar @ {:?}", Instant::now()).unwrap(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/spawn.rs b/examples/spawn.rs index 300b3b3a54..449fcfb9ae 100644 --- a/examples/spawn.rs +++ b/examples/spawn.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; @@ -26,11 +26,4 @@ mod app { } foo::spawn(2, 3).unwrap(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/spawn2.rs b/examples/spawn2.rs index 070223b897..c485b92278 100644 --- a/examples/spawn2.rs +++ b/examples/spawn2.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; @@ -32,11 +32,4 @@ mod app { hprintln!("foo2 {}", x).unwrap(); foo::spawn(x, 0).unwrap(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/t-cfg.rs b/examples/t-cfg.rs index 7076f5d71f..5bcef0af84 100644 --- a/examples/t-cfg.rs +++ b/examples/t-cfg.rs @@ -5,7 +5,7 @@ use panic_halt as _; -#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0, QEI0])] mod app { #[resources] struct Resources { @@ -47,12 +47,4 @@ mod app { #[cfg(never)] #[task] fn quux(_: quux::Context) {} - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - fn QEI0(); - } } diff --git a/examples/t-schedule-core-stable.rs b/examples/t-schedule-core-stable.rs index c2a8fdb54a..10539014a7 100644 --- a/examples/t-schedule-core-stable.rs +++ b/examples/t-schedule-core-stable.rs @@ -7,7 +7,7 @@ use panic_halt as _; -#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])] mod app { #[init] fn init(c: init::Context) -> init::LateResources { @@ -18,11 +18,4 @@ mod app { #[task] fn some_task(_: some_task::Context) {} - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs index b1faaa6d9c..9c94d1b427 100644 --- a/examples/t-schedule.rs +++ b/examples/t-schedule.rs @@ -7,7 +7,7 @@ use panic_halt as _; -#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])] mod app { use rtic::cyccnt::{Instant, U32Ext as _}; @@ -57,11 +57,4 @@ mod app { #[task] fn baz(_: baz::Context, _x: u32, _y: u32) {} - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/t-spawn.rs b/examples/t-spawn.rs index cf850e46e7..c9949ef9b9 100644 --- a/examples/t-spawn.rs +++ b/examples/t-spawn.rs @@ -7,7 +7,7 @@ use panic_halt as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { #[init] fn init(_: init::Context) -> init::LateResources { @@ -55,11 +55,4 @@ mod app { #[task] fn baz(_: baz::Context, _x: u32, _y: u32) {} - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/t-stask-main.rs b/examples/t-stask-main.rs index 56dc1af562..034ad7c56e 100644 --- a/examples/t-stask-main.rs +++ b/examples/t-stask-main.rs @@ -5,7 +5,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::debug; @@ -20,11 +20,4 @@ mod app { fn taskmain(_: taskmain::Context) { debug::exit(debug::EXIT_SUCCESS); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/examples/task.rs b/examples/task.rs index 60591b9f46..5e4769a59b 100644 --- a/examples/task.rs +++ b/examples/task.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])] mod app { use cortex_m_semihosting::{debug, hprintln}; @@ -47,12 +47,4 @@ mod app { fn baz(_: baz::Context) { hprintln!("baz").unwrap(); } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - fn QEI0(); - } } diff --git a/examples/types.rs b/examples/types.rs index cb93a36f58..bcdd30a930 100644 --- a/examples/types.rs +++ b/examples/types.rs @@ -7,7 +7,7 @@ use panic_semihosting as _; -#[rtic::app(device = lm3s6965, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] +#[rtic::app(device = lm3s6965, peripherals = true, monotonic = rtic::cyccnt::CYCCNT, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::debug; use rtic::cyccnt; @@ -48,11 +48,4 @@ mod app { let _: resources::shared = cx.resources.shared; let _: foo::Resources = cx.resources; } - - // RTIC requires that unused interrupts are declared in an extern block when - // using software tasks; these free interrupts will be used to dispatch the - // software tasks. - extern "C" { - fn SSI0(); - } } diff --git a/macros/src/analyze.rs b/macros/src/analyze.rs index 2301167b02..6b26138879 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, - pub interrupts: BTreeMap, + pub interrupts: BTreeMap, } 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, app: &App) -> P { - 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::>(); - 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 = 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 cfc18d3de5..e3161cb950 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, 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> { +pub fn app(app: &App, _analysis: &Analysis) -> parse::Result { // 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> { .collect::>(); 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> { 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> { 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> { } } - 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 b975536838..8309473acb 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 a76f622eff..a6c695f191 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::now();)), Some(quote!(, instant)), diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index a5b61394ea..838a989f26 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 17c9c2f4aa..969de84a67 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>(); - 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 0dd98f0126..fa2c7b3699 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 { 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 rtic::Mutex for #path<'a> { diff --git a/macros/src/tests/single.rs b/macros/src/tests/single.rs index 97cbbb3f3a..8c026e9925 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"); } diff --git a/ui/single/extern-interrupt-not-enough.stderr b/ui/single/extern-interrupt-not-enough.stderr index 73ce7ad008..14f8fe9c36 100644 --- a/ui/single/extern-interrupt-not-enough.stderr +++ b/ui/single/extern-interrupt-not-enough.stderr @@ -1,4 +1,4 @@ -error: not enough `extern` interrupts to dispatch all software tasks (need: 1; given: 0) +error: not enough interrupts to dispatch all software tasks (need: 1; given: 0) --> $DIR/extern-interrupt-not-enough.rs:6:8 | 6 | fn a(_: a::Context) {} diff --git a/ui/single/extern-interrupt-used.rs b/ui/single/extern-interrupt-used.rs index 89c2378460..2ba316824c 100644 --- a/ui/single/extern-interrupt-used.rs +++ b/ui/single/extern-interrupt-used.rs @@ -1,6 +1,6 @@ #![no_main] -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [UART0])] mod app { #[task(binds = UART0)] fn a(_: a::Context) {} diff --git a/ui/single/extern-interrupt-used.stderr b/ui/single/extern-interrupt-used.stderr index fb0ff5bc7c..b4d8d16076 100644 --- a/ui/single/extern-interrupt-used.stderr +++ b/ui/single/extern-interrupt-used.stderr @@ -1,4 +1,4 @@ -error: `extern` interrupts can't be used as hardware tasks +error: dispatcher interrupts can't be used as hardware tasks --> $DIR/extern-interrupt-used.rs:5:20 | 5 | #[task(binds = UART0)] diff --git a/ui/single/locals-cfg.rs b/ui/single/locals-cfg.rs index 45a7a9116a..3bfdaa1e0c 100644 --- a/ui/single/locals-cfg.rs +++ b/ui/single/locals-cfg.rs @@ -1,7 +1,7 @@ #![no_main] use panic_halt as _; -#[rtic::app(device = lm3s6965)] +#[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { #[init] fn init(_: init::Context) -> init::LateResources { @@ -46,8 +46,4 @@ mod app { FOO; } - - extern "C" { - fn UART1(); - } }