From 11d2ca9f2bd47e8c653c5b830b137ce263b66b54 Mon Sep 17 00:00:00 2001 From: Olle Ronstad Date: Thu, 2 Oct 2025 17:02:43 +0200 Subject: [PATCH] added argument trampoline to hardware tasks to allow exception "masking" Co-authored-by: Salon --- rtic-macros/src/codegen/bindings/cortex.rs | 6 +- rtic-macros/src/codegen/hardware_tasks.rs | 74 ++++++++++++++++------ rtic-macros/src/syntax/ast.rs | 3 + rtic-macros/src/syntax/parse.rs | 22 ++++++- 4 files changed, 79 insertions(+), 26 deletions(-) diff --git a/rtic-macros/src/codegen/bindings/cortex.rs b/rtic-macros/src/codegen/bindings/cortex.rs index 5c56261db5d..87a06ac55ee 100644 --- a/rtic-macros/src/codegen/bindings/cortex.rs +++ b/rtic-macros/src/codegen/bindings/cortex.rs @@ -319,13 +319,13 @@ pub fn architecture_specific_analysis(app: &App, _: &SyntaxAnalysis) -> parse::R .filter(|prio| *prio > 0) .collect::>(); - let need = priorities.len(); + let need_software = priorities.len(); let given = app.args.dispatchers.len(); - if need > given { + if need_software > given { let s = { format!( "not enough interrupts to dispatch \ - all software tasks (need: {need}; given: {given})" + all software tasks (need: {need_software}; given: {given})" ) }; diff --git a/rtic-macros/src/codegen/hardware_tasks.rs b/rtic-macros/src/codegen/hardware_tasks.rs index ee85f59f335..e77c7f1e588 100644 --- a/rtic-macros/src/codegen/hardware_tasks.rs +++ b/rtic-macros/src/codegen/hardware_tasks.rs @@ -24,26 +24,62 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { let exit_stmts = interrupt_exit(app, analysis); let config = handler_config(app, analysis, symbol.clone()); - mod_app.push(quote!( - #[allow(non_snake_case)] - #[no_mangle] - #(#attrs)* - #(#cfgs)* - #(#config)* - unsafe fn #symbol() { - #(#entry_stmts)* + if let Some(trampoline) = &task.args.trampoline { + let trampoline_symbol = trampoline.clone(); + mod_app.push(quote!( - const PRIORITY: u8 = #priority; + #[allow(non_snake_case)] + #[no_mangle] + #(#attrs)* + #(#cfgs)* + #(#config)* + unsafe fn #symbol() { + rtic::export::pend(rtic::export::Interrupt::#trampoline_symbol); + } - rtic::export::run(PRIORITY, || { - #name( - #name::Context::new() - ) - }); - - #(#exit_stmts)* - } - )); + #[allow(non_snake_case)] + #[no_mangle] + #(#attrs)* + #(#cfgs)* + #(#config)* + unsafe fn #trampoline_symbol() { + #(#entry_stmts)* + + const PRIORITY: u8 = #priority; + + rtic::export::run(PRIORITY, || { + #name( + #name::Context::new() + ) + }); + + + #(#exit_stmts)* + } + )); + + } else { + mod_app.push(quote!( + #[allow(non_snake_case)] + #[no_mangle] + #(#attrs)* + #(#cfgs)* + #(#config)* + unsafe fn #symbol() { + #(#entry_stmts)* + + const PRIORITY: u8 = #priority; + + rtic::export::run(PRIORITY, || { + #name( + #name::Context::new() + ) + }); + + #(#exit_stmts)* + } + )); + } // `${task}Locals` if !task.args.local_resources.is_empty() { @@ -51,7 +87,6 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { local_resources_struct::codegen(Context::HardwareTask(name), app); root.push(item); - mod_app.push(constructor); } @@ -61,7 +96,6 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { shared_resources_struct::codegen(Context::HardwareTask(name), app); root.push(item); - mod_app.push(constructor); } diff --git a/rtic-macros/src/syntax/ast.rs b/rtic-macros/src/syntax/ast.rs index 44c1385d24f..0229e64ef2a 100644 --- a/rtic-macros/src/syntax/ast.rs +++ b/rtic-macros/src/syntax/ast.rs @@ -298,6 +298,9 @@ pub struct HardwareTaskArgs { /// The interrupt or exception that this task is bound to pub binds: Ident, + /// if set the bind would trampoline with the given interrupt handler + pub trampoline: Option, + /// The priority of this task pub priority: u8, diff --git a/rtic-macros/src/syntax/parse.rs b/rtic-macros/src/syntax/parse.rs index ea7ff29409a..3b0494a43a5 100644 --- a/rtic-macros/src/syntax/parse.rs +++ b/rtic-macros/src/syntax/parse.rs @@ -193,6 +193,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result parse::Result { + if trampoline.is_some() { + return Err(parse::Error::new( + ident.span(), + "argument appears more than once", + )); + } + + // Parse identifier name + let ident: Ident = input.parse()?; + + trampoline = Some(ident); + }, "priority" => { if priority.is_some() { @@ -277,8 +292,8 @@ fn task_args(tokens: TokenStream2) -> parse::Result { - return Err(parse::Error::new(ident.span(), "unexpected argument")); + a => { + return Err(parse::Error::new(ident.span(), format!("unexpected argument {}", a))); } } @@ -308,6 +323,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result