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 #[cfg(target_arch = "arm")]
26 {
27 const SCB_CPACR_PTR: *mut u32 = 0xE000_ED88 as *mut u32;
31 const SCB_CPACR_FULL_ACCESS: u32 = 0b11;
32 let mut temp = SCB_CPACR_PTR.read_volatile();
34 temp |= SCB_CPACR_FULL_ACCESS << (4 * 2);
36 temp |= SCB_CPACR_FULL_ACCESS << (0 * 2);
38 SCB_CPACR_PTR.write_volatile(temp);
39 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
41 }
42 })
43 .into();
44 let clear_locks = parse_macro_input!(clear_locks as Stmt);
45
46 let stmts = insert_after_static(f.block.stmts, clear_locks);
48 f.block.stmts = stmts;
49
50 quote!(
51 #[rp235x_hal::arch_entry]
52 #f
53 )
54 .into()
55}
56
57fn insert_after_static(stmts: impl IntoIterator<Item = Stmt>, insert: Stmt) -> Vec<Stmt> {
59 let mut istmts = stmts.into_iter();
60 let mut stmts = vec![];
61 for stmt in istmts.by_ref() {
62 match stmt {
63 Stmt::Item(Item::Static(var)) => {
64 stmts.push(Stmt::Item(Item::Static(var)));
65 }
66 _ => {
67 stmts.push(insert);
68 stmts.push(stmt);
69 break;
70 }
71 }
72 }
73 stmts.extend(istmts);
74
75 stmts
76}