diff options
Diffstat (limited to 'rtic-macros')
-rw-r--r-- | rtic-macros/Cargo.toml | 1 | ||||
-rw-r--r-- | rtic-macros/src/bindings.rs | 1 | ||||
-rw-r--r-- | rtic-macros/src/check.rs | 71 | ||||
-rw-r--r-- | rtic-macros/src/codegen.rs | 2 | ||||
-rw-r--r-- | rtic-macros/src/codegen/assertions.rs | 36 | ||||
-rw-r--r-- | rtic-macros/src/codegen/bindings.rs | 5 | ||||
-rw-r--r-- | rtic-macros/src/codegen/bindings/cortex.rs | 346 | ||||
-rw-r--r-- | rtic-macros/src/codegen/module.rs | 4 | ||||
-rw-r--r-- | rtic-macros/src/codegen/pre_init.rs | 69 | ||||
-rw-r--r-- | rtic-macros/src/codegen/shared_resources.rs | 86 | ||||
-rw-r--r-- | rtic-macros/src/codegen/util.rs | 68 | ||||
-rw-r--r-- | rtic-macros/src/lib.rs | 3 |
12 files changed, 372 insertions, 320 deletions
diff --git a/rtic-macros/Cargo.toml b/rtic-macros/Cargo.toml index 970f6662..12cd0d95 100644 --- a/rtic-macros/Cargo.toml +++ b/rtic-macros/Cargo.toml @@ -24,6 +24,7 @@ proc-macro = true [features] default = [] debugprint = [] + # list of supported codegen backends thumbv6 = [] thumbv7 = [] diff --git a/rtic-macros/src/bindings.rs b/rtic-macros/src/bindings.rs deleted file mode 100644 index 8b137891..00000000 --- a/rtic-macros/src/bindings.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/rtic-macros/src/check.rs b/rtic-macros/src/check.rs index a05c82e8..957a9b36 100644 --- a/rtic-macros/src/check.rs +++ b/rtic-macros/src/check.rs @@ -1,70 +1,7 @@ -use std::collections::HashSet; - -use crate::syntax::ast::App; +use crate::codegen::bindings::architecture_specific_analysis; +use crate::syntax::{analyze::Analysis, ast::App}; use syn::parse; -pub fn app(app: &App) -> parse::Result<()> { - // Check that external (device-specific) interrupts are not named after known (Cortex-M) - // exceptions - for name in app.args.dispatchers.keys() { - let name_s = name.to_string(); - - match &*name_s { - "NonMaskableInt" | "HardFault" | "MemoryManagement" | "BusFault" | "UsageFault" - | "SecureFault" | "SVCall" | "DebugMonitor" | "PendSV" | "SysTick" => { - return Err(parse::Error::new( - name.span(), - "Cortex-M exceptions can't be used as `extern` interrupts", - )); - } - - _ => {} - } - } - - // Check that there are enough external interrupts to dispatch the software tasks and the timer - // queue handler - let mut first = None; - let priorities = app - .software_tasks - .iter() - .map(|(name, task)| { - first = Some(name); - task.args.priority - }) - .filter(|prio| *prio > 0) - .collect::<HashSet<_>>(); - - let need = priorities.len(); - let given = app.args.dispatchers.len(); - if need > given { - let s = { - format!( - "not enough interrupts to dispatch \ - all software tasks (need: {need}; given: {given})" - ) - }; - - // If not enough tasks and first still is None, may cause - // "custom attribute panicked" due to unwrap on None - return Err(parse::Error::new(first.unwrap().span(), s)); - } - - // Check that all exceptions are valid; only exceptions with configurable priorities are - // accepted - for (name, task) in &app.hardware_tasks { - let name_s = task.args.binds.to_string(); - match &*name_s { - "NonMaskableInt" | "HardFault" => { - return Err(parse::Error::new( - name.span(), - "only exceptions with configurable priority can be used as hardware tasks", - )); - } - - _ => {} - } - } - - Ok(()) +pub fn app(app: &App, analysis: &Analysis) -> parse::Result<()> { + architecture_specific_analysis(app, analysis) } diff --git a/rtic-macros/src/codegen.rs b/rtic-macros/src/codegen.rs index 24e98ce9..48ee5e33 100644 --- a/rtic-macros/src/codegen.rs +++ b/rtic-macros/src/codegen.rs @@ -4,6 +4,8 @@ use quote::quote; use crate::analyze::Analysis; use crate::syntax::ast::App; +pub mod bindings; + mod assertions; mod async_dispatchers; mod hardware_tasks; diff --git a/rtic-macros/src/codegen/assertions.rs b/rtic-macros/src/codegen/assertions.rs index dd94aa6d..2f5dd523 100644 --- a/rtic-macros/src/codegen/assertions.rs +++ b/rtic-macros/src/codegen/assertions.rs @@ -1,8 +1,9 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; +use super::bindings::extra_assertions; +use crate::analyze::Analysis; use crate::syntax::ast::App; -use crate::{analyze::Analysis, codegen::util}; /// Generates compile-time assertions that check that types implement the `Send` / `Sync` traits pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> { @@ -16,38 +17,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> { stmts.push(quote!(rtic::export::assert_sync::<#ty>();)); } - let device = &app.args.device; - let chunks_name = util::priority_mask_chunks_ident(); - let no_basepri_checks: Vec<_> = app - .hardware_tasks - .iter() - .filter_map(|(_, task)| { - if !util::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: () = { - if !rtic::export::have_basepri() { - #(#no_basepri_checks)* - } else { - // TODO: Add armv7 checks here - } - }; - - let _ = _CONST_CHECK; - }; - - stmts.push(const_check); + stmts.append(&mut extra_assertions(app, analysis)); stmts } diff --git a/rtic-macros/src/codegen/bindings.rs b/rtic-macros/src/codegen/bindings.rs new file mode 100644 index 00000000..1efe0ce0 --- /dev/null +++ b/rtic-macros/src/codegen/bindings.rs @@ -0,0 +1,5 @@ +// TODO: Feature gate +mod cortex; + +// TODO: Feature gate +pub use cortex::*; diff --git a/rtic-macros/src/codegen/bindings/cortex.rs b/rtic-macros/src/codegen/bindings/cortex.rs new file mode 100644 index 00000000..15976a10 --- /dev/null +++ b/rtic-macros/src/codegen/bindings/cortex.rs @@ -0,0 +1,346 @@ +use crate::{ + analyze::Analysis as CodegenAnalysis, + codegen::util, + syntax::{analyze::Analysis as SyntaxAnalysis, ast::App}, +}; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use std::collections::HashSet; +use syn::{parse, Attribute, Ident}; + +// TODO: This should be feature gated +// pub use basepri::*; +pub use source_masking::*; + +/// Whether `name` is an exception with configurable priority +fn is_exception(name: &Ident) -> bool { + let s = name.to_string(); + + matches!( + &*s, + "MemoryManagement" + | "BusFault" + | "UsageFault" + | "SecureFault" + | "SVCall" + | "DebugMonitor" + | "PendSV" + | "SysTick" + ) +} + +pub mod source_masking { + use super::*; + use std::collections::HashMap; + + /// Generates a `Mutex` implementation + pub fn impl_mutex( + app: &App, + analysis: &CodegenAnalysis, + cfgs: &[Attribute], + resources_prefix: bool, + name: &Ident, + ty: &TokenStream2, + ceiling: u8, + ptr: &TokenStream2, + ) -> TokenStream2 { + let path = if resources_prefix { + quote!(shared_resources::#name) + } else { + quote!(#name) + }; + + // Computing mapping of used interrupts to masks + let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); + + let mut prio_to_masks = HashMap::new(); + let device = &app.args.device; + // let mut uses_exceptions_with_resources = false; + + let mut mask_ids = Vec::new(); + + for (&priority, name) in interrupt_ids.chain(app.hardware_tasks.values().flat_map(|task| { + if !is_exception(&task.args.binds) { + Some((&task.args.priority, &task.args.binds)) + } 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)); + } + + // Call rtic::export::create_mask([Mask; N]), where the array is the list of shifts + + let mut mask_arr = Vec::new(); + // NOTE: 0..3 assumes max 4 priority levels according to M0, M23 spec + for i in 0..3 { + let v = if let Some(v) = prio_to_masks.get(&i) { + v.clone() + } else { + Vec::new() + }; + + mask_arr.push(quote!( + rtic::export::create_mask([#(#v),*]) + )); + } + + // 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> { + type T = #ty; + + #[inline(always)] + fn lock<RTIC_INTERNAL_R>(&mut self, f: impl FnOnce(&mut #ty) -> RTIC_INTERNAL_R) -> RTIC_INTERNAL_R { + /// Priority ceiling + const CEILING: u8 = #ceiling; + const N_CHUNKS: usize = rtic::export::compute_mask_chunks([#(#mask_ids),*]); + const MASKS: [rtic::export::Mask<N_CHUNKS>; 3] = [#(#mask_arr),*]; + + unsafe { + rtic::export::lock( + #ptr, + CEILING, + &MASKS, + f, + ) + } + } + } + ) + } + + pub fn extra_assertions(_: &App, _: &SyntaxAnalysis) -> Vec<TokenStream2> { + // 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 { + use super::*; + + /// Generates a `Mutex` implementation + pub fn impl_mutex( + app: &App, + _analysis: &CodegenAnalysis, + cfgs: &[Attribute], + resources_prefix: bool, + name: &Ident, + ty: &TokenStream2, + ceiling: u8, + ptr: &TokenStream2, + ) -> TokenStream2 { + let path = if resources_prefix { + quote!(shared_resources::#name) + } else { + quote!(#name) + }; + + let device = &app.args.device; + quote!( + #(#cfgs)* + impl<'a> rtic::Mutex for #path<'a> { + type T = #ty; + + #[inline(always)] + fn lock<RTIC_INTERNAL_R>(&mut self, f: impl FnOnce(&mut #ty) -> RTIC_INTERNAL_R) -> RTIC_INTERNAL_R { + /// Priority ceiling + const CEILING: u8 = #ceiling; + + unsafe { + rtic::export::lock( + #ptr, + CEILING, + #device::NVIC_PRIO_BITS, + f, + ) + } + } + } + ) + } + + pub fn extra_assertions(_: &App, _: &SyntaxAnalysis) -> Vec<TokenStream2> { + vec![] + } +} + +pub fn pre_init_checks(app: &App, _: &SyntaxAnalysis) -> Vec<TokenStream2> { + let mut stmts = vec![]; + + // check that all dispatchers exists in the `Interrupt` enumeration regardless of whether + // they are used or not + let interrupt = util::interrupt_ident(); + let rt_err = util::rt_err_ident(); + + for name in app.args.dispatchers.keys() { + stmts.push(quote!(let _ = #rt_err::#interrupt::#name;)); + } + + stmts +} + +pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { + let mut stmts = vec![]; + + let interrupt = util::interrupt_ident(); + let rt_err = util::rt_err_ident(); + let device = &app.args.device; + let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS); + let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); + + // Unmask interrupts and set their priorities + for (&priority, name) in interrupt_ids.chain(app.hardware_tasks.values().filter_map(|task| { + if is_exception(&task.args.binds) { + // We do exceptions in another pass + None + } else { + Some((&task.args.priority, &task.args.binds)) + } + })) { + let es = format!( + "Maximum priority used by interrupt vector '{name}' is more than supported by hardware" + ); + // Compile time assert that this priority is supported by the device + stmts.push(quote!( + const _: () = if (1 << #nvic_prio_bits) < #priority as usize { ::core::panic!(#es); }; + )); + + stmts.push(quote!( + core.NVIC.set_priority( + #rt_err::#interrupt::#name, + rtic::export::logical2hw(#priority, #nvic_prio_bits), + ); + )); + + // NOTE unmask the interrupt *after* setting its priority: changing the priority of a pended + // interrupt is implementation defined + stmts.push(quote!(rtic::export::NVIC::unmask(#rt_err::#interrupt::#name);)); + } + + // Set exception priorities + for (name, priority) in app.hardware_tasks.values().filter_map(|task| { + if is_exception(&task.args.binds) { + Some((&task.args.binds, task.args.priority)) + } else { + None + } + }) { + let es = format!( + "Maximum priority used by interrupt vector '{name}' is more than supported by hardware" + ); + // Compile time assert that this priority is supported by the device + stmts.push(quote!( + const _: () = if (1 << #nvic_prio_bits) < #priority as usize { ::core::panic!(#es); }; + )); + + stmts.push(quote!(core.SCB.set_priority( + rtic::export::SystemHandler::#name, + rtic::export::logical2hw(#priority, #nvic_prio_bits), + );)); + } + + stmts +} + +pub fn architecture_specific_analysis(app: &App, _: &SyntaxAnalysis) -> parse::Result<()> { + // Check that external (device-specific) interrupts are not named after known (Cortex-M) + // exceptions + for name in app.args.dispatchers.keys() { + let name_s = name.to_string(); + + match &*name_s { + "NonMaskableInt" | "HardFault" | "MemoryManagement" | "BusFault" | "UsageFault" + | "SecureFault" | "SVCall" | "DebugMonitor" | "PendSV" | "SysTick" => { + return Err(parse::Error::new( + name.span(), + "Cortex-M exceptions can't be used as `extern` interrupts", + )); + } + + _ => {} + } + } + + // Check that there are enough external interrupts to dispatch the software tasks and the timer + // queue handler + let mut first = None; + let priorities = app + .software_tasks + .iter() + .map(|(name, task)| { + first = Some(name); + task.args.priority + }) + .filter(|prio| *prio > 0) + .collect::<HashSet<_>>(); + + let need = priorities.len(); + let given = app.args.dispatchers.len(); + if need > given { + let s = { + format!( + "not enough interrupts to dispatch \ + all software tasks (need: {need}; given: {given})" + ) + }; + + // If not enough tasks and first still is None, may cause + // "custom attribute panicked" due to unwrap on None + return Err(parse::Error::new(first.unwrap().span(), s)); + } + + // Check that all exceptions are valid; only exceptions with configurable priorities are + // accepted + for (name, task) in &app.hardware_tasks { + let name_s = task.args.binds.to_string(); + match &*name_s { + "NonMaskableInt" | "HardFault" => { + return Err(parse::Error::new( + name.span(), + "only exceptions with configurable priority can be used as hardware tasks", + )); + } + + _ => {} + } + } + + Ok(()) +} diff --git a/rtic-macros/src/codegen/module.rs b/rtic-macros/src/codegen/module.rs index 8b3fca23..af4e0346 100644 --- a/rtic-macros/src/codegen/module.rs +++ b/rtic-macros/src/codegen/module.rs @@ -17,7 +17,7 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { match ctxt { Context::Init => { fields.push(quote!( - /// Core (Cortex-M) peripherals + /// Core peripherals pub core: rtic::export::Peripherals )); @@ -25,7 +25,7 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { let device = &app.args.device; fields.push(quote!( - /// Device peripherals + /// Device peripherals (PAC) pub device: #device::Peripherals )); diff --git a/rtic-macros/src/codegen/pre_init.rs b/rtic-macros/src/codegen/pre_init.rs index 28ba29c0..a2d0e8c1 100644 --- a/rtic-macros/src/codegen/pre_init.rs +++ b/rtic-macros/src/codegen/pre_init.rs @@ -1,15 +1,13 @@ +use super::bindings::{pre_init_checks, pre_init_enable_interrupts}; +use crate::analyze::Analysis; use crate::syntax::ast::App; use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use crate::{analyze::Analysis, codegen::util}; - /// Generates code that runs before `#[init]` pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> { let mut stmts = vec![]; - let rt_err = util::rt_err_ident(); - // Disable interrupts -- `init` must run with interrupts disabled stmts.push(quote!(rtic::export::interrupt::disable();)); @@ -18,68 +16,9 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> { let mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().into(); )); - let device = &app.args.device; - let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS); - - // check that all dispatchers exists in the `Interrupt` enumeration regardless of whether - // they are used or not - let interrupt = util::interrupt_ident(); - for name in app.args.dispatchers.keys() { - stmts.push(quote!(let _ = #rt_err::#interrupt::#name;)); - } - - let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); - - // Unmask interrupts and set their priorities - for (&priority, name) in interrupt_ids.chain(app.hardware_tasks.values().filter_map(|task| { - if util::is_exception(&task.args.binds) { - // We do exceptions in another pass - None - } else { - Some((&task.args.priority, &task.args.binds)) - } - })) { - let es = format!( - "Maximum priority used by interrupt vector '{name}' is more than supported by hardware" - ); - // Compile time assert that this priority is supported by the device - stmts.push(quote!( - const _: () = if (1 << #nvic_prio_bits) < #priority as usize { ::core::panic!(#es); }; - )); - - stmts.push(quote!( - core.NVIC.set_priority( - #rt_err::#interrupt::#name, - rtic::export::logical2hw(#priority, #nvic_prio_bits), - ); - )); - - // NOTE unmask the interrupt *after* setting its priority: changing the priority of a pended - // interrupt is implementation defined - stmts.push(quote!(rtic::export::NVIC::unmask(#rt_err::#interrupt::#name);)); - } - - // Set exception priorities - for (name, priority) in app.hardware_tasks.values().filter_map(|task| { - if util::is_exception(&task.args.binds) { - Some((&task.args.binds, task.args.priority)) - } else { - None - } - }) { - let es = format!( - "Maximum priority used by interrupt vector '{name}' is more than supported by hardware" - ); - // Compile time assert that this priority is supported by the device - stmts.push(quote!( - const _: () = if (1 << #nvic_prio_bits) < #priority as usize { ::core::panic!(#es); }; - )); + stmts.append(&mut pre_init_checks(app, analysis)); - stmts.push(quote!(core.SCB.set_priority( - rtic::export::SystemHandler::#name, - rtic::export::logical2hw(#priority, #nvic_prio_bits), - );)); - } + stmts.append(&mut pre_init_enable_interrupts(app, analysis)); stmts } diff --git a/rtic-macros/src/codegen/shared_resources.rs b/rtic-macros/src/codegen/shared_resources.rs index 19fd13fe..686c2809 100644 --- a/rtic-macros/src/codegen/shared_resources.rs +++ b/rtic-macros/src/codegen/shared_resources.rs @@ -2,7 +2,8 @@ use crate::syntax::{analyze::Ownership, ast::App}; use crate::{analyze::Analysis, codegen::util}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; -use std::collections::HashMap; + +use super::bindings::impl_mutex; /// Generates `static` variables and shared resource proxies pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { @@ -75,8 +76,9 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { // For future use // let doc = format!(" RTIC internal ({} resource): {}:{}", doc, file!(), line!()); - mod_app.push(util::impl_mutex( + mod_app.push(impl_mutex( app, + analysis, cfgs, true, &shared_name, @@ -95,86 +97,6 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { }) }; - // Computing mapping of used interrupts to masks - let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); - - let mut prio_to_masks = HashMap::new(); - let device = &app.args.device; - let mut uses_exceptions_with_resources = false; - - let mut mask_ids = Vec::new(); - - for (&priority, name) in interrupt_ids.chain(app.hardware_tasks.values().flat_map(|task| { - if !util::is_exception(&task.args.binds) { - Some((&task.args.priority, &task.args.binds)) - } else { - // If any resource to the exception uses non-lock-free or non-local resources this is - // not allwed on thumbv6. - uses_exceptions_with_resources = uses_exceptions_with_resources - || task - .args - .shared_resources - .iter() - .map(|(ident, access)| { - if access.is_exclusive() { - if let Some(r) = app.shared_resources.get(ident) { - !r.properties.lock_free - } else { - false - } - } else { - false - } - }) - .any(|v| v); - - 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)); - } - - // Call rtic::export::create_mask([Mask; N]), where the array is the list of shifts - - let mut mask_arr = Vec::new(); - // NOTE: 0..3 assumes max 4 priority levels according to M0, M23 spec - for i in 0..3 { - let v = if let Some(v) = prio_to_masks.get(&i) { - v.clone() - } else { - Vec::new() - }; - - mask_arr.push(quote!( - rtic::export::create_mask([#(#v),*]) - )); - } - - // Generate a constant for the number of chunks needed by Mask. - let chunks_name = util::priority_mask_chunks_ident(); - mod_app.push(quote!( - #[doc(hidden)] - #[allow(non_upper_case_globals)] - const #chunks_name: usize = rtic::export::compute_mask_chunks([#(#mask_ids),*]); - )); - - let masks_name = util::priority_masks_ident(); - mod_app.push(quote!( - #[doc(hidden)] - #[allow(non_upper_case_globals)] - const #masks_name: [rtic::export::Mask<#chunks_name>; 3] = [#(#mask_arr),*]; - )); - - 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!( #(#mod_app)* diff --git a/rtic-macros/src/codegen/util.rs b/rtic-macros/src/codegen/util.rs index d0c8cc0e..27c8a2a1 100644 --- a/rtic-macros/src/codegen/util.rs +++ b/rtic-macros/src/codegen/util.rs @@ -6,70 +6,11 @@ use syn::{Attribute, Ident, PatType}; const RTIC_INTERNAL: &str = "__rtic_internal"; -/// Generates a `Mutex` implementation -pub fn impl_mutex( - app: &App, - cfgs: &[Attribute], - resources_prefix: bool, - name: &Ident, - ty: &TokenStream2, - ceiling: u8, - ptr: &TokenStream2, -) -> TokenStream2 { - let path = if resources_prefix { - quote!(shared_resources::#name) - } else { - quote!(#name) - }; - - let device = &app.args.device; - let masks_name = priority_masks_ident(); - quote!( - #(#cfgs)* - impl<'a> rtic::Mutex for #path<'a> { - type T = #ty; - - #[inline(always)] - fn lock<RTIC_INTERNAL_R>(&mut self, f: impl FnOnce(&mut #ty) -> RTIC_INTERNAL_R) -> RTIC_INTERNAL_R { - /// Priority ceiling - const CEILING: u8 = #ceiling; - - unsafe { - rtic::export::lock( - #ptr, - CEILING, - #device::NVIC_PRIO_BITS, - &#masks_name, - f, - ) - } - } - } - ) -} - pub fn interrupt_ident() -> Ident { let span = Span::call_site(); Ident::new("interrupt", span) } -/// Whether `name` is an exception with configurable priority -pub fn is_exception(name: &Ident) -> bool { - let s = name.to_string(); - - matches!( - &*s, - "MemoryManagement" - | "BusFault" - | "UsageFault" - | "SecureFault" - | "SVCall" - | "DebugMonitor" - | "PendSV" - | "SysTick" - ) -} - /// Mark a name as internal pub fn mark_internal_name(name: &str) -> Ident { Ident::new(&format!("{RTIC_INTERNAL}_{name}"), Span::call_site()) @@ -204,15 +145,6 @@ pub fn static_shared_resource_ident(name: &Ident) -> Ident { mark_internal_name(&format!("shared_resource_{name}")) } -/// Generates an Ident for the number of 32 bit chunks used for Mask storage. -pub fn priority_mask_chunks_ident() -> Ident { - mark_internal_name("MASK_CHUNKS") -} - -pub fn priority_masks_ident() -> Ident { - mark_internal_name("MASKS") -} - pub fn static_local_resource_ident(name: &Ident) -> Ident { mark_internal_name(&format!("local_resource_{name}")) } diff --git a/rtic-macros/src/lib.rs b/rtic-macros/src/lib.rs index 3ac27017..cd2a9245 100644 --- a/rtic-macros/src/lib.rs +++ b/rtic-macros/src/lib.rs @@ -8,7 +8,6 @@ use proc_macro::TokenStream; use std::{env, fs, path::Path}; mod analyze; -mod bindings; mod check; mod codegen; mod syntax; @@ -38,7 +37,7 @@ pub fn app(args: TokenStream, input: TokenStream) -> TokenStream { Ok(x) => x, }; - if let Err(e) = check::app(&app) { + if let Err(e) = check::app(&app, &analysis) { return e.to_compile_error().into(); } |