diff --git a/Cargo.lock b/Cargo.lock index 6fcd313fc..7888c1a0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3337,7 +3337,9 @@ dependencies = [ "esp-hal", "linkme", "panic-semihosting", + "paste", "riot-rs-runqueue", + "static_cell", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b12efb3c9..7ff253f66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -65,6 +65,7 @@ document-features = "0.2.8" heapless = { version = "0.8.0", default-features = false } konst = { version = "0.3.8", default_features = false } ld-memory = { version = "0.2.9" } +paste = { version = "1.0" } static_cell = { version = "2.0.0", features = ["nightly"] } [profile.dev] diff --git a/src/riot-rs-macros/src/thread.rs b/src/riot-rs-macros/src/thread.rs index 19f4773a5..25ae9371a 100644 --- a/src/riot-rs-macros/src/thread.rs +++ b/src/riot-rs-macros/src/thread.rs @@ -37,7 +37,7 @@ pub fn thread(args: TokenStream, item: TokenStream) -> TokenStream { #[allow(clippy::wildcard_imports)] use thread::*; - use quote::{format_ident, quote}; + use quote::quote; let mut attrs = Attributes::default(); let thread_parser = syn::meta::parser(|meta| attrs.parse(&meta)); @@ -57,7 +57,6 @@ pub fn thread(args: TokenStream, item: TokenStream) -> TokenStream { }; let fn_name = thread_function.sig.ident.clone(); - let slice_fn_name_ident = format_ident!("__start_thread_{fn_name}"); let Parameters { stack_size, priority, @@ -69,12 +68,7 @@ pub fn thread(args: TokenStream, item: TokenStream) -> TokenStream { #no_mangle_attr #thread_function - #[#riot_rs_crate::linkme::distributed_slice(#riot_rs_crate::thread::THREAD_FNS)] - #[linkme(crate = #riot_rs_crate::linkme)] - fn #slice_fn_name_ident() { - let stack = #riot_rs_crate::static_cell::make_static!([0u8; #stack_size as usize]); - #riot_rs_crate::thread::thread_create_noarg(#fn_name, stack, #priority); - } + #riot_rs_crate::thread::autostart_thread!(#fn_name, stacksize = #stack_size, priority = #priority); }; TokenStream::from(expanded) diff --git a/src/riot-rs-threads/Cargo.toml b/src/riot-rs-threads/Cargo.toml index 1cbdf810f..3988bd974 100644 --- a/src/riot-rs-threads/Cargo.toml +++ b/src/riot-rs-threads/Cargo.toml @@ -14,7 +14,9 @@ workspace = true cfg-if.workspace = true critical-section.workspace = true linkme = { workspace = true } +paste.workspace = true riot-rs-runqueue.workspace = true +static_cell.workspace = true [target.'cfg(context = "esp32c3")'.dependencies] esp-hal = { workspace = true, features = ["esp32c3"] } diff --git a/src/riot-rs-threads/src/autostart_thread.rs b/src/riot-rs-threads/src/autostart_thread.rs new file mode 100644 index 000000000..f1e5e6e34 --- /dev/null +++ b/src/riot-rs-threads/src/autostart_thread.rs @@ -0,0 +1,16 @@ +/// Starts the `fn_name` function in a dedicated thread at startup. +/// +/// The thread is given a `stacksize`-byte stack, and has priority `priority`. +#[macro_export] +macro_rules! autostart_thread { + ($fn_name:ident, stacksize = $stacksize:literal, priority = $priority:literal) => { + $crate::macro_reexports::paste::paste! { + #[$crate::macro_reexports::linkme::distributed_slice($crate::THREAD_FNS)] + #[linkme(crate = $crate::macro_reexports::linkme)] + fn [<__start_thread_ $fn_name>] () { + let stack = $crate::macro_reexports::static_cell::make_static!([0u8; $stacksize as usize]); + $crate::thread_create_noarg($fn_name, stack, $priority); + } + } + }; +} diff --git a/src/riot-rs-threads/src/lib.rs b/src/riot-rs-threads/src/lib.rs index 0cecd34dd..436d2b62a 100644 --- a/src/riot-rs-threads/src/lib.rs +++ b/src/riot-rs-threads/src/lib.rs @@ -7,6 +7,7 @@ #![allow(clippy::indexing_slicing)] mod arch; +mod autostart_thread; mod ensure_once; mod thread; mod threadlist; @@ -15,6 +16,14 @@ pub mod channel; pub mod lock; pub mod thread_flags; +#[doc(hidden)] +pub mod macro_reexports { + // Used by `autostart_thread` + pub use linkme; + pub use paste; + pub use static_cell; +} + pub use riot_rs_runqueue::{RunqueueId, ThreadId}; pub use thread_flags as flags;