diff options
author | 2021-04-08 08:15:05 +0000 | |
---|---|---|
committer | 2021-04-08 08:15:05 +0000 | |
commit | 83cdf00eecb0f14857b5e0f28e884b2120eabb18 (patch) | |
tree | 17f732cbb06dd480bd0881d0ec627cc173ba5bfc | |
parent | 6c8257bb73de0f68072467447692a1f7dff555f9 (diff) | |
parent | 51500a1d7096395be9162599fae647ec121db91d (diff) | |
download | rtic-83cdf00eecb0f14857b5e0f28e884b2120eabb18.tar.gz rtic-83cdf00eecb0f14857b5e0f28e884b2120eabb18.tar.zst rtic-83cdf00eecb0f14857b5e0f28e884b2120eabb18.zip |
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>
-rw-r--r-- | examples/t-schedule.rs | 33 | ||||
-rw-r--r-- | examples/type-usage.rs | 15 | ||||
-rw-r--r-- | macros/Cargo.toml | 3 | ||||
-rw-r--r-- | macros/src/codegen.rs | 16 | ||||
-rw-r--r-- | macros/src/codegen/hardware_tasks.rs | 4 | ||||
-rw-r--r-- | macros/src/codegen/module.rs | 37 | ||||
-rw-r--r-- | src/tq.rs | 6 |
7 files changed, 75 insertions, 39 deletions
diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs index ef04c451..5e38dbaf 100644 --- a/examples/t-schedule.rs +++ b/examples/t-schedule.rs @@ -26,24 +26,27 @@ mod app { // Task without message passing // 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 _: Result<foo::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_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 _: Result<(), ()> = handle.unwrap().cancel(); // 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 _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_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 _: Result<(), ()> = handle.unwrap().cancel(); @@ -51,7 +54,8 @@ mod app { // Task with single message passing // 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> = bar::MyMono::spawn_after(Seconds(1_u32), 0); let _: Result<bar::MyMono::SpawnHandle, ()> = @@ -59,19 +63,21 @@ mod app { let handle: Result<bar::MyMono::SpawnHandle, u32> = 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> = bar::MyMono::spawn_after(Seconds(1_u32), 0); let _: Result<u32, ()> = handle.unwrap().cancel(); // 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 _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32)); 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 _: Result<u32, ()> = handle.unwrap().cancel(); @@ -80,7 +86,7 @@ mod app { // Not default 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)> = baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); let _: Result<baz::MyMono::SpawnHandle, ()> = @@ -88,19 +94,22 @@ mod app { let handle: Result<baz::MyMono::SpawnHandle, (u32, u32)> = 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)> = baz::MyMono::spawn_after(Seconds(1_u32), 0, 1); let _: Result<(u32, u32), ()> = handle.unwrap().cancel(); // 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 _: 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 _: 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 _: Result<(u32, u32), ()> = handle.unwrap().cancel(); diff --git a/examples/type-usage.rs b/examples/type-usage.rs new file mode 100644 index 00000000..9bb7eb8d --- /dev/null +++ b/examples/type-usage.rs @@ -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) {} +} diff --git a/macros/Cargo.toml b/macros/Cargo.toml index f14b1046..203a2bb1 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -22,5 +22,4 @@ proc-macro2 = "1" proc-macro-error = "1" quote = "1" syn = "1" -rtic-syntax = "0.5.0-alpha.1" - +rtic-syntax = "0.5.0-alpha.2" diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index c5d95687..cf728a7d 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -112,8 +112,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let user_imports = &app.user_imports; quote! { - pub use rtic::Monotonic as _; - #[doc = #doc] #[allow(non_snake_case)] pub mod #name { @@ -143,6 +141,18 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { }) .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(); 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 use #device as #rt_err; - #(#monotonic_parts)* + #monotonics #(#user_imports)* diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs index 4a1d7492..540b95e5 100644 --- a/macros/src/codegen/hardware_tasks.rs +++ b/macros/src/codegen/hardware_tasks.rs @@ -37,12 +37,16 @@ pub fn codegen( let symbol = task.args.binds.clone(); let priority = task.args.priority; + let cfgs = &task.cfgs; + let attrs = &task.attrs; let app_name = &app.name; let app_path = quote! {crate::#app_name}; mod_app.push(quote!( #[allow(non_snake_case)] #[no_mangle] + #(#attrs)* + #(#cfgs)* unsafe fn #symbol() { const PRIORITY: u8 = #priority; diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index e15aab1c..50146c02 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -21,7 +21,7 @@ pub fn codegen( let app_name = &app.name; let app_path = quote! {crate::#app_name}; - let all_task_names: Vec<_> = app + let all_task_imports: Vec<_> = app .software_tasks .iter() .map(|(name, st)| { @@ -46,6 +46,13 @@ pub fn codegen( quote!() } })) + .chain(app.user_types.iter().map(|ty| { + let t = &ty.ident; + quote! { + #[allow(unused_imports)] + use super::#t; + } + })) .collect(); let mut lt = None; @@ -230,7 +237,7 @@ pub fn codegen( // Spawn caller items.push(quote!( - #(#all_task_names)* + #(#all_task_imports)* #(#cfgs)* /// Spawns the task directly @@ -268,7 +275,7 @@ pub fn codegen( let tq = util::mark_internal_ident(&tq); let t = util::schedule_t_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::mark_internal_ident(&m_ident); let m_isr = &monotonic.args.binds; @@ -300,10 +307,6 @@ pub fn codegen( items.push(quote!( /// Holds methods related to this monotonic pub mod #m { - // #( - // #[allow(unused_imports)] - // use #app_path::#all_task_names as #all_task_names; - // )* use super::*; #[allow(unused_imports)] use #app_path::#tq_marker; @@ -341,7 +344,7 @@ pub fn codegen( where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, 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, ()> @@ -373,7 +376,7 @@ pub fn codegen( let instant = if rtic::export::interrupt::free(|_| unsafe { #app_path::#m_ident.is_none() }) { rtic::time::Instant::new(0) } else { - #app_path::#m::now() + #app_path::monotonics::#m::now() }; spawn_at(instant + duration #(,#untupled)*) @@ -411,17 +414,11 @@ pub fn codegen( let tq = unsafe { &mut *#app_path::#tq.as_mut_ptr() }; - if let Some(mono) = #app_path::#m_ident.as_mut() { - tq.enqueue_unchecked( - nr, - || #enable_interrupt, - || #pend, - 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() - } + tq.enqueue_unchecked( + nr, + || #enable_interrupt, + || #pend, + #app_path::#m_ident.as_mut()); Ok(SpawnHandle { marker }) }) @@ -42,7 +42,7 @@ where nr: NotReady<Mono, Task>, enable_interrupt: F1, pend_handler: F2, - mono: &mut Mono, + mono: Option<&mut Mono>, ) where F1: FnOnce(), F2: FnOnce(), @@ -57,7 +57,9 @@ where if if_heap_max_greater_than_nr { if Mono::DISABLE_INTERRUPT_ON_EMPTY_QUEUE && self.0.is_empty() { - mono.enable_timer(); + if let Some(mono) = mono { + mono.enable_timer(); + } enable_interrupt(); } |