diff options
Diffstat (limited to 'rtic-macros/src/codegen')
| -rw-r--r-- | rtic-macros/src/codegen/async_dispatchers.rs | 7 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/bindings.rs | 11 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/bindings/cortex.rs | 18 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/bindings/esp32c3.rs | 14 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/bindings/riscv_slic.rs | 255 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/bindings/template.rs | 60 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/extra_mods.rs | 9 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/main.rs | 16 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/module.rs | 29 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/pre_init.rs | 10 | ||||
| -rw-r--r-- | rtic-macros/src/codegen/util.rs | 2 |
11 files changed, 383 insertions, 48 deletions
diff --git a/rtic-macros/src/codegen/async_dispatchers.rs b/rtic-macros/src/codegen/async_dispatchers.rs index 9144b2a..3d166ca 100644 --- a/rtic-macros/src/codegen/async_dispatchers.rs +++ b/rtic-macros/src/codegen/async_dispatchers.rs @@ -2,7 +2,7 @@ use crate::syntax::ast::App; use crate::{ analyze::Analysis, codegen::{ - bindings::{async_entry, handler_config, interrupt_entry, interrupt_exit}, + bindings::{async_entry, handler_config, interrupt_entry, interrupt_exit, interrupt_mod}, util, }, }; @@ -36,10 +36,9 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { }; let pend_interrupt = if level > 0 { - let device = &app.args.device; - let enum_ = util::interrupt_ident(); + let int_mod = interrupt_mod(app); - quote!(rtic::export::pend(#device::#enum_::#dispatcher_name);) + quote!(rtic::export::pend(#int_mod::#dispatcher_name);) } else { // For 0 priority tasks we don't need to pend anything quote!() diff --git a/rtic-macros/src/codegen/bindings.rs b/rtic-macros/src/codegen/bindings.rs index 60605f3..501ccdf 100644 --- a/rtic-macros/src/codegen/bindings.rs +++ b/rtic-macros/src/codegen/bindings.rs @@ -2,7 +2,8 @@ feature = "cortex-m-source-masking", feature = "cortex-m-basepri", feature = "test-template", - feature = "riscv-esp32c3" + feature = "riscv-esp32c3", + feature = "riscv-slic", )))] compile_error!("No backend selected"); @@ -22,4 +23,10 @@ mod template; pub use esp32c3::*; #[cfg(feature = "riscv-esp32c3")] -mod esp32c3;
\ No newline at end of file +mod esp32c3; + +#[cfg(feature = "riscv-slic")] +pub use riscv_slic::*; + +#[cfg(feature = "riscv-slic")] +mod riscv_slic; diff --git a/rtic-macros/src/codegen/bindings/cortex.rs b/rtic-macros/src/codegen/bindings/cortex.rs index 69b5ee5..5c56261 100644 --- a/rtic-macros/src/codegen/bindings/cortex.rs +++ b/rtic-macros/src/codegen/bindings/cortex.rs @@ -35,6 +35,12 @@ pub fn interrupt_ident() -> Ident { Ident::new("interrupt", span) } +pub fn interrupt_mod(app: &App) -> TokenStream2 { + let device = &app.args.device; + let interrupt = interrupt_ident(); + quote!(#device::#interrupt) +} + pub fn check_stack_overflow_before_init( _app: &App, _analysis: &CodegenAnalysis, @@ -199,12 +205,16 @@ mod basepri { } } +pub fn pre_init_preprocessing(_app: &mut App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + Ok(()) +} + 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 interrupt = interrupt_ident(); let rt_err = util::rt_err_ident(); for name in app.args.dispatchers.keys() { @@ -217,7 +227,7 @@ pub fn pre_init_checks(app: &App, _: &SyntaxAnalysis) -> Vec<TokenStream2> { pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { let mut stmts = vec![]; - let interrupt = util::interrupt_ident(); + let interrupt = interrupt_ident(); let rt_err = util::rt_err_ident(); let device = &app.args.device; let nvic_prio_bits = quote!(#device::NVIC_PRIO_BITS); @@ -381,3 +391,7 @@ pub fn handler_config( ) -> Vec<TokenStream2> { vec![] } + +pub fn extra_modules(_app: &App, _analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { + vec![] +} diff --git a/rtic-macros/src/codegen/bindings/esp32c3.rs b/rtic-macros/src/codegen/bindings/esp32c3.rs index 4b14cae..f8ea22a 100644 --- a/rtic-macros/src/codegen/bindings/esp32c3.rs +++ b/rtic-macros/src/codegen/bindings/esp32c3.rs @@ -55,10 +55,20 @@ mod esp32c3 { Ident::new("Interrupt", span) } + pub fn interrupt_mod(app: &App) -> TokenStream2 { + let device = &app.args.device; + let interrupt = interrupt_ident(); + quote!(#device::#interrupt) + } + pub fn extra_assertions(_: &App, _: &SyntaxAnalysis) -> Vec<TokenStream2> { vec![] } + pub fn pre_init_preprocessing(_app: &mut App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + Ok(()) + } + 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 @@ -232,3 +242,7 @@ mod esp32c3 { stmts } } + +pub fn extra_modules(_app: &App, _analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { + vec![] +} diff --git a/rtic-macros/src/codegen/bindings/riscv_slic.rs b/rtic-macros/src/codegen/bindings/riscv_slic.rs new file mode 100644 index 0000000..c9bf50a --- /dev/null +++ b/rtic-macros/src/codegen/bindings/riscv_slic.rs @@ -0,0 +1,255 @@ +use crate::{ + analyze::Analysis as CodegenAnalysis, + syntax::{ + analyze::Analysis as SyntaxAnalysis, + ast::{App, Dispatcher}, + }, +}; +use proc_macro2::{Span, TokenStream as TokenStream2}; +use quote::quote; +use std::{collections::HashSet, vec}; +use syn::{parse, Attribute, Ident}; + +/// Utility function to get the SLIC interrupt module. +pub fn interrupt_ident() -> Ident { + let span = Span::call_site(); + Ident::new("Interrupt", span) +} + +pub fn interrupt_mod(_app: &App) -> TokenStream2 { + let interrupt = interrupt_ident(); + quote!(slic::#interrupt) +} + +/// This macro implements the [`rtic::Mutex`] trait for shared resources using the SLIC. +#[allow(clippy::too_many_arguments)] +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) + }; + + 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 { + + const CEILING: u8 = #ceiling; + + unsafe { + rtic::export::lock(#ptr, CEILING, f) + } + } + } + ) +} + +/// This macro is used to define additional compile-time assertions in case the platform needs it. +/// The Cortex-M implementations do not use it. Thus, we think we do not need it either. +pub fn extra_assertions(_app: &App, _analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { + vec![] +} + +pub fn pre_init_preprocessing(app: &mut App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + app.args.core = false; // RISC-V SLIC is not compatible with using core peripherals + if !app.args.dispatchers.is_empty() { + return Err(parse::Error::new( + Span::call_site(), + "this backend does not support explicit interrupt dispatchers; remove the `dispatchers` argument from `#[app]`", + )); + } + + // Compute the number of handlers we need to dispatch the software tasks + let soft_priorities = app + .software_tasks + .iter() + .map(|(_, task)| task.args.priority) + .filter(|prio| *prio > 0) + .collect::<HashSet<_>>(); + + for i in 0..soft_priorities.len() { + let dispatcher_ident = Ident::new(&format!("__RTICDispatcher{}", i), Span::call_site()); + app.args + .dispatchers + .insert(dispatcher_ident, Dispatcher { attrs: vec![] }); + } + + Ok(()) +} + +/// This macro is used to check at run-time that all the interruption dispatchers exist. +pub fn pre_init_checks(app: &App, _analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { + let mut stmts: Vec<TokenStream2> = vec![]; + let int_mod = interrupt_mod(app); + + // check that all dispatchers exists in the `slic::Interrupt` enumeration + for name in app.args.dispatchers.keys() { + stmts.push(quote!(let _ = #int_mod::#name;)); + } + + stmts +} + +/// This macro must perform all the required operations to activate the +/// interrupt sources with their corresponding priority level. +pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { + let mut stmts = vec![]; + + // First, we reset and disable all the interrupt controllers + stmts.push(quote!(rtic::export::clear_interrupts();)); + + // Then, we set the corresponding priorities + let interrupt_ids = analysis.interrupts.iter().map(|(p, (id, _))| (p, id)); + for (&p, name) in interrupt_ids.chain( + app.hardware_tasks + .values() + .map(|task| (&task.args.priority, &task.args.binds)), + ) { + stmts.push(quote!( + rtic::export::set_priority(slic::Interrupt::#name, #p); + )); + } + // Finally, we activate the interrupts + stmts.push(quote!(rtic::export::set_interrupts();)); + stmts +} + +/// Any additional checks that depend on the system architecture. +pub fn architecture_specific_analysis(app: &App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { + // 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})" + ) + }; + + return Err(parse::Error::new(first.unwrap().span(), s)); + } + + if app.args.backend.is_none() { + return Err(parse::Error::new( + Span::call_site(), + "SLIC requires backend-specific configuration", + )); + } + + Ok(()) +} + +/// Macro to add statements to be executed at the beginning of all the interrupt handlers. +pub fn interrupt_entry(_app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStream2> { + vec![] +} + +/// Macro to add statements to be executed at the end of all the interrupt handlers. +pub fn interrupt_exit(_app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStream2> { + vec![] +} + +pub fn check_stack_overflow_before_init( + _app: &App, + _analysis: &CodegenAnalysis, +) -> Vec<TokenStream2> { + vec![quote!( + // Check for stack overflow using symbols from `risc-v-rt`. + extern "C" { + pub static _stack_start: u32; + pub static _ebss: u32; + } + + let stack_start = &_stack_start as *const _ as u32; + let ebss = &_ebss as *const _ as u32; + + if stack_start > ebss { + // No flip-link usage, check the SP for overflow. + if rtic::export::read_sp() <= ebss { + panic!("Stack overflow after allocating executors"); + } + } + )] +} + +pub fn async_entry( + _app: &App, + _analysis: &CodegenAnalysis, + _dispatcher_name: Ident, +) -> Vec<TokenStream2> { + vec![] +} + +/// Macro to define a maximum priority level for async tasks. +pub fn async_prio_limit(_app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { + let max = if let Some(max) = analysis.max_async_prio { + quote!(#max) + } else { + quote!(u8::MAX) // No limit + }; + + vec![quote!( + /// Holds the maximum priority level for use by async HAL drivers. + #[no_mangle] + static RTIC_ASYNC_MAX_LOGICAL_PRIO: u8 = #max; + )] +} + +pub fn handler_config( + _app: &App, + _analysis: &CodegenAnalysis, + _dispatcher_name: Ident, +) -> Vec<TokenStream2> { + vec![] +} + +/// The SLIC requires us to call to the [`riscv_rtic::codegen`] macro to generate +/// the appropriate SLIC structure, interrupt enumerations, etc. +pub fn extra_modules(app: &App, _analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { + let mut stmts = vec![]; + + let hw_slice: Vec<_> = app + .hardware_tasks + .values() + .map(|task| &task.args.binds) + .collect(); + let sw_slice: Vec<_> = app.args.dispatchers.keys().collect(); + + let swi_slice: Vec<_> = hw_slice.iter().chain(sw_slice.iter()).collect(); + + let device = &app.args.device; + + stmts.push(quote!( + use rtic::export::riscv_slic; + )); + let hart_id = &app.args.backend.as_ref().unwrap().hart_id; + + stmts.push(quote!(rtic::export::codegen!(pac = #device, swi = [#(#swi_slice,)*], backend = [hart_id = #hart_id]);)); + + stmts +} diff --git a/rtic-macros/src/codegen/bindings/template.rs b/rtic-macros/src/codegen/bindings/template.rs index b5488b7..ecb46d5 100644 --- a/rtic-macros/src/codegen/bindings/template.rs +++ b/rtic-macros/src/codegen/bindings/template.rs @@ -6,40 +6,55 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; use syn::{parse, Attribute, Ident}; +pub fn interrupt_ident() -> Ident { + let span = Span::call_site(); + Ident::new("interrupt", span) +} + +pub fn interrupt_mod(app: &App) -> TokenStream2 { + let device = &app.args.device; + let interrupt = interrupt_ident(); + quote!(#device::#interrupt) +} + pub fn impl_mutex( - _app: &App, - _analysis: &CodegenAnalysis, - _cfgs: &[Attribute], - _resources_prefix: bool, - _name: &Ident, - _ty: &TokenStream2, - _ceiling: u8, - _ptr: &TokenStream2, + app: &App, + analysis: &CodegenAnalysis, + cfgs: &[Attribute], + resources_prefix: bool, + name: &Ident, + ty: &TokenStream2, + ceiling: u8, + ptr: &TokenStream2, ) -> TokenStream2 { quote!() } -pub fn extra_assertions(_app: &App, _analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { +pub fn extra_assertions(app: &App, analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { vec![] } -pub fn pre_init_checks(_app: &App, _analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { +pub fn pre_init_preprocessing(app: &mut App, analysis: &SyntaxAnalysis) -> parse::Result<()> { + Ok(()) +} + +pub fn pre_init_checks(app: &App, analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { vec![] } -pub fn pre_init_enable_interrupts(_app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStream2> { +pub fn pre_init_enable_interrupts(app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { vec![] } -pub fn architecture_specific_analysis(_app: &App, _analysis: &SyntaxAnalysis) -> parse::Result<()> { +pub fn architecture_specific_analysis(app: &App, analysis: &SyntaxAnalysis) -> parse::Result<()> { Ok(()) } -pub fn interrupt_entry(_app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStream2> { +pub fn interrupt_entry(app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { vec![] } -pub fn interrupt_exit(_app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStream2> { +pub fn interrupt_exit(app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { vec![] } @@ -51,20 +66,25 @@ pub fn check_stack_overflow_before_init( } pub fn async_entry( - _app: &App, - _analysis: &CodegenAnalysis, - _dispatcher_name: Ident, + app: &App, + analysis: &CodegenAnalysis, + dispatcher_name: Ident, ) -> Vec<TokenStream2> { vec![] } -pub fn async_prio_limit(app: &App, _analysis: &CodegenAnalysis) -> Vec<TokenStream2> { +pub fn async_prio_limit(app: &App, analysis: &CodegenAnalysis) -> Vec<TokenStream2> { vec![] } + pub fn handler_config( - _app: &App, - _analysis: &CodegenAnalysis, + app: &App, + analysis: &CodegenAnalysis, dispatcher_name: Ident, ) -> Vec<TokenStream2> { vec![] } + +pub fn extra_modules(app: &App, analysis: &SyntaxAnalysis) -> Vec<TokenStream2> { + vec![] +} diff --git a/rtic-macros/src/codegen/extra_mods.rs b/rtic-macros/src/codegen/extra_mods.rs new file mode 100644 index 0000000..b92dda6 --- /dev/null +++ b/rtic-macros/src/codegen/extra_mods.rs @@ -0,0 +1,9 @@ +use super::bindings::extra_modules; +use crate::analyze::Analysis; +use crate::syntax::ast::App; +use proc_macro2::TokenStream as TokenStream2; + +/// Generates code that runs before `#[init]` +pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> { + extra_modules(app, analysis) +} diff --git a/rtic-macros/src/codegen/main.rs b/rtic-macros/src/codegen/main.rs index 5612796..80f2cf6 100644 --- a/rtic-macros/src/codegen/main.rs +++ b/rtic-macros/src/codegen/main.rs @@ -1,4 +1,3 @@ -use super::{assertions, post_init, pre_init}; use crate::{ analyze::Analysis, codegen::{bindings, util}, @@ -7,8 +6,12 @@ use crate::{ use proc_macro2::TokenStream as TokenStream2; use quote::quote; +use super::{assertions, extra_mods, post_init, pre_init}; + /// Generates code for `fn main` pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { + let extra_mods_stmts = extra_mods::codegen(app, analysis); + let assertion_stmts = assertions::codegen(app, analysis); let pre_init_stmts = pre_init::codegen(app, analysis); @@ -40,9 +43,18 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { let main = util::suffixed("main"); let init_name = &app.init.name; + + let init_args = if app.args.core { + quote!(core.into(), executors_size) + } else { + quote!(executors_size) + }; + let msp_check = bindings::check_stack_overflow_before_init(app, analysis); quote!( + #(#extra_mods_stmts)* + #[doc(hidden)] #[no_mangle] unsafe extern "C" fn #main() -> ! { @@ -63,7 +75,7 @@ pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 { // Wrap late_init_stmts in a function to ensure that stack space is reclaimed. __rtic_init_resources(||{ - let (shared_resources, local_resources) = #init_name(#init_name::Context::new(core.into(), executors_size)); + let (shared_resources, local_resources) = #init_name(#init_name::Context::new(#init_args)); #(#post_init_stmts)* }); diff --git a/rtic-macros/src/codegen/module.rs b/rtic-macros/src/codegen/module.rs index c8afe07..17c8ce7 100644 --- a/rtic-macros/src/codegen/module.rs +++ b/rtic-macros/src/codegen/module.rs @@ -1,5 +1,5 @@ use crate::syntax::{ast::App, Context}; -use crate::{analyze::Analysis, codegen::util}; +use crate::{analyze::Analysis, codegen::bindings::interrupt_mod, codegen::util}; use proc_macro2::TokenStream as TokenStream2; use quote::quote; @@ -17,15 +17,19 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { match ctxt { Context::Init => { fields.push(quote!( - /// Core peripherals - pub core: rtic::export::Peripherals - )); - - fields.push(quote!( /// The space used to allocate async executors in bytes. pub executors_size: usize )); + if app.args.core { + fields.push(quote!( + /// Core peripherals + pub core: rtic::export::Peripherals + )); + + values.push(quote!(core: core)); + } + if app.args.peripherals { let device = &app.args.device; @@ -43,8 +47,6 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { )); values.push(quote!(cs: rtic::export::CriticalSection::new())); - - values.push(quote!(core)); values.push(quote!(executors_size)); } @@ -98,7 +100,11 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { }; let core = if ctxt.is_init() { - Some(quote!(core: rtic::export::Peripherals, executors_size: usize)) + if app.args.core { + Some(quote!(core: rtic::export::Peripherals, executors_size: usize)) + } else { + Some(quote!(executors_size: usize)) + } } else { None }; @@ -144,10 +150,9 @@ pub fn codegen(ctxt: Context, app: &App, analysis: &Analysis) -> TokenStream2 { task_cfgs = cfgs.clone(); let pend_interrupt = if priority > 0 { - let device = &app.args.device; - let enum_ = util::interrupt_ident(); + let int_mod = interrupt_mod(app); let interrupt = &analysis.interrupts.get(&priority).expect("UREACHABLE").0; - quote!(rtic::export::pend(#device::#enum_::#interrupt);) + quote!(rtic::export::pend(#int_mod::#interrupt);) } else { quote!() }; diff --git a/rtic-macros/src/codegen/pre_init.rs b/rtic-macros/src/codegen/pre_init.rs index a2d0e8c..8de75ff 100644 --- a/rtic-macros/src/codegen/pre_init.rs +++ b/rtic-macros/src/codegen/pre_init.rs @@ -11,10 +11,12 @@ pub fn codegen(app: &App, analysis: &Analysis) -> Vec<TokenStream2> { // Disable interrupts -- `init` must run with interrupts disabled stmts.push(quote!(rtic::export::interrupt::disable();)); - stmts.push(quote!( - // To set the variable in cortex_m so the peripherals cannot be taken multiple times - let mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().into(); - )); + if app.args.core { + stmts.push(quote!( + // To set the variable in cortex_m so the peripherals cannot be taken multiple times + let mut core: rtic::export::Peripherals = rtic::export::Peripherals::steal().into(); + )); + } stmts.append(&mut pre_init_checks(app, analysis)); diff --git a/rtic-macros/src/codegen/util.rs b/rtic-macros/src/codegen/util.rs index b4682ee..dda7e29 100644 --- a/rtic-macros/src/codegen/util.rs +++ b/rtic-macros/src/codegen/util.rs @@ -3,8 +3,6 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::{Ident, PatType}; -//hook the target specific interrupt_ident function -pub use super::bindings::interrupt_ident; const RTIC_INTERNAL: &str = "__rtic_internal"; |
