Skip to content

feat: add Ariel OS support #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,8 @@ embassy = [
# you will use your own executor by setting it via the `tasks` macro, e.g. `#[embedded_test::tests(executor = esp_hal::embassy::executor::thread::Executor::new())]`
external-executor = ["embedded-test-macros/external-executor"]

# Enables Ariel OS integration
ariel-os = ["embedded-test-macros/ariel-os", "embassy"]

# enables the xtensa-specific semihosting implementation
xtensa-semihosting = ["semihosting/openocd-semihosting"]
1 change: 1 addition & 0 deletions macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ darling = "0.20.8"
[features]
embassy = []
external-executor = []
ariel-os = []

[dev-dependencies]
trybuild = "1"
72 changes: 56 additions & 16 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ fn tests_impl(args: TokenStream, input: TokenStream) -> parse::Result<TokenStrea
));
}

#[cfg(feature = "ariel-os")]
if macro_args.executor.is_some() {
return Err(parse::Error::new(
proc_macro2::Span::call_site(),
"`#[embedded_test::tests]` attribute doesn't take an executor the feature `ariel-os` is enabled",
));
}

let module: ItemMod = syn::parse(input)?;

let items = if let Some(content) = module.content {
Expand Down Expand Up @@ -339,6 +347,12 @@ fn tests_impl(args: TokenStream, input: TokenStream) -> parse::Result<TokenStrea
}
);

let task_path = if cfg!(feature = "ariel-os") {
quote!(ariel_os::task)
} else {
quote!(#krate::export::task)
};

// The closure that will be called, if the test should be runned.
// This closure has the signature () -> !, so it will never return.
// The closure will signal the test result via semihosting exit/abort instead
Expand All @@ -347,29 +361,37 @@ fn tests_impl(args: TokenStream, input: TokenStream) -> parse::Result<TokenStrea
let cfgs = &test.cfgs;
test_function_invokers.push(quote!(
#(#cfgs)*
#[#krate::export::task]
#[#task_path]
async fn #ident_invoker() {
#init_run_and_check
}
));

let executor = if let Some(executor) = &macro_args.executor {
quote! {
#executor
}
if cfg!(feature = "ariel-os") {
quote!(|| {
ariel_os::asynch::spawner().must_spawn(#ident_invoker());
ariel_os::thread::park();
unreachable!();
})
} else {
quote! {
#krate::export::Executor::new()
}
};
let executor = if let Some(executor) = &macro_args.executor {
quote! {
#executor
}
} else {
quote! {
#krate::export::Executor::new()
}
};

quote!(|| {
let mut executor = #executor;
let executor = unsafe { __make_static(&mut executor) };
executor.run(|spawner| {
spawner.must_spawn(#ident_invoker());
quote!(|| {
let mut executor = #executor;
let executor = unsafe { __make_static(&mut executor) };
executor.run(|spawner| {
spawner.must_spawn(#ident_invoker());
})
})
})
}
} else {
quote!(|| {
#init_run_and_check
Expand Down Expand Up @@ -420,6 +442,22 @@ fn tests_impl(args: TokenStream, input: TokenStream) -> parse::Result<TokenStrea
};
let setup = macro_args.setup;

let (thread_start, maybe_export_name) = if cfg!(feature = "ariel-os") {
(
quote!(
// TODO: make stack size configurable
//#[cfg(feature = "ariel-os")]
#[ariel_os::thread(autostart, stacksize = 16384)]
fn embedded_test_thread() {
unsafe { __embedded_test_entry() }
}
),
quote!(),
)
} else {
(quote!(), quote!(#[export_name = "main"]))
};

Ok(quote!(
#[cfg(test)]
mod #ident {
Expand All @@ -435,7 +473,9 @@ fn tests_impl(args: TokenStream, input: TokenStream) -> parse::Result<TokenStrea
::core::mem::transmute(t)
}

#[export_name = "main"]
#thread_start

#maybe_export_name
unsafe extern "C" fn __embedded_test_entry() -> ! {
// The linker file will redirect this call to the function below.
// This trick ensures that we get a compile error, if the linker file was not added to the rustflags.
Expand Down
8 changes: 6 additions & 2 deletions src/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ pub fn ensure_linker_file_was_added_to_rustflags() -> ! {
}

// Reexport the embassy stuff
#[cfg(feature = "embassy")]
#[cfg(all(feature = "embassy", not(feature = "ariel-os")))]
pub use embassy_executor::task;
#[cfg(all(feature = "embassy", not(feature = "external-executor")))]
#[cfg(all(
feature = "embassy",
not(feature = "external-executor"),
not(feature = "ariel-os")
))]
pub use embassy_executor::Executor; // Please activate the `executor-thread` or `executor-interrupt` feature on the embassy-executor crate (v0.7.x)!

const VERSION: u32 = 1; //Format version of our protocol between probe-rs and target running embedded-test
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ mod fmt;

pub use embedded_test_macros::tests;

#[cfg(feature = "panic-handler")]
#[cfg(all(feature = "panic-handler", not(feature = "ariel-os")))]
#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
error!("====================== PANIC ======================");
Expand Down
Loading