register_interface/
lib.rs1use proc_macro::TokenStream;
2use proc_macro2::{Ident, Span};
3use quote::quote;
4use syn::parse::{Parse, ParseStream};
5use syn::{parse_macro_input, ItemStruct, LitInt, Result, Token};
6
7struct FieldArgs {
8 name: Ident,
9 _s0: Token![,],
10 from: LitInt,
11 _s1: Token![,],
12 to: LitInt,
13}
14
15impl Parse for FieldArgs {
16 fn parse(input: ParseStream) -> Result<Self> {
17 Ok(FieldArgs {
18 name: input.parse()?,
19 _s0: input.parse()?,
20 from: input.parse()?,
21 _s1: input.parse()?,
22 to: input.parse()?,
23 })
24 }
25}
26
27#[proc_macro_attribute]
28pub fn field(args: TokenStream, input: TokenStream) -> TokenStream {
29 let args_p = parse_macro_input!(args as FieldArgs);
30 let field_name = args_p.name.clone();
31 let field_from = args_p.from.base10_digits().parse().unwrap();
32 let field_to = args_p.to.base10_digits().parse().unwrap();
33 let clonned = input.clone();
34 let input_p = parse_macro_input!(input as ItemStruct);
35 let struct_name = input_p.ident;
36 let set_field_name = Ident::new(&format!("set_{}", args_p.name), Span::call_site());
37
38 let mask = gen_mask(field_from, field_to);
39 let n_mask = !mask;
40 let extended = quote!(
41 impl #struct_name {
42 pub fn #field_name(&self) -> usize {
43 use core::ptr::read_volatile;
44 ((unsafe { read_volatile(self.addr)}) & #mask) >> #field_from
45 }
46 pub fn #set_field_name(&mut self, value: usize) {
47 use core::ptr::{read_volatile, write_volatile};
48 unsafe {
49 let original = read_volatile(self.addr) & #n_mask;
50 let value = value << #field_from;
51 write_volatile(self.addr, original | value);
52 }
53 }
54 }
55 );
56
57 let mut ts = TokenStream::from(extended);
58 ts.extend(clonned);
59 ts
60}
61
62struct RegisterArgs {
63 name: Ident,
64 _s0: Token![,],
65 typ: Ident,
66 _s1: Token![,],
67 offset: LitInt,
68}
69
70impl Parse for RegisterArgs {
71 fn parse(input: ParseStream) -> Result<Self> {
72 Ok(RegisterArgs {
73 name: input.parse()?,
74 _s0: input.parse()?,
75 typ: input.parse()?,
76 _s1: input.parse()?,
77 offset: input.parse()?,
78 })
79 }
80}
81
82#[proc_macro_attribute]
83pub fn register(args: TokenStream, input: TokenStream) -> TokenStream {
84 let args_p = parse_macro_input!(args as RegisterArgs);
85 let reg_name = args_p.name.clone();
86 let reg_offset: usize = args_p.offset.base10_digits().parse().unwrap();
87 let reg_type = args_p.typ;
88 let clonned = input.clone();
89 let input_p = parse_macro_input!(input as ItemStruct);
90 let struct_name = input_p.ident;
91
92 let extended = quote!(
93 impl #struct_name {
94 pub fn #reg_name(&self) -> #reg_type {
95 use core::mem::transmute;
96 unsafe {
97 let addr = (self.addr as usize + #reg_offset) as *mut usize;
98 #reg_type{addr}
99 }
100 }
101 }
102 );
103
104 let mut ts = TokenStream::from(extended);
105 ts.extend(clonned);
106 ts
107}
108
109fn gen_mask(from: u32, to: u32) -> usize {
110 let mut mask = 0;
111 for i in from..=to {
112 mask |= 1 << i;
113 }
114 mask
115}