aboutsummaryrefslogtreecommitdiff
path: root/rtic-macros/src/check.rs
diff options
context:
space:
mode:
authorHenrik Tjäder <henrik@tjaders.com>2023-02-04 16:47:17 +0100
committerHenrik Tjäder <henrik@tjaders.com>2023-03-01 00:35:13 +0100
commit9e445b3583c15c7701f3167eaa8dfe4afd541691 (patch)
tree167565d51598f42c0454d60b34e1170589ae1056 /rtic-macros/src/check.rs
parent4124fbdd61ff823c6217a2a16ebb4d813146116c (diff)
Move rtic macros to repo root, tune xtask
Diffstat (limited to 'rtic-macros/src/check.rs')
-rw-r--r--rtic-macros/src/check.rs70
1 files changed, 70 insertions, 0 deletions
diff --git a/rtic-macros/src/check.rs b/rtic-macros/src/check.rs
new file mode 100644
index 0000000..a05c82e
--- /dev/null
+++ b/rtic-macros/src/check.rs
@@ -0,0 +1,70 @@
+use std::collections::HashSet;
+
+use crate::syntax::ast::App;
+use syn::parse;
+
+pub fn app(app: &App) -> parse::Result<()> {
+ // Check that external (device-specific) interrupts are not named after known (Cortex-M)
+ // exceptions
+ for name in app.args.dispatchers.keys() {
+ let name_s = name.to_string();
+
+ match &*name_s {
+ "NonMaskableInt" | "HardFault" | "MemoryManagement" | "BusFault" | "UsageFault"
+ | "SecureFault" | "SVCall" | "DebugMonitor" | "PendSV" | "SysTick" => {
+ return Err(parse::Error::new(
+ name.span(),
+ "Cortex-M exceptions can't be used as `extern` interrupts",
+ ));
+ }
+
+ _ => {}
+ }
+ }
+
+ // Check that there are enough external interrupts to dispatch the software tasks and the timer
+ // queue handler
+ let mut first = None;
+ let priorities = app
+ .software_tasks
+ .iter()
+ .map(|(name, task)| {
+ first = Some(name);
+ task.args.priority
+ })
+ .filter(|prio| *prio > 0)
+ .collect::<HashSet<_>>();
+
+ let need = priorities.len();
+ let given = app.args.dispatchers.len();
+ if need > given {
+ let s = {
+ format!(
+ "not enough interrupts to dispatch \
+ all software tasks (need: {need}; given: {given})"
+ )
+ };
+
+ // If not enough tasks and first still is None, may cause
+ // "custom attribute panicked" due to unwrap on None
+ return Err(parse::Error::new(first.unwrap().span(), s));
+ }
+
+ // Check that all exceptions are valid; only exceptions with configurable priorities are
+ // accepted
+ for (name, task) in &app.hardware_tasks {
+ let name_s = task.args.binds.to_string();
+ match &*name_s {
+ "NonMaskableInt" | "HardFault" => {
+ return Err(parse::Error::new(
+ name.span(),
+ "only exceptions with configurable priority can be used as hardware tasks",
+ ));
+ }
+
+ _ => {}
+ }
+ }
+
+ Ok(())
+}