Add #[interrupt]
macro to register static interrupts.
This commit is contained in:
parent
eb4571dc4c
commit
92be72e0e3
2 changed files with 69 additions and 5 deletions
|
@ -3,9 +3,13 @@
|
||||||
extern crate proc_macro;
|
extern crate proc_macro;
|
||||||
|
|
||||||
use darling::FromMeta;
|
use darling::FromMeta;
|
||||||
use proc_macro::{Span, TokenStream};
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::Span;
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
use std::iter;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
|
use syn::{parse, Type, Visibility};
|
||||||
|
use syn::{ItemFn, ReturnType};
|
||||||
|
|
||||||
mod path;
|
mod path;
|
||||||
|
|
||||||
|
@ -58,10 +62,9 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
fail = true;
|
fail = true;
|
||||||
}
|
}
|
||||||
if pool_size < 1 {
|
if pool_size < 1 {
|
||||||
Span::call_site()
|
return parse::Error::new(Span::call_site(), "pool_size must be 1 or greater")
|
||||||
.error("pool_size must be 1 or greater")
|
.to_compile_error()
|
||||||
.emit();
|
.into();
|
||||||
fail = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut arg_names: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]> =
|
let mut arg_names: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]> =
|
||||||
|
@ -120,6 +123,66 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
result.into()
|
result.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
let mut f: ItemFn = syn::parse(input).expect("`#[interrupt]` must be applied to a function");
|
||||||
|
|
||||||
|
if !args.is_empty() {
|
||||||
|
return parse::Error::new(Span::call_site(), "This attribute accepts no arguments")
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
let fspan = f.span();
|
||||||
|
let ident = f.sig.ident.clone();
|
||||||
|
let ident_s = ident.to_string();
|
||||||
|
|
||||||
|
// XXX should we blacklist other attributes?
|
||||||
|
|
||||||
|
let valid_signature = f.sig.constness.is_none()
|
||||||
|
&& f.vis == Visibility::Inherited
|
||||||
|
&& f.sig.abi.is_none()
|
||||||
|
&& f.sig.inputs.is_empty()
|
||||||
|
&& f.sig.generics.params.is_empty()
|
||||||
|
&& f.sig.generics.where_clause.is_none()
|
||||||
|
&& f.sig.variadic.is_none()
|
||||||
|
&& match f.sig.output {
|
||||||
|
ReturnType::Default => true,
|
||||||
|
ReturnType::Type(_, ref ty) => match **ty {
|
||||||
|
Type::Tuple(ref tuple) => tuple.elems.is_empty(),
|
||||||
|
Type::Never(..) => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if !valid_signature {
|
||||||
|
return parse::Error::new(
|
||||||
|
fspan,
|
||||||
|
"`#[interrupt]` handlers must have signature `[unsafe] fn() [-> !]`",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
f.block.stmts = iter::once(
|
||||||
|
syn::parse2(quote! {{
|
||||||
|
// Check that this interrupt actually exists
|
||||||
|
let __irq_exists_check: interrupt::#ident;
|
||||||
|
}})
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.chain(f.block.stmts)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
quote!(
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[export_name = #ident_s]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#f
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn interrupt_declare(item: TokenStream) -> TokenStream {
|
pub fn interrupt_declare(item: TokenStream) -> TokenStream {
|
||||||
let name = syn::parse_macro_input!(item as syn::Ident);
|
let name = syn::parse_macro_input!(item as syn::Ident);
|
||||||
|
|
|
@ -72,3 +72,4 @@ pub mod interrupt {
|
||||||
pub use embassy::interrupt::{declare, take, Interrupt};
|
pub use embassy::interrupt::{declare, take, Interrupt};
|
||||||
pub use embassy_extras::interrupt::Priority3 as Priority;
|
pub use embassy_extras::interrupt::Priority3 as Priority;
|
||||||
}
|
}
|
||||||
|
pub use embassy_macros::interrupt;
|
||||||
|
|
Loading…
Reference in a new issue