aboutsummaryrefslogtreecommitdiff
path: root/embassy-macros
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-macros')
-rw-r--r--embassy-macros/src/lib.rs62
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]
103pub 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]
128pub 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}