diff --git a/rtic-macros/Cargo.toml b/rtic-macros/Cargo.toml index 12cd0d9515..bdc2c12278 100644 --- a/rtic-macros/Cargo.toml +++ b/rtic-macros/Cargo.toml @@ -26,10 +26,13 @@ default = [] debugprint = [] # list of supported codegen backends -thumbv6 = [] -thumbv7 = [] -# riscv-clic = [] -# riscv-ch32 = [] +cortex_m_source_masking = [] +cortex_m_basepri = [] +# riscv_clic = [] +# riscv_ch32 = [] + +# backend API test +test_template = [] [dependencies] indexmap = "1.9.2" diff --git a/rtic-macros/src/codegen/bindings.rs b/rtic-macros/src/codegen/bindings.rs index 1efe0ce0b2..a187820ea0 100644 --- a/rtic-macros/src/codegen/bindings.rs +++ b/rtic-macros/src/codegen/bindings.rs @@ -1,5 +1,18 @@ -// TODO: Feature gate +#[cfg(not(any( + feature = "cortex_m_source_masking", + feature = "cortex_m_basepri", + feaute = "test_template" +)))] +compile_error!("No backend selected"); + +#[cfg(any(feature = "cortex_m_source_masking", feature = "cortex_m_basepri"))] +pub use cortex::*; + +#[cfg(feature = "test_template")] +pub use cortex::*; + +#[cfg(any(feature = "cortex_m_source_masking", feature = "cortex_m_basepri"))] mod cortex; -// TODO: Feature gate -pub use cortex::*; +#[cfg(feature = "test_template")] +mod template; diff --git a/rtic-macros/src/codegen/bindings/cortex.rs b/rtic-macros/src/codegen/bindings/cortex.rs index 15976a1087..f028cee7cb 100644 --- a/rtic-macros/src/codegen/bindings/cortex.rs +++ b/rtic-macros/src/codegen/bindings/cortex.rs @@ -8,8 +8,9 @@ use quote::quote; use std::collections::HashSet; use syn::{parse, Attribute, Ident}; -// TODO: This should be feature gated -// pub use basepri::*; +#[cfg(feature = "cortex_m_basepri")] +pub use basepri::*; +#[cfg(feature = "cortex_m_source_masking")] pub use source_masking::*; /// Whether `name` is an exception with configurable priority @@ -29,7 +30,8 @@ fn is_exception(name: &Ident) -> bool { ) } -pub mod source_masking { +#[cfg(feature = "cortex_m_source_masking")] +mod source_masking { use super::*; use std::collections::HashMap; @@ -87,14 +89,6 @@ pub mod source_masking { )); } - // if uses_exceptions_with_resources { - // mod_app.push(quote!( - // #[doc(hidden)] - // #[allow(non_upper_case_globals)] - // const __rtic_internal_V6_ERROR: () = rtic::export::no_basepri_panic(); - // )); - // } - quote!( #(#cfgs)* impl<'a> rtic::Mutex for #path<'a> { @@ -121,38 +115,12 @@ pub mod source_masking { } pub fn extra_assertions(_: &App, _: &SyntaxAnalysis) -> Vec { - // let device = &app.args.device; - // let no_basepri_checks: Vec<_> = app - // .hardware_tasks - // .iter() - // .filter_map(|(_, task)| { - // if !is_exception(&task.args.binds) { - // let interrupt_name = &task.args.binds; - // Some(quote!( - // if (#device::Interrupt::#interrupt_name as usize) >= (#chunks_name * 32) { - // ::core::panic!("An interrupt out of range is used while in armv6 or armv8m.base"); - // } - // )) - // } else { - // None - // } - // }) - // .collect(); - - // let const_check = quote! { - // const _CONST_CHECK: () = { - // #(#no_basepri_checks)* - // }; - - // let _ = _CONST_CHECK; - // }; - - // vec![const_check] vec![] } } -pub mod basepri { +#[cfg(feature = "cortex_m_basepri")] +mod basepri { use super::*; /// Generates a `Mutex` implementation @@ -245,7 +213,7 @@ pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec< stmts.push(quote!( core.NVIC.set_priority( #rt_err::#interrupt::#name, - rtic::export::logical2hw(#priority, #nvic_prio_bits), + rtic::export::cortex_logical2hw(#priority, #nvic_prio_bits), ); )); @@ -272,7 +240,7 @@ pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec< stmts.push(quote!(core.SCB.set_priority( rtic::export::SystemHandler::#name, - rtic::export::logical2hw(#priority, #nvic_prio_bits), + rtic::export::cortex_logical2hw(#priority, #nvic_prio_bits), );)); } diff --git a/rtic-macros/src/codegen/util.rs b/rtic-macros/src/codegen/util.rs index 27c8a2a10e..2f44edb0bc 100644 --- a/rtic-macros/src/codegen/util.rs +++ b/rtic-macros/src/codegen/util.rs @@ -2,7 +2,7 @@ use crate::syntax::{ast::App, Context}; use core::sync::atomic::{AtomicUsize, Ordering}; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; -use syn::{Attribute, Ident, PatType}; +use syn::{Ident, PatType}; const RTIC_INTERNAL: &str = "__rtic_internal"; diff --git a/rtic-monotonics/src/systick.rs b/rtic-monotonics/src/systick.rs index 27110220a3..62d4e0c02f 100644 --- a/rtic-monotonics/src/systick.rs +++ b/rtic-monotonics/src/systick.rs @@ -157,7 +157,7 @@ macro_rules! make_systick_handler { #[no_mangle] #[allow(non_snake_case)] unsafe extern "C" fn SysTick() { - Systick::__tq().on_monotonic_interrupt(); + rtic_monotonics::systick::Systick::__tq().on_monotonic_interrupt(); } }; } diff --git a/rtic/Cargo.toml b/rtic/Cargo.toml index 24b7fd1748..4448fd3c88 100644 --- a/rtic/Cargo.toml +++ b/rtic/Cargo.toml @@ -40,10 +40,7 @@ bare-metal = "1.0.0" atomic-polyfill = "1" rtic-macros = { path = "../rtic-macros", version = "2.0.0-alpha.0" } rtic-core = "1" - - -[build-dependencies] -version_check = "0.9" +critical-section = "1" [dev-dependencies] heapless = "0.7.7" @@ -66,6 +63,17 @@ version = "0.6.0" trybuild = "1" [features] +default = [] + +thumbv6 = ["rtic-macros/cortex_m_source_masking"] +thumbv7 = ["rtic-macros/cortex_m_basepri"] +thumbv8_base = ["rtic-macros/cortex_m_source_masking"] +thumbv8_main = ["rtic-macros/cortex_m_basepri"] +# riscv_clic = ["rtic-macros/riscv_clic"] +# riscv_ch32 = ["rtic-macros/riscv_ch32"] +# riscv_esp32c3 = ["rtic-macros/riscv_esp32c3"] + +# needed for testing test-critical-section = ["cortex-m/critical-section-single-core", "rtic-monotonics/systick_100hz"] # [[example]] diff --git a/rtic/build.rs b/rtic/build.rs index 35f8303f5c..178a8e3428 100644 --- a/rtic/build.rs +++ b/rtic/build.rs @@ -3,22 +3,21 @@ use std::env; fn main() { let target = env::var("TARGET").unwrap(); - if version_check::Channel::read().unwrap().is_nightly() { - println!("cargo:rustc-cfg=rustc_is_nightly"); - } - // These targets all have know support for the BASEPRI register. if target.starts_with("thumbv7m") | target.starts_with("thumbv7em") | target.starts_with("thumbv8m.main") { - println!("cargo:rustc-cfg=have_basepri"); + println!("cargo:rustc-cfg=cortex_m_basepri"); + } else if target.starts_with("thumbv6m") | target.starts_with("thumbv8m.base") { + println!("cargo:rustc-cfg=cortex_m_source_masking"); + } else if target.starts_with("riscv32i") { + panic!("No RISC-V support yet."); - // These targets are all known to _not_ have the BASEPRI register. - } else if target.starts_with("thumb") - && !(target.starts_with("thumbv6m") | target.starts_with("thumbv8m.base")) - { - panic!("Unknown target '{target}'. Need to update BASEPRI logic in build.rs."); + // TODO: Add feature here for risc-v targets + // println!("cargo:rustc-cfg=riscv"); + } else if target.starts_with("thumb") || target.starts_with("riscv32") { + panic!("Unknown target '{target}'. Need to update logic in build.rs."); } println!("cargo:rerun-if-changed=build.rs"); diff --git a/rtic/examples/async-delay.rs b/rtic/examples/async-delay.rs index ba6ec54191..c163a3e692 100644 --- a/rtic/examples/async-delay.rs +++ b/rtic/examples/async-delay.rs @@ -12,7 +12,7 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)] mod app { use cortex_m_semihosting::{debug, hprintln}; - use rtic_monotonics::systick_monotonic::*; + use rtic_monotonics::systick::*; rtic_monotonics::make_systick_handler!(); diff --git a/rtic/examples/async-timeout.rs b/rtic/examples/async-timeout.rs index cdccb3a428..384c8886fa 100644 --- a/rtic/examples/async-timeout.rs +++ b/rtic/examples/async-timeout.rs @@ -9,7 +9,7 @@ use cortex_m_semihosting::{debug, hprintln}; use panic_semihosting as _; -use rtic_monotonics::systick_monotonic::*; +use rtic_monotonics::systick::*; #[rtic::app(device = lm3s6965, dispatchers = [SSI0, UART0], peripherals = true)] mod app { diff --git a/rtic/src/export.rs b/rtic/src/export.rs index 91812fa0d8..2ce8ce202c 100644 --- a/rtic/src/export.rs +++ b/rtic/src/export.rs @@ -4,13 +4,36 @@ pub use atomic_polyfill as atomic; pub mod executor; -// #[cfg(have_basepri)] -pub mod cortex_basepri; +#[cfg(all( + cortex_m_basepri, + not(any(feature = "thumbv7", feature = "thumbv8_main")) +))] +compile_error!( + "Building for Cortex-M with basepri, but 'thumbv7' or 'thumbv8_main' backend not selected" +); -// #[cfg(not(have_basepri))] -pub mod cortex_source_mask; +#[cfg(all( + cortex_m_source_masking, + not(any(feature = "thumbv6", feature = "thumbv8_base")) +))] +compile_error!( + "Building for Cortex-M with source masking, but 'thumbv6' or 'thumbv8_base' backend not selected" +); + +#[cfg(cortex_m_basepri)] +pub use cortex_basepri::*; + +#[cfg(cortex_m_basepri)] +mod cortex_basepri; + +#[cfg(cortex_m_source_masking)] +pub use cortex_source_mask::*; + +#[cfg(cortex_m_source_masking)] +mod cortex_source_mask; /// Priority conversion, takes logical priorities 1..=N and converts it to NVIC priority. +#[cfg(any(cortex_m_basepri, cortex_m_source_masking))] #[inline] #[must_use] pub const fn cortex_logical2hw(logical: u8, nvic_prio_bits: u8) -> u8 { diff --git a/rtic/src/export/cortex_basepri.rs b/rtic/src/export/cortex_basepri.rs index 04f8ae900c..d3ceba35ba 100644 --- a/rtic/src/export/cortex_basepri.rs +++ b/rtic/src/export/cortex_basepri.rs @@ -59,14 +59,14 @@ where /// but can in theory be fixed. /// #[inline(always)] -pub unsafe fn lock( +pub unsafe fn lock( ptr: *mut T, ceiling: u8, nvic_prio_bits: u8, f: impl FnOnce(&mut T) -> R, ) -> R { if ceiling == (1 << nvic_prio_bits) { - let r = interrupt::free(|_| f(&mut *ptr)); + let r = critical_section::with(|_| f(&mut *ptr)); r } else { let current = basepri::read(); diff --git a/rtic/src/export/cortex_source_mask.rs b/rtic/src/export/cortex_source_mask.rs index db5c5f71c5..fe95b1b7db 100644 --- a/rtic/src/export/cortex_source_mask.rs +++ b/rtic/src/export/cortex_source_mask.rs @@ -126,7 +126,7 @@ pub unsafe fn lock( // execute closure under protection of raised system ceiling // safe to manipulate outside critical section - interrupt::free(|_| f(&mut *ptr)) + critical_section::with(|_| f(&mut *ptr)) } else { // safe to manipulate outside critical section let mask = compute_mask(0, ceiling, masks); @@ -164,6 +164,7 @@ pub const fn compute_mask( idx += 1; } + // old code (non const) // masks[from_prio as usize..to_prio as usize] // .iter() // .for_each(|m| res |= *m);