continued work on rtic trampoline

Co-authored-by: Salon <salon64@users.noreply.github.com>
This commit is contained in:
Olle Ronstad 2025-10-03 17:30:45 +02:00
parent 936dfc51e9
commit ccddee6198
4 changed files with 107 additions and 4 deletions

View file

@ -0,0 +1,6 @@
gpioa lock
gpioa unlock
SysTick start
idle
SysTick start
idle end

View file

@ -0,0 +1,65 @@
//! examples/bouncy_trampoline.rs
#![no_std]
#![no_main]
#![deny(warnings)]
#![deny(unsafe_code)]
#![deny(missing_docs)]
use panic_semihosting as _;
// `examples/bouncy_trampoline.rs` testing trampoline feature
#[rtic::app(device = lm3s6965)]
mod app {
use cortex_m_semihosting::{debug, hprintln};
use lm3s6965::Interrupt;
#[shared]
struct Shared {
h_priority: u8,
}
#[local]
struct Local {}
#[init]
fn init(_: init::Context) -> (Shared, Local) {
// Trigger SW0 interrupt to test NMI preemption
rtic::pend(Interrupt::GPIOA);
(Shared { h_priority: 0 }, Local {})
}
#[idle]
fn idle(_: idle::Context) -> ! {
hprintln!("idle");
// pend another interrupt to test trampoline
cortex_m::peripheral::SCB::set_pendst();
hprintln!("idle end");
debug::exit(debug::EXIT_SUCCESS);
loop {
cortex_m::asm::wfi();
}
}
#[task(binds = SysTick, trampoline = GPIOC, priority = 2, shared = [h_priority])]
fn sys_tick(_: sys_tick::Context) {
hprintln!("SysTick start");
}
#[task(binds = GPIOA, priority = 1, shared = [h_priority])]
fn gpioa(mut ctx: gpioa::Context) {
ctx.shared.h_priority.lock(|_| {
hprintln!("gpioa lock");
cortex_m::peripheral::SCB::set_pendst();
cortex_m::asm::delay(100_000_000);
hprintln!("gpioa unlock");
});
}
#[task(binds = GPIOB, priority = 3, shared = [h_priority])]
fn high_priority_task(_: high_priority_task::Context) {
hprintln!("High priority task");
}
}

View file

@ -102,7 +102,20 @@ mod source_masking {
} else {
None
}
})) {
})
// Add trampoline tasks if present and not exceptions
.chain(app.hardware_tasks.values().filter_map(|task| {
if let Some(trampoline) = &task.args.trampoline {
if !is_exception(trampoline) {
Some((&task.args.priority, trampoline))
} else {
None
}
} else {
None
}
}))
) {
let v: &mut Vec<_> = prio_to_masks.entry(priority - 1).or_default();
v.push(quote!(#device::Interrupt::#name as u32));
mask_ids.push(quote!(#device::Interrupt::#name as u32));
@ -245,7 +258,7 @@ pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec<
if let Some(trampoline) = &task.args.trampoline {
if is_exception(trampoline) {
// We do exceptions in another pass
return None;
None
} else {
// If there's a trampoline, we need to unmask and set priority for it too
Some((&task.args.priority, trampoline))
@ -362,6 +375,27 @@ pub fn architecture_specific_analysis(app: &App, _: &SyntaxAnalysis) -> parse::R
}
}
// Check that a exception is not used with shared resources
// TODO provide warning when a exception is used with source masking since it then ignores locks in priority ceilings
#[cfg(feature = "cortex-m-source-masking")]
for (name, task) in &app.hardware_tasks {
if is_exception(name) && !app.shared_resources.is_empty(){
if let Some(trampoline) = task.args.trampoline.as_ref() {
if is_exception(trampoline) {
return Err(parse::Error::new(
trampoline.span(),
"cannot use exceptions as trampoline tasks when using source masking",
));
}
} else {
return Err(parse::Error::new(
name.span(),
"cannot use exceptions with shared resources as hardware tasks when using source masking, consider adding the trampoline attribute",
));
}
}
}
Ok(())
}

View file

@ -38,10 +38,8 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
#(#cfgs)*
#(#config)*
unsafe fn #symbol() {
info!("Pend trampoline");
use #rt_err::Interrupt;
rtic::pend(Interrupt::#trampoline_symbol);
info!("Exit trampoline handler");
}
#[allow(non_snake_case)]