From 9e445b3583c15c7701f3167eaa8dfe4afd541691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Tj=C3=A4der?= Date: Sat, 4 Feb 2023 16:47:17 +0100 Subject: Move rtic macros to repo root, tune xtask --- rtic-macros/src/codegen/shared_resources.rs | 183 ++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 rtic-macros/src/codegen/shared_resources.rs (limited to 'rtic-macros/src/codegen/shared_resources.rs') diff --git a/rtic-macros/src/codegen/shared_resources.rs b/rtic-macros/src/codegen/shared_resources.rs new file mode 100644 index 0000000..19fd13f --- /dev/null +++ b/rtic-macros/src/codegen/shared_resources.rs @@ -0,0 +1,183 @@ +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; + +/// Generates `static` variables and shared resource proxies +pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { + let mut mod_app = vec![]; + let mut mod_resources = vec![]; + + for (name, res) in &app.shared_resources { + let cfgs = &res.cfgs; + let ty = &res.ty; + let mangled_name = &util::static_shared_resource_ident(name); + + let attrs = &res.attrs; + + // late resources in `util::link_section_uninit` + // unless user specifies custom link section + let section = if attrs.iter().any(|attr| attr.path.is_ident("link_section")) { + None + } else { + Some(util::link_section_uninit()) + }; + + // For future use + // let doc = format!(" RTIC internal: {}:{}", file!(), line!()); + mod_app.push(quote!( + #[allow(non_camel_case_types)] + #[allow(non_upper_case_globals)] + // #[doc = #doc] + #[doc(hidden)] + #(#attrs)* + #(#cfgs)* + #section + static #mangled_name: rtic::RacyCell> = rtic::RacyCell::new(core::mem::MaybeUninit::uninit()); + )); + + // For future use + // let doc = format!(" RTIC internal: {}:{}", file!(), line!()); + + let shared_name = util::need_to_lock_ident(name); + + if !res.properties.lock_free { + mod_resources.push(quote!( + // #[doc = #doc] + #[doc(hidden)] + #[allow(non_camel_case_types)] + #(#cfgs)* + pub struct #shared_name<'a> { + __rtic_internal_p: ::core::marker::PhantomData<&'a ()>, + } + + #(#cfgs)* + impl<'a> #shared_name<'a> { + #[inline(always)] + pub unsafe fn new() -> Self { + #shared_name { __rtic_internal_p: ::core::marker::PhantomData } + } + } + )); + + let ptr = quote!( + #(#cfgs)* + #mangled_name.get_mut() as *mut _ + ); + + let ceiling = match analysis.ownerships.get(name) { + Some(Ownership::Owned { priority } | Ownership::CoOwned { priority }) => *priority, + Some(Ownership::Contended { ceiling }) => *ceiling, + None => 0, + }; + + // For future use + // let doc = format!(" RTIC internal ({} resource): {}:{}", doc, file!(), line!()); + + mod_app.push(util::impl_mutex( + app, + cfgs, + true, + &shared_name, + "e!(#ty), + ceiling, + &ptr, + )); + } + } + + let mod_resources = if mod_resources.is_empty() { + quote!() + } else { + quote!(mod shared_resources { + #(#mod_resources)* + }) + }; + + // 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)* + + #mod_resources + ) +} -- cgit v1.2.3 From 60f0342b697cdddbab9c0e8c6d772bc7aab9de38 Mon Sep 17 00:00:00 2001 From: Emil Fresk Date: Sat, 11 Feb 2023 08:55:19 +0100 Subject: Break out core specific codegen to bindings --- rtic-macros/src/codegen/shared_resources.rs | 86 ++--------------------------- 1 file changed, 4 insertions(+), 82 deletions(-) (limited to 'rtic-macros/src/codegen/shared_resources.rs') diff --git a/rtic-macros/src/codegen/shared_resources.rs b/rtic-macros/src/codegen/shared_resources.rs index 19fd13f..686c280 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)* -- cgit v1.2.3