Skip to content

Commit 27ede02

Browse files
committed
Added procedural macro #[ram]
1 parent f262e7a commit 27ede02

File tree

6 files changed

+184
-1
lines changed

6 files changed

+184
-1
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/target
2+
procmacros/target
23
**/*.rs.bk
34
Cargo.lock
45
.vscode/.cortex-debug*

Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ authors = ["Scott Mabin <[email protected]>", "Arjan Mels <[email protected]>"]
55
edition = "2018"
66

77
[dependencies]
8-
xtensa-lx6-rt = { git = "https://github.com/esp-rs/xtensa-lx6-rt.git", rev = "62229c1" }
8+
esp32-hal-proc-macros = { path = "procmacros" }
9+
xtensa-lx6-rt = { git = "https://github.com/esp-rs/xtensa-lx6-rt.git", rev = "b5ebc04" }
910
esp32 = { version = "0.3.0" }
1011
nb = "0.1.2"
1112
spin = "0.5.2"

procmacros/Cargo.toml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
[package]
3+
authors = ["Arjan Mels <[email protected]>"]
4+
categories = ["embedded", "no-std"]
5+
description = "Attributes re-exported in `esp32-hal`"
6+
keywords = ["esp32", "esp32-hal", "runtime", "startup"]
7+
license = "MIT OR Apache-2.0"
8+
name = "esp32-hal-proc-macros"
9+
repository = "https://github.com/esp-rs/xtensa-lx6-rt"
10+
version = "0.1.0"
11+
edition = "2018"
12+
13+
[lib]
14+
proc-macro = true
15+
16+
[dependencies]
17+
quote = "1.0"
18+
proc-macro2 = "1.0"
19+
20+
[dependencies.syn]
21+
features = ["extra-traits", "full"]
22+
version = "1.0"

procmacros/src/lib.rs

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
//! Internal implementation details of `xtensa-lx6-rt`.
2+
//!
3+
//! Do not use this crate directly.
4+
5+
#![deny(warnings)]
6+
#![feature(proc_macro_diagnostic)]
7+
8+
extern crate proc_macro;
9+
10+
use proc_macro::TokenStream;
11+
//use proc_macro2::Span;
12+
use quote::quote;
13+
//use std::collections::HashSet;
14+
use syn::spanned::Spanned;
15+
use syn::Item;
16+
17+
// check if all called function are in ram
18+
// check if all used data i in ram
19+
// check that no constants are use in teh function (these cannot be forced to ram)
20+
fn check_ram_function(func: &syn::ItemFn) {
21+
eprintln!("{:?}", func);
22+
}
23+
24+
#[proc_macro_attribute]
25+
pub fn ram(_args: TokenStream, input: TokenStream) -> TokenStream {
26+
let item: syn::Item = syn::parse(input).expect("failed to parse input");
27+
28+
let section: proc_macro2::TokenStream;
29+
match item {
30+
Item::Static(ref _struct_item) => section = quote! {#[link_section=".data"]},
31+
Item::Const(ref _struct_item) => section = quote! {#[link_section=".data"]},
32+
Item::Fn(ref function_item) => {
33+
check_ram_function(function_item);
34+
section = quote! {#[link_section=".rwtext"]};
35+
}
36+
_ => {
37+
section = quote! {};
38+
item.span()
39+
.unstable()
40+
.error("#[ram] attribute can only be applied to functions, statics and consts")
41+
.emit();
42+
}
43+
}
44+
45+
let output = quote! {
46+
#section
47+
#item
48+
};
49+
output.into()
50+
51+
// let f = parse_macro_input!(input as ItemFn);
52+
/* TokenStream::from(quote!(
53+
#[link_section=".rwtext"]
54+
#f
55+
))*/
56+
57+
/*
58+
// check the function signature
59+
let valid_signature = f.sig.constness.is_none()
60+
&& f.vis == Visibility::Inherited
61+
&& f.sig.abi.is_none()
62+
&& f.sig.inputs.is_empty()
63+
&& f.sig.generics.params.is_empty()
64+
&& f.sig.generics.where_clause.is_none()
65+
&& f.sig.variadic.is_none()
66+
&& match f.sig.output {
67+
ReturnType::Default => false,
68+
ReturnType::Type(_, ref ty) => match **ty {
69+
Type::Never(_) => true,
70+
_ => false,
71+
},
72+
};
73+
74+
if !valid_signature {
75+
return parse::Error::new(
76+
f.span(),
77+
"`#[entry]` function must have signature `[unsafe] fn() -> !`",
78+
)
79+
.to_compile_error()
80+
.into();
81+
}
82+
83+
if !args.is_empty() {
84+
return parse::Error::new(Span::call_site(), "This attribute accepts no arguments")
85+
.to_compile_error()
86+
.into();
87+
}
88+
89+
// XXX should we blacklist other attributes?
90+
let (statics, stmts) = match extract_static_muts(f.block.stmts) {
91+
Err(e) => return e.to_compile_error().into(),
92+
Ok(x) => x,
93+
};
94+
95+
f.sig.ident = Ident::new(
96+
&format!("__xtensa_lx6_rt_{}", f.sig.ident),
97+
Span::call_site(),
98+
);
99+
f.sig.inputs.extend(statics.iter().map(|statik| {
100+
let ident = &statik.ident;
101+
let ty = &statik.ty;
102+
let attrs = &statik.attrs;
103+
104+
// Note that we use an explicit `'static` lifetime for the entry point arguments. This makes
105+
// it more flexible, and is sound here, since the entry will not be called again, ever.
106+
syn::parse::<FnArg>(
107+
quote!(#[allow(non_snake_case)] #(#attrs)* #ident: &'static mut #ty).into(),
108+
)
109+
.unwrap()
110+
}));
111+
f.block.stmts = stmts;
112+
113+
let tramp_ident = Ident::new(&format!("{}_trampoline", f.sig.ident), Span::call_site());
114+
let ident = &f.sig.ident;
115+
116+
let resource_args = statics
117+
.iter()
118+
.map(|statik| {
119+
let (ref cfgs, ref attrs) = extract_cfgs(statik.attrs.clone());
120+
let ident = &statik.ident;
121+
let ty = &statik.ty;
122+
let expr = &statik.expr;
123+
quote! {
124+
#(#cfgs)*
125+
{
126+
#(#attrs)*
127+
static mut #ident: #ty = #expr;
128+
&mut #ident
129+
}
130+
}
131+
})
132+
.collect::<Vec<_>>();
133+
134+
if let Err(error) = check_attr_whitelist(&f.attrs, WhiteListCaller::Entry) {
135+
return error;
136+
}
137+
138+
let (ref cfgs, ref attrs) = extract_cfgs(f.attrs.clone());
139+
quote!(
140+
#(#cfgs)*
141+
#(#attrs)*
142+
#[doc(hidden)]
143+
#[export_name = "main"]
144+
pub unsafe extern "C" fn #tramp_ident() {
145+
#ident(
146+
#(#resource_args),*
147+
)
148+
}
149+
150+
#f
151+
)
152+
.into()
153+
*/
154+
}

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
pub use embedded_hal as hal;
44
pub use esp32;
55

6+
extern crate esp32_hal_proc_macros as proc_macros;
7+
pub use proc_macros::ram;
8+
69
pub mod analog;
710
pub mod clock_control;
811
pub mod dport;

src/prelude.rs

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ pub use embedded_hal::prelude::*;
77
pub use crate::analog::SensExt as _esp32_hal_analog_SensExt;
88
pub use crate::gpio::GpioExt as _esp32_hal_gpio_GpioExt;
99
pub use crate::units::*;
10+
11+
pub use crate::proc_macros::*;

0 commit comments

Comments
 (0)