mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-27 14:04:56 +01:00
Merge #466
466: Fix for type aliases in `mod app`, UB in `spawn_at`, and `#[cfg]` in hardware tasks r=AfoHT a=korken89 Type aliases such as the following did not work in `0.6-alpha`: ```rust use rtic::app; #[app(device = lm3s6965, dispatchers = [SSI0])] mod app { type Test = u32; #[task] fn t1(_: t1::Context, _val: Test) {} } ``` Plus that accessing associated constants of monotonic timers was not working as it should dues to the syntax and codegen transforming: ```rust #[monotonic(binds = SysTick, default = true)] type MyMono = DwtSystick<8_000_000>; // 8 MHz ``` into ```rust mod MyMono { // ... } ``` causing the original `type MyMono` to not exist anymore. This PR fixes this and adds test to check for this by doing the following expansion instead: ```rust #[monotonic(binds = SysTick, default = true)] type MyMono = DwtSystick<8_000_000>; // 8 MHz ``` into ```rust type MyMono = DwtSystick<8_000_000>; mod monotonics { mod MyMono { // ... } // And other monotonics go here as well } ``` **Breaking change** This causes a breaking change in accessing the `MyMono::now()` method which now exists under `monotonics::MyMono::now()`. --- Moreover a UB issue was found and fixed in `spawn_at` and hardware tasks properly propagate `#[cfg]`s. Closes #460 Closes #462 Closes #463 Co-authored-by: Emil Fresk <emil.fresk@gmail.com>
This commit is contained in:
commit
83cdf00eec
7 changed files with 75 additions and 39 deletions
|
@ -26,24 +26,27 @@ mod app {
|
||||||
// Task without message passing
|
// Task without message passing
|
||||||
|
|
||||||
// Not default
|
// Not default
|
||||||
let _: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_at(MyMono::now());
|
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
||||||
|
foo::MyMono::spawn_at(monotonics::MyMono::now());
|
||||||
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32));
|
||||||
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
||||||
handle.unwrap().reschedule_after(Seconds(1_u32));
|
handle.unwrap().reschedule_after(Seconds(1_u32));
|
||||||
|
|
||||||
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32));
|
||||||
let _: Result<foo::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_at(MyMono::now());
|
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
||||||
|
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||||
|
|
||||||
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::MyMono::SpawnHandle, ()> = foo::MyMono::spawn_after(Seconds(1_u32));
|
||||||
let _: Result<(), ()> = handle.unwrap().cancel();
|
let _: Result<(), ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
// Using default
|
// Using default
|
||||||
let _: Result<foo::SpawnHandle, ()> = foo::spawn_at(MyMono::now());
|
let _: Result<foo::SpawnHandle, ()> = foo::spawn_at(monotonics::MyMono::now());
|
||||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
||||||
let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
||||||
|
|
||||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
||||||
let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_at(MyMono::now());
|
let _: Result<foo::SpawnHandle, ()> =
|
||||||
|
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||||
|
|
||||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
||||||
let _: Result<(), ()> = handle.unwrap().cancel();
|
let _: Result<(), ()> = handle.unwrap().cancel();
|
||||||
|
@ -51,7 +54,8 @@ mod app {
|
||||||
// Task with single message passing
|
// Task with single message passing
|
||||||
|
|
||||||
// Not default
|
// Not default
|
||||||
let _: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_at(MyMono::now(), 0);
|
let _: Result<bar::MyMono::SpawnHandle, u32> =
|
||||||
|
bar::MyMono::spawn_at(monotonics::MyMono::now(), 0);
|
||||||
let handle: Result<bar::MyMono::SpawnHandle, u32> =
|
let handle: Result<bar::MyMono::SpawnHandle, u32> =
|
||||||
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
||||||
let _: Result<bar::MyMono::SpawnHandle, ()> =
|
let _: Result<bar::MyMono::SpawnHandle, ()> =
|
||||||
|
@ -59,19 +63,21 @@ mod app {
|
||||||
|
|
||||||
let handle: Result<bar::MyMono::SpawnHandle, u32> =
|
let handle: Result<bar::MyMono::SpawnHandle, u32> =
|
||||||
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
||||||
let _: Result<bar::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_at(MyMono::now());
|
let _: Result<bar::MyMono::SpawnHandle, ()> =
|
||||||
|
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||||
|
|
||||||
let handle: Result<bar::MyMono::SpawnHandle, u32> =
|
let handle: Result<bar::MyMono::SpawnHandle, u32> =
|
||||||
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
||||||
let _: Result<u32, ()> = handle.unwrap().cancel();
|
let _: Result<u32, ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
// Using default
|
// Using default
|
||||||
let _: Result<bar::SpawnHandle, u32> = bar::spawn_at(MyMono::now(), 0);
|
let _: Result<bar::SpawnHandle, u32> = bar::spawn_at(monotonics::MyMono::now(), 0);
|
||||||
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0);
|
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0);
|
||||||
let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
||||||
|
|
||||||
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0);
|
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0);
|
||||||
let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_at(MyMono::now());
|
let _: Result<bar::SpawnHandle, ()> =
|
||||||
|
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||||
|
|
||||||
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0);
|
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0);
|
||||||
let _: Result<u32, ()> = handle.unwrap().cancel();
|
let _: Result<u32, ()> = handle.unwrap().cancel();
|
||||||
|
@ -80,7 +86,7 @@ mod app {
|
||||||
|
|
||||||
// Not default
|
// Not default
|
||||||
let _: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
let _: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||||
baz::MyMono::spawn_at(MyMono::now(), 0, 1);
|
baz::MyMono::spawn_at(monotonics::MyMono::now(), 0, 1);
|
||||||
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||||
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1);
|
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1);
|
||||||
let _: Result<baz::MyMono::SpawnHandle, ()> =
|
let _: Result<baz::MyMono::SpawnHandle, ()> =
|
||||||
|
@ -88,19 +94,22 @@ mod app {
|
||||||
|
|
||||||
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||||
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1);
|
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1);
|
||||||
let _: Result<baz::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_at(MyMono::now());
|
let _: Result<baz::MyMono::SpawnHandle, ()> =
|
||||||
|
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||||
|
|
||||||
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||||
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1);
|
baz::MyMono::spawn_after(Seconds(1_u32), 0, 1);
|
||||||
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
// Using default
|
// Using default
|
||||||
let _: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_at(MyMono::now(), 0, 1);
|
let _: Result<baz::SpawnHandle, (u32, u32)> =
|
||||||
|
baz::spawn_at(monotonics::MyMono::now(), 0, 1);
|
||||||
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1);
|
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1);
|
||||||
let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
||||||
|
|
||||||
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1);
|
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1);
|
||||||
let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_at(MyMono::now());
|
let _: Result<baz::SpawnHandle, ()> =
|
||||||
|
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
||||||
|
|
||||||
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1);
|
let handle: Result<baz::SpawnHandle, (u32, u32)> = baz::spawn_after(Seconds(1_u32), 0, 1);
|
||||||
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
||||||
|
|
15
examples/type-usage.rs
Normal file
15
examples/type-usage.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
//! examples/type-usage.rs
|
||||||
|
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use panic_semihosting as _; // panic handler
|
||||||
|
use rtic::app;
|
||||||
|
|
||||||
|
#[app(device = lm3s6965, dispatchers = [SSI0])]
|
||||||
|
mod app {
|
||||||
|
type Test = u32;
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
fn t1(_: t1::Context, _val: Test) {}
|
||||||
|
}
|
|
@ -22,5 +22,4 @@ proc-macro2 = "1"
|
||||||
proc-macro-error = "1"
|
proc-macro-error = "1"
|
||||||
quote = "1"
|
quote = "1"
|
||||||
syn = "1"
|
syn = "1"
|
||||||
rtic-syntax = "0.5.0-alpha.1"
|
rtic-syntax = "0.5.0-alpha.2"
|
||||||
|
|
||||||
|
|
|
@ -112,8 +112,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
let user_imports = &app.user_imports;
|
let user_imports = &app.user_imports;
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
pub use rtic::Monotonic as _;
|
|
||||||
|
|
||||||
#[doc = #doc]
|
#[doc = #doc]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub mod #name {
|
pub mod #name {
|
||||||
|
@ -143,6 +141,18 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
let monotonics = if !monotonic_parts.is_empty() {
|
||||||
|
quote!(
|
||||||
|
pub use rtic::Monotonic as _;
|
||||||
|
|
||||||
|
/// Holds static methods for each monotonic.
|
||||||
|
pub mod monotonics {
|
||||||
|
#(#monotonic_parts)*
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
quote!()
|
||||||
|
};
|
||||||
let rt_err = util::rt_err_ident();
|
let rt_err = util::rt_err_ident();
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
|
@ -151,7 +161,7 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
/// Always include the device crate which contains the vector table
|
/// Always include the device crate which contains the vector table
|
||||||
use #device as #rt_err;
|
use #device as #rt_err;
|
||||||
|
|
||||||
#(#monotonic_parts)*
|
#monotonics
|
||||||
|
|
||||||
#(#user_imports)*
|
#(#user_imports)*
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,16 @@ pub fn codegen(
|
||||||
|
|
||||||
let symbol = task.args.binds.clone();
|
let symbol = task.args.binds.clone();
|
||||||
let priority = task.args.priority;
|
let priority = task.args.priority;
|
||||||
|
let cfgs = &task.cfgs;
|
||||||
|
let attrs = &task.attrs;
|
||||||
|
|
||||||
let app_name = &app.name;
|
let app_name = &app.name;
|
||||||
let app_path = quote! {crate::#app_name};
|
let app_path = quote! {crate::#app_name};
|
||||||
mod_app.push(quote!(
|
mod_app.push(quote!(
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
#(#attrs)*
|
||||||
|
#(#cfgs)*
|
||||||
unsafe fn #symbol() {
|
unsafe fn #symbol() {
|
||||||
const PRIORITY: u8 = #priority;
|
const PRIORITY: u8 = #priority;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub fn codegen(
|
||||||
let app_name = &app.name;
|
let app_name = &app.name;
|
||||||
let app_path = quote! {crate::#app_name};
|
let app_path = quote! {crate::#app_name};
|
||||||
|
|
||||||
let all_task_names: Vec<_> = app
|
let all_task_imports: Vec<_> = app
|
||||||
.software_tasks
|
.software_tasks
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(name, st)| {
|
.map(|(name, st)| {
|
||||||
|
@ -46,6 +46,13 @@ pub fn codegen(
|
||||||
quote!()
|
quote!()
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.chain(app.user_types.iter().map(|ty| {
|
||||||
|
let t = &ty.ident;
|
||||||
|
quote! {
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use super::#t;
|
||||||
|
}
|
||||||
|
}))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut lt = None;
|
let mut lt = None;
|
||||||
|
@ -230,7 +237,7 @@ pub fn codegen(
|
||||||
// Spawn caller
|
// Spawn caller
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
|
|
||||||
#(#all_task_names)*
|
#(#all_task_imports)*
|
||||||
|
|
||||||
#(#cfgs)*
|
#(#cfgs)*
|
||||||
/// Spawns the task directly
|
/// Spawns the task directly
|
||||||
|
@ -268,7 +275,7 @@ pub fn codegen(
|
||||||
let tq = util::mark_internal_ident(&tq);
|
let tq = util::mark_internal_ident(&tq);
|
||||||
let t = util::schedule_t_ident();
|
let t = util::schedule_t_ident();
|
||||||
let m = &monotonic.ident;
|
let m = &monotonic.ident;
|
||||||
let mono_type = &monotonic.ty;
|
let mono_type = &monotonic.ident;
|
||||||
let m_ident = util::monotonic_ident(&monotonic_name);
|
let m_ident = util::monotonic_ident(&monotonic_name);
|
||||||
let m_ident = util::mark_internal_ident(&m_ident);
|
let m_ident = util::mark_internal_ident(&m_ident);
|
||||||
let m_isr = &monotonic.args.binds;
|
let m_isr = &monotonic.args.binds;
|
||||||
|
@ -300,10 +307,6 @@ pub fn codegen(
|
||||||
items.push(quote!(
|
items.push(quote!(
|
||||||
/// Holds methods related to this monotonic
|
/// Holds methods related to this monotonic
|
||||||
pub mod #m {
|
pub mod #m {
|
||||||
// #(
|
|
||||||
// #[allow(unused_imports)]
|
|
||||||
// use #app_path::#all_task_names as #all_task_names;
|
|
||||||
// )*
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use #app_path::#tq_marker;
|
use #app_path::#tq_marker;
|
||||||
|
@ -341,7 +344,7 @@ pub fn codegen(
|
||||||
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
||||||
D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>,
|
D::T: Into<<#app_path::#mono_type as rtic::time::Clock>::T>,
|
||||||
{
|
{
|
||||||
self.reschedule_at(#app_path::#m::now() + duration)
|
self.reschedule_at(#app_path::monotonics::#m::now() + duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reschedule_at(self, instant: rtic::time::Instant<#app_path::#mono_type>) -> Result<Self, ()>
|
pub fn reschedule_at(self, instant: rtic::time::Instant<#app_path::#mono_type>) -> Result<Self, ()>
|
||||||
|
@ -373,7 +376,7 @@ pub fn codegen(
|
||||||
let instant = if rtic::export::interrupt::free(|_| unsafe { #app_path::#m_ident.is_none() }) {
|
let instant = if rtic::export::interrupt::free(|_| unsafe { #app_path::#m_ident.is_none() }) {
|
||||||
rtic::time::Instant::new(0)
|
rtic::time::Instant::new(0)
|
||||||
} else {
|
} else {
|
||||||
#app_path::#m::now()
|
#app_path::monotonics::#m::now()
|
||||||
};
|
};
|
||||||
|
|
||||||
spawn_at(instant + duration #(,#untupled)*)
|
spawn_at(instant + duration #(,#untupled)*)
|
||||||
|
@ -411,17 +414,11 @@ pub fn codegen(
|
||||||
|
|
||||||
let tq = unsafe { &mut *#app_path::#tq.as_mut_ptr() };
|
let tq = unsafe { &mut *#app_path::#tq.as_mut_ptr() };
|
||||||
|
|
||||||
if let Some(mono) = #app_path::#m_ident.as_mut() {
|
tq.enqueue_unchecked(
|
||||||
tq.enqueue_unchecked(
|
nr,
|
||||||
nr,
|
|| #enable_interrupt,
|
||||||
|| #enable_interrupt,
|
|| #pend,
|
||||||
|| #pend,
|
#app_path::#m_ident.as_mut());
|
||||||
mono)
|
|
||||||
} else {
|
|
||||||
// We can only use the timer queue if `init` has returned, and it
|
|
||||||
// writes the `Some(monotonic)` we are accessing here.
|
|
||||||
core::hint::unreachable_unchecked()
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(SpawnHandle { marker })
|
Ok(SpawnHandle { marker })
|
||||||
})
|
})
|
||||||
|
|
|
@ -42,7 +42,7 @@ where
|
||||||
nr: NotReady<Mono, Task>,
|
nr: NotReady<Mono, Task>,
|
||||||
enable_interrupt: F1,
|
enable_interrupt: F1,
|
||||||
pend_handler: F2,
|
pend_handler: F2,
|
||||||
mono: &mut Mono,
|
mono: Option<&mut Mono>,
|
||||||
) where
|
) where
|
||||||
F1: FnOnce(),
|
F1: FnOnce(),
|
||||||
F2: FnOnce(),
|
F2: FnOnce(),
|
||||||
|
@ -57,7 +57,9 @@ where
|
||||||
|
|
||||||
if if_heap_max_greater_than_nr {
|
if if_heap_max_greater_than_nr {
|
||||||
if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE && self.0.is_empty() {
|
if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE && self.0.is_empty() {
|
||||||
mono.enable_timer();
|
if let Some(mono) = mono {
|
||||||
|
mono.enable_timer();
|
||||||
|
}
|
||||||
enable_interrupt();
|
enable_interrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue