diff --git a/ci/expected/lm3s6965/trampoline.run b/ci/expected/lm3s6965/trampoline.run new file mode 100644 index 00000000000..87dab984087 --- /dev/null +++ b/ci/expected/lm3s6965/trampoline.run @@ -0,0 +1,6 @@ +gpioa lock +gpioa unlock +SysTick start +idle +SysTick start +idle end diff --git a/examples/lm3s6965/examples/trampoline.rs b/examples/lm3s6965/examples/trampoline.rs new file mode 100644 index 00000000000..03768a64986 --- /dev/null +++ b/examples/lm3s6965/examples/trampoline.rs @@ -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"); + } +} diff --git a/rtic-macros/src/codegen/bindings/cortex.rs b/rtic-macros/src/codegen/bindings/cortex.rs index 8f759c3eae8..a73f92271df 100644 --- a/rtic-macros/src/codegen/bindings/cortex.rs +++ b/rtic-macros/src/codegen/bindings/cortex.rs @@ -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(()) } diff --git a/rtic-macros/src/codegen/hardware_tasks.rs b/rtic-macros/src/codegen/hardware_tasks.rs index b7c54997029..9b238295398 100644 --- a/rtic-macros/src/codegen/hardware_tasks.rs +++ b/rtic-macros/src/codegen/hardware_tasks.rs @@ -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)]