From 0750234fbead723138d6d1ebb0635a55c82923e0 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 29 Dec 2020 00:05:52 +0100 Subject: WIP owned irqs --- embassy-macros/src/lib.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'embassy-macros/src/lib.rs') diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index b11fc4ae9..091e08cfa 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -98,3 +98,65 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream { }; result.into() } + +#[proc_macro] +pub fn interrupt_declare(item: TokenStream) -> TokenStream { + let name = syn::parse_macro_input!(item as syn::Ident); + let name = format_ident!("{}", name); + let name_interrupt = format_ident!("{}Interrupt", name); + let name_handler = format!("__EMBASSY_{}_HANDLER", name); + + let result = quote! { + #[allow(non_camel_case_types)] + pub struct #name_interrupt(()); + unsafe impl OwnedInterrupt for #name_interrupt { + type Priority = Priority; + fn number(&self) -> u8 { + Interrupt::#name as u8 + } + unsafe fn __handler(&self) -> &'static ::core::sync::atomic::AtomicPtr { + #[export_name = #name_handler] + static HANDLER: ::core::sync::atomic::AtomicPtr = ::core::sync::atomic::AtomicPtr::new(::core::ptr::null_mut()); + &HANDLER + } + } + }; + result.into() +} + +#[proc_macro] +pub fn interrupt_take(item: TokenStream) -> TokenStream { + let name = syn::parse_macro_input!(item as syn::Ident); + let name = format!("{}", name); + let name_interrupt = format_ident!("{}Interrupt", name); + let name_handler = format!("__EMBASSY_{}_HANDLER", name); + + let result = quote! { + { + #[allow(non_snake_case)] + #[export_name = #name] + pub unsafe extern "C" fn trampoline() { + extern "C" { + #[link_name = #name_handler] + static HANDLER: ::core::sync::atomic::AtomicPtr; + } + + let p = HANDLER.load(::core::sync::atomic::Ordering::Acquire); + if !p.is_null() { + let f: fn() = ::core::mem::transmute(p); + f() + } + } + + static TAKEN: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false); + + if TAKEN.compare_and_swap(false, true, ::core::sync::atomic::Ordering::AcqRel) { + panic!("IRQ Already taken"); + } + + let irq: interrupt::#name_interrupt = unsafe { ::core::mem::transmute(()) }; + irq + } + }; + result.into() +} -- cgit