1extern crate proc_macro;
2
3use proc_macro::TokenStream;
4use proc_macro2::Span;
5use quote::quote;
6use syn::{parse, parse_macro_input, Item, ItemFn, Stmt};
7
8#[proc_macro_attribute]
9pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
10 let mut f = parse_macro_input!(input as ItemFn);
11
12 if !args.is_empty() {
13 return parse::Error::new(Span::call_site(), "This attribute accepts no arguments")
14 .to_compile_error()
15 .into();
16 }
17
18 let clear_locks: TokenStream = quote!(unsafe {
19 const SIO_BASE: u32 = 0xd0000000;
20 const SPINLOCK0_PTR: *mut u32 = (SIO_BASE + 0x100) as *mut u32;
21 const SPINLOCK_COUNT: usize = 32;
22 for i in 0..SPINLOCK_COUNT {
23 SPINLOCK0_PTR.wrapping_add(i).write_volatile(1);
24 }
25 })
26 .into();
27 let clear_locks = parse_macro_input!(clear_locks as Stmt);
28
29 let stmts = insert_after_static(f.block.stmts, clear_locks);
31 f.block.stmts = stmts;
32
33 quote!(
34 #[::cortex_m_rt::entry]
35 #f
36 )
37 .into()
38}
39
40fn insert_after_static(stmts: impl IntoIterator<Item = Stmt>, insert: Stmt) -> Vec<Stmt> {
42 let mut istmts = stmts.into_iter();
43 let mut stmts = vec![];
44 for stmt in istmts.by_ref() {
45 match stmt {
46 Stmt::Item(Item::Static(var)) => {
47 stmts.push(Stmt::Item(Item::Static(var)));
48 }
49 _ => {
50 stmts.push(insert);
51 stmts.push(stmt);
52 break;
53 }
54 }
55 }
56 stmts.extend(istmts);
57
58 stmts
59}