diff options
Diffstat (limited to 'embassy-macros/src/lib.rs')
| -rw-r--r-- | embassy-macros/src/lib.rs | 62 |
1 files changed, 62 insertions, 0 deletions
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 { | |||
| 98 | }; | 98 | }; |
| 99 | result.into() | 99 | result.into() |
| 100 | } | 100 | } |
| 101 | |||
| 102 | #[proc_macro] | ||
| 103 | pub fn interrupt_declare(item: TokenStream) -> TokenStream { | ||
| 104 | let name = syn::parse_macro_input!(item as syn::Ident); | ||
| 105 | let name = format_ident!("{}", name); | ||
| 106 | let name_interrupt = format_ident!("{}Interrupt", name); | ||
| 107 | let name_handler = format!("__EMBASSY_{}_HANDLER", name); | ||
| 108 | |||
| 109 | let result = quote! { | ||
| 110 | #[allow(non_camel_case_types)] | ||
| 111 | pub struct #name_interrupt(()); | ||
| 112 | unsafe impl OwnedInterrupt for #name_interrupt { | ||
| 113 | type Priority = Priority; | ||
| 114 | fn number(&self) -> u8 { | ||
| 115 | Interrupt::#name as u8 | ||
| 116 | } | ||
| 117 | unsafe fn __handler(&self) -> &'static ::core::sync::atomic::AtomicPtr<u32> { | ||
| 118 | #[export_name = #name_handler] | ||
| 119 | static HANDLER: ::core::sync::atomic::AtomicPtr<u32> = ::core::sync::atomic::AtomicPtr::new(::core::ptr::null_mut()); | ||
| 120 | &HANDLER | ||
| 121 | } | ||
| 122 | } | ||
| 123 | }; | ||
| 124 | result.into() | ||
| 125 | } | ||
| 126 | |||
| 127 | #[proc_macro] | ||
| 128 | pub fn interrupt_take(item: TokenStream) -> TokenStream { | ||
| 129 | let name = syn::parse_macro_input!(item as syn::Ident); | ||
| 130 | let name = format!("{}", name); | ||
| 131 | let name_interrupt = format_ident!("{}Interrupt", name); | ||
| 132 | let name_handler = format!("__EMBASSY_{}_HANDLER", name); | ||
| 133 | |||
| 134 | let result = quote! { | ||
| 135 | { | ||
| 136 | #[allow(non_snake_case)] | ||
| 137 | #[export_name = #name] | ||
| 138 | pub unsafe extern "C" fn trampoline() { | ||
| 139 | extern "C" { | ||
| 140 | #[link_name = #name_handler] | ||
| 141 | static HANDLER: ::core::sync::atomic::AtomicPtr<u32>; | ||
| 142 | } | ||
| 143 | |||
| 144 | let p = HANDLER.load(::core::sync::atomic::Ordering::Acquire); | ||
| 145 | if !p.is_null() { | ||
| 146 | let f: fn() = ::core::mem::transmute(p); | ||
| 147 | f() | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | static TAKEN: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false); | ||
| 152 | |||
| 153 | if TAKEN.compare_and_swap(false, true, ::core::sync::atomic::Ordering::AcqRel) { | ||
| 154 | panic!("IRQ Already taken"); | ||
| 155 | } | ||
| 156 | |||
| 157 | let irq: interrupt::#name_interrupt = unsafe { ::core::mem::transmute(()) }; | ||
| 158 | irq | ||
| 159 | } | ||
| 160 | }; | ||
| 161 | result.into() | ||
| 162 | } | ||
