added argument trampoline to hardware tasks to allow exception "masking"

Co-authored-by: Salon <salon64@users.noreply.github.com>
This commit is contained in:
Olle Ronstad 2025-10-02 17:02:43 +02:00
parent 300ad99b74
commit 11d2ca9f2b
4 changed files with 79 additions and 26 deletions

View file

@ -319,13 +319,13 @@ pub fn architecture_specific_analysis(app: &App, _: &SyntaxAnalysis) -> parse::R
.filter(|prio| *prio > 0) .filter(|prio| *prio > 0)
.collect::<HashSet<_>>(); .collect::<HashSet<_>>();
let need = priorities.len(); let need_software = priorities.len();
let given = app.args.dispatchers.len(); let given = app.args.dispatchers.len();
if need > given { if need_software > given {
let s = { let s = {
format!( format!(
"not enough interrupts to dispatch \ "not enough interrupts to dispatch \
all software tasks (need: {need}; given: {given})" all software tasks (need: {need_software}; given: {given})"
) )
}; };

View file

@ -24,26 +24,62 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
let exit_stmts = interrupt_exit(app, analysis); let exit_stmts = interrupt_exit(app, analysis);
let config = handler_config(app, analysis, symbol.clone()); let config = handler_config(app, analysis, symbol.clone());
mod_app.push(quote!( if let Some(trampoline) = &task.args.trampoline {
#[allow(non_snake_case)] let trampoline_symbol = trampoline.clone();
#[no_mangle] mod_app.push(quote!(
#(#attrs)*
#(#cfgs)*
#(#config)*
unsafe fn #symbol() {
#(#entry_stmts)*
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, || { #[allow(non_snake_case)]
#name( #[no_mangle]
#name::Context::new() #(#attrs)*
) #(#cfgs)*
}); #(#config)*
unsafe fn #trampoline_symbol() {
#(#exit_stmts)* #(#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` // `${task}Locals`
if !task.args.local_resources.is_empty() { 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); local_resources_struct::codegen(Context::HardwareTask(name), app);
root.push(item); root.push(item);
mod_app.push(constructor); mod_app.push(constructor);
} }
@ -61,7 +96,6 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
shared_resources_struct::codegen(Context::HardwareTask(name), app); shared_resources_struct::codegen(Context::HardwareTask(name), app);
root.push(item); root.push(item);
mod_app.push(constructor); mod_app.push(constructor);
} }

View file

@ -298,6 +298,9 @@ pub struct HardwareTaskArgs {
/// The interrupt or exception that this task is bound to /// The interrupt or exception that this task is bound to
pub binds: Ident, pub binds: Ident,
/// if set the bind would trampoline with the given interrupt handler
pub trampoline: Option<Ident>,
/// The priority of this task /// The priority of this task
pub priority: u8, pub priority: u8,

View file

@ -193,6 +193,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
} }
let mut binds = None; let mut binds = None;
let mut trampoline = None;
let mut priority = None; let mut priority = None;
let mut shared_resources = None; let mut shared_resources = None;
let mut local_resources = None; let mut local_resources = None;
@ -223,7 +224,21 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
let ident = input.parse()?; let ident = input.parse()?;
binds = Some(ident); binds = Some(ident);
} },
"trampoline" => {
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" => { "priority" => {
if priority.is_some() { if priority.is_some() {
@ -277,8 +292,8 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
local_resources = Some(util::parse_local_resources(input)?); local_resources = Some(util::parse_local_resources(input)?);
} }
_ => { a => {
return Err(parse::Error::new(ident.span(), "unexpected argument")); return Err(parse::Error::new(ident.span(), format!("unexpected argument {}", a)));
} }
} }
@ -308,6 +323,7 @@ fn task_args(tokens: TokenStream2) -> parse::Result<Either<HardwareTaskArgs, Sof
priority, priority,
shared_resources, shared_resources,
local_resources, local_resources,
trampoline,
}) })
} else { } else {
// Software tasks start at idle priority // Software tasks start at idle priority