aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-05-19 14:14:08 +0000
committerGitHub <[email protected]>2023-05-19 14:14:08 +0000
commit464018e12db16f5926f49cfc8c348baee07f5fa7 (patch)
treea44c2bbe0e948f2d0a4fd5d434419c431d4d9d89
parent55e4a89819b68a8c3c8e54b50901ac96b08dd710 (diff)
parent4e9ed223a9c489ec75d2d928e26d5a83c2cdf5d4 (diff)
Merge #1463
1463: Allow for an optional user-defined entry macro when targeting RISC-V r=Dirbaio a=jessebraham In [esp-hal](https://github.com/esp-rs/esp-hal) we use our own custom runtime crate, [esp-riscv-rt](https://github.com/esp-rs/esp-riscv-rt). This PR adds the ability to optionally specify an entry macro when using `embassy_executor::main`. The following forms are both accepted: ```rust #[embassy_executor::main] // uses `riscv_rt::entry` by default async fn main() {} #[embassy_executor::main(entry = "esp_riscv_rt::entry")] async fn main() {} ``` I attempted to get this working without needing to quote the entry macro argument, however I was not able to get this working. Based off some reading I did this may not be possible, however I am rather inexperienced with proc macros. Happy to change this if anybody has any insight. Co-authored-by: Jesse Braham <[email protected]>
-rw-r--r--embassy-macros/src/lib.rs14
-rw-r--r--embassy-macros/src/macros/main.rs22
2 files changed, 31 insertions, 5 deletions
diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs
index d2c696c72..dc5b519ff 100644
--- a/embassy-macros/src/lib.rs
+++ b/embassy-macros/src/lib.rs
@@ -79,6 +79,8 @@ pub fn main_cortex_m(args: TokenStream, item: TokenStream) -> TokenStream {
79/// * The function must not use generics. 79/// * The function must not use generics.
80/// * Only a single `main` task may be declared. 80/// * Only a single `main` task may be declared.
81/// 81///
82/// A user-defined entry macro can be optionally provided via the `entry` argument to override the default of `riscv_rt::entry`.
83///
82/// ## Examples 84/// ## Examples
83/// Spawning a task: 85/// Spawning a task:
84/// 86///
@@ -88,11 +90,21 @@ pub fn main_cortex_m(args: TokenStream, item: TokenStream) -> TokenStream {
88/// // Function body 90/// // Function body
89/// } 91/// }
90/// ``` 92/// ```
93///
94/// Spawning a task using a custom entry macro:
95/// ``` rust
96/// #[embassy_executor::main(entry = "esp_riscv_rt::entry")]
97/// async fn main(_s: embassy_executor::Spawner) {
98/// // Function body
99/// }
100/// ```
91#[proc_macro_attribute] 101#[proc_macro_attribute]
92pub fn main_riscv(args: TokenStream, item: TokenStream) -> TokenStream { 102pub fn main_riscv(args: TokenStream, item: TokenStream) -> TokenStream {
93 let args = syn::parse_macro_input!(args as syn::AttributeArgs); 103 let args = syn::parse_macro_input!(args as syn::AttributeArgs);
94 let f = syn::parse_macro_input!(item as syn::ItemFn); 104 let f = syn::parse_macro_input!(item as syn::ItemFn);
95 main::run(args, f, main::riscv()).unwrap_or_else(|x| x).into() 105 main::run(args.clone(), f, main::riscv(args))
106 .unwrap_or_else(|x| x)
107 .into()
96} 108}
97 109
98/// Creates a new `executor` instance and declares an application entry point for STD spawning the corresponding function body as an async task. 110/// Creates a new `executor` instance and declares an application entry point for STD spawning the corresponding function body as an async task.
diff --git a/embassy-macros/src/macros/main.rs b/embassy-macros/src/macros/main.rs
index 6ae77398d..5c099f68a 100644
--- a/embassy-macros/src/macros/main.rs
+++ b/embassy-macros/src/macros/main.rs
@@ -1,16 +1,30 @@
1use darling::FromMeta; 1use darling::FromMeta;
2use proc_macro2::TokenStream; 2use proc_macro2::TokenStream;
3use quote::quote; 3use quote::quote;
4use syn::{ReturnType, Type}; 4use syn::{Expr, ReturnType, Type};
5 5
6use crate::util::ctxt::Ctxt; 6use crate::util::ctxt::Ctxt;
7 7
8#[derive(Debug, FromMeta)] 8#[derive(Debug, FromMeta)]
9struct Args {} 9struct Args {
10 #[darling(default)]
11 entry: Option<String>,
12}
13
14pub fn riscv(args: syn::AttributeArgs) -> TokenStream {
15 let maybe_entry = match Args::from_list(&args) {
16 Ok(args) => args.entry,
17 Err(e) => return e.write_errors(),
18 };
19
20 let entry = maybe_entry.unwrap_or("riscv_rt::entry".into());
21 let entry = match Expr::from_string(&entry) {
22 Ok(expr) => expr,
23 Err(e) => return e.write_errors(),
24 };
10 25
11pub fn riscv() -> TokenStream {
12 quote! { 26 quote! {
13 #[riscv_rt::entry] 27 #[#entry]
14 fn main() -> ! { 28 fn main() -> ! {
15 let mut executor = ::embassy_executor::Executor::new(); 29 let mut executor = ::embassy_executor::Executor::new();
16 let executor = unsafe { __make_static(&mut executor) }; 30 let executor = unsafe { __make_static(&mut executor) };