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;
|
||||
|
||||
use darling::FromMeta;
|
||||
use proc_macro::{Span, TokenStream};
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::{format_ident, quote};
|
||||
use std::iter;
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{parse, Type, Visibility};
|
||||
use syn::{ItemFn, ReturnType};
|
||||
|
||||
mod path;
|
||||
|
||||
|
@ -58,10 +62,9 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream {
|
|||
fail = true;
|
||||
}
|
||||
if pool_size < 1 {
|
||||
Span::call_site()
|
||||
.error("pool_size must be 1 or greater")
|
||||
.emit();
|
||||
fail = true
|
||||
return parse::Error::new(Span::call_site(), "pool_size must be 1 or greater")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
#[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]
|
||||
pub fn interrupt_declare(item: TokenStream) -> TokenStream {
|
||||
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_extras::interrupt::Priority3 as Priority;
|
||||
}
|
||||
pub use embassy_macros::interrupt;
|
||||
|
|
Loading…
Reference in a new issue