aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--book/en/src/migration/migration_v5.md31
-rw-r--r--examples/baseline.rs9
-rw-r--r--examples/capacity.rs9
-rw-r--r--examples/cfg-whole-task.rs10
-rw-r--r--examples/cfg.rs10
-rw-r--r--examples/double_schedule.rs6
-rw-r--r--examples/message.rs9
-rw-r--r--examples/not-sync.rs9
-rw-r--r--examples/periodic.rs9
-rw-r--r--examples/pool.rs10
-rw-r--r--examples/ramfunc.rs17
-rw-r--r--examples/schedule.rs9
-rw-r--r--examples/spawn.rs9
-rw-r--r--examples/spawn2.rs9
-rw-r--r--examples/t-cfg.rs10
-rw-r--r--examples/t-schedule-core-stable.rs9
-rw-r--r--examples/t-schedule.rs9
-rw-r--r--examples/t-spawn.rs9
-rw-r--r--examples/t-stask-main.rs9
-rw-r--r--examples/task.rs10
-rw-r--r--examples/types.rs9
-rw-r--r--macros/src/analyze.rs24
-rw-r--r--macros/src/check.rs79
-rw-r--r--macros/src/codegen.rs2
-rw-r--r--macros/src/codegen/dispatchers.rs4
-rw-r--r--macros/src/codegen/hardware_tasks.rs2
-rw-r--r--macros/src/codegen/module.rs20
-rw-r--r--macros/src/codegen/pre_init.rs24
-rw-r--r--macros/src/codegen/software_tasks.rs2
-rw-r--r--macros/src/codegen/timer_queue.rs4
-rw-r--r--macros/src/codegen/util.rs2
-rw-r--r--macros/src/tests/single.rs13
-rw-r--r--ui/single/extern-interrupt-not-enough.stderr2
-rw-r--r--ui/single/extern-interrupt-used.rs2
-rw-r--r--ui/single/extern-interrupt-used.stderr2
-rw-r--r--ui/single/locals-cfg.rs6
37 files changed, 124 insertions, 287 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index faecd10d..bb8f6ef9 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 1d83444e..5cf818c5 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 82f1887e..17278748 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 29b4f04e..b25a7584 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 e225da33..b19c280c 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 fae13e5b..d3f2cea1 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 78eaac49..32477efe 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 4306430f..4c5d8997 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 d2616ee9..21c316ae 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 eedf720c..3ff9c907 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 fc740fea..eaad9c09 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 4d46c6dd..b5aa17b9 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 f57f53f5..5f73c500 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 300b3b3a..449fcfb9 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 070223b8..c485b922 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 7076f5d7..5bcef0af 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 c2a8fdb5..10539014 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 b1faaa6d..9c94d1b4 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 cf850e46..c9949ef9 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 56dc1af5..034ad7c5 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 60591b9f..5e4769a5 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 cb93a36f..bcdd30a9 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 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");
}
diff --git a/ui/single/extern-interrupt-not-enough.stderr b/ui/single/extern-interrupt-not-enough.stderr
index 73ce7ad0..14f8fe9c 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 89c23784..2ba31682 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 fb0ff5bc..b4d8d160 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 45a7a911..3bfdaa1e 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();
- }
}