mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-25 21:19:35 +01:00
New monotonic trait working
This commit is contained in:
parent
ae034aec14
commit
0dcb0c4e49
11 changed files with 66 additions and 106 deletions
|
@ -22,7 +22,8 @@ name = "rtic"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cortex-m = "0.7.0"
|
cortex-m = "0.7.0"
|
||||||
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-rc.3" }
|
cortex-m-rtic-macros = { path = "macros", version = "0.6.0-rc.3" }
|
||||||
rtic-monotonic = "0.1.0-rc.1"
|
# rtic-monotonic = "0.1.0-rc.1"
|
||||||
|
rtic-monotonic = { git = "https://github.com/rtic-rs/rtic-monotonic.git", branch = "master" }
|
||||||
rtic-core = "0.3.1"
|
rtic-core = "0.3.1"
|
||||||
heapless = "0.7.7"
|
heapless = "0.7.7"
|
||||||
bare-metal = "1.0.0"
|
bare-metal = "1.0.0"
|
||||||
|
@ -33,7 +34,7 @@ version_check = "0.9"
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
lm3s6965 = "0.1.3"
|
lm3s6965 = "0.1.3"
|
||||||
cortex-m-semihosting = "0.3.3"
|
cortex-m-semihosting = "0.3.3"
|
||||||
systick-monotonic = "0.1.0-rc.1"
|
systick-monotonic = { git = "https://github.com/rtic-rs/systick-monotonic.git", branch = "new-trait-and-time-lib" }
|
||||||
|
|
||||||
[dev-dependencies.panic-semihosting]
|
[dev-dependencies.panic-semihosting]
|
||||||
features = ["exit"]
|
features = ["exit"]
|
||||||
|
|
|
@ -10,8 +10,7 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||||
mod app {
|
mod app {
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use rtic::time::duration::*;
|
use systick_monotonic::*;
|
||||||
use systick_monotonic::Systick;
|
|
||||||
|
|
||||||
#[monotonic(binds = SysTick, default = true)]
|
#[monotonic(binds = SysTick, default = true)]
|
||||||
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
||||||
|
@ -32,7 +31,7 @@ mod app {
|
||||||
hprintln!("init").ok();
|
hprintln!("init").ok();
|
||||||
|
|
||||||
// Schedule `foo` to run 1 second in the future
|
// Schedule `foo` to run 1 second in the future
|
||||||
foo::spawn_after(1.seconds()).unwrap();
|
foo::spawn_after(1.secs()).unwrap();
|
||||||
|
|
||||||
(
|
(
|
||||||
Shared {},
|
Shared {},
|
||||||
|
@ -46,8 +45,8 @@ mod app {
|
||||||
hprintln!("foo").ok();
|
hprintln!("foo").ok();
|
||||||
|
|
||||||
// Schedule `bar` to run 2 seconds in the future (1 second after foo runs)
|
// Schedule `bar` to run 2 seconds in the future (1 second after foo runs)
|
||||||
let spawn_handle = baz::spawn_after(2.seconds()).unwrap();
|
let spawn_handle = baz::spawn_after(2.secs()).unwrap();
|
||||||
bar::spawn_after(1.seconds(), spawn_handle, false).unwrap(); // Change to true
|
bar::spawn_after(1.secs(), spawn_handle, false).unwrap(); // Change to true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
|
@ -57,7 +56,7 @@ mod app {
|
||||||
if do_reschedule {
|
if do_reschedule {
|
||||||
// Reschedule baz 2 seconds from now, instead of the original 1 second
|
// Reschedule baz 2 seconds from now, instead of the original 1 second
|
||||||
// from now.
|
// from now.
|
||||||
baz_handle.reschedule_after(2.seconds()).unwrap();
|
baz_handle.reschedule_after(2.secs()).unwrap();
|
||||||
// Or baz_handle.reschedule_at(/* time */)
|
// Or baz_handle.reschedule_at(/* time */)
|
||||||
} else {
|
} else {
|
||||||
// Or cancel it
|
// Or cancel it
|
||||||
|
|
|
@ -10,8 +10,7 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
#[rtic::app(device = lm3s6965, dispatchers = [SSI0, QEI0])]
|
||||||
mod app {
|
mod app {
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use rtic::time::duration::*;
|
use systick_monotonic::*; // Implements the `Monotonic` trait
|
||||||
use systick_monotonic::Systick; // Implements the `Monotonic` trait // Time helpers, such as `N.seconds()`
|
|
||||||
|
|
||||||
// A monotonic timer to enable scheduling in RTIC
|
// A monotonic timer to enable scheduling in RTIC
|
||||||
#[monotonic(binds = SysTick, default = true)]
|
#[monotonic(binds = SysTick, default = true)]
|
||||||
|
@ -41,7 +40,7 @@ mod app {
|
||||||
|
|
||||||
// Spawn the task `bar` 1 second after `init` finishes, this is enabled
|
// Spawn the task `bar` 1 second after `init` finishes, this is enabled
|
||||||
// by the `#[monotonic(..)]` above
|
// by the `#[monotonic(..)]` above
|
||||||
bar::spawn_after(1.seconds()).unwrap();
|
bar::spawn_after(1.secs()).unwrap();
|
||||||
|
|
||||||
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
debug::exit(debug::EXIT_SUCCESS); // Exit QEMU simulator
|
||||||
|
|
||||||
|
@ -83,7 +82,7 @@ mod app {
|
||||||
hprintln!("bar").ok();
|
hprintln!("bar").ok();
|
||||||
|
|
||||||
// Run `bar` once per second
|
// Run `bar` once per second
|
||||||
bar::spawn_after(1.seconds()).unwrap();
|
bar::spawn_after(1.secs()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardware task, bound to a hardware interrupt
|
// Hardware task, bound to a hardware interrupt
|
||||||
|
|
|
@ -10,8 +10,7 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||||
mod app {
|
mod app {
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use rtic::time::duration::*;
|
use systick_monotonic::*;
|
||||||
use systick_monotonic::Systick;
|
|
||||||
|
|
||||||
#[monotonic(binds = SysTick, default = true)]
|
#[monotonic(binds = SysTick, default = true)]
|
||||||
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
||||||
|
@ -28,7 +27,7 @@ mod app {
|
||||||
|
|
||||||
let mono = Systick::new(systick, 12_000_000);
|
let mono = Systick::new(systick, 12_000_000);
|
||||||
|
|
||||||
foo::spawn_after(1.seconds()).unwrap();
|
foo::spawn_after(1.secs()).unwrap();
|
||||||
|
|
||||||
(Shared {}, Local {}, init::Monotonics(mono))
|
(Shared {}, Local {}, init::Monotonics(mono))
|
||||||
}
|
}
|
||||||
|
@ -43,6 +42,6 @@ mod app {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Periodic ever 1 seconds
|
// Periodic ever 1 seconds
|
||||||
foo::spawn_after(1.seconds()).unwrap();
|
foo::spawn_after(1.secs()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,7 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||||
mod app {
|
mod app {
|
||||||
use cortex_m_semihosting::{debug, hprintln};
|
use cortex_m_semihosting::{debug, hprintln};
|
||||||
use rtic::time::duration::*;
|
use systick_monotonic::*;
|
||||||
use systick_monotonic::Systick;
|
|
||||||
|
|
||||||
#[monotonic(binds = SysTick, default = true)]
|
#[monotonic(binds = SysTick, default = true)]
|
||||||
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
||||||
|
@ -32,7 +31,7 @@ mod app {
|
||||||
hprintln!("init").ok();
|
hprintln!("init").ok();
|
||||||
|
|
||||||
// Schedule `foo` to run 1 second in the future
|
// Schedule `foo` to run 1 second in the future
|
||||||
foo::spawn_after(1.seconds()).unwrap();
|
foo::spawn_after(1.secs()).unwrap();
|
||||||
|
|
||||||
(
|
(
|
||||||
Shared {},
|
Shared {},
|
||||||
|
@ -46,7 +45,7 @@ mod app {
|
||||||
hprintln!("foo").ok();
|
hprintln!("foo").ok();
|
||||||
|
|
||||||
// Schedule `bar` to run 2 seconds in the future (1 second after foo runs)
|
// Schedule `bar` to run 2 seconds in the future (1 second after foo runs)
|
||||||
bar::spawn_after(1.seconds()).unwrap();
|
bar::spawn_after(1.secs()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
|
@ -54,7 +53,7 @@ mod app {
|
||||||
hprintln!("bar").ok();
|
hprintln!("bar").ok();
|
||||||
|
|
||||||
// Schedule `baz` to run 1 seconds from now, but with a specific time instant.
|
// Schedule `baz` to run 1 seconds from now, but with a specific time instant.
|
||||||
baz::spawn_at(monotonics::now() + 1.seconds()).unwrap();
|
baz::spawn_at(monotonics::now() + 1.secs()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
|
|
|
@ -10,8 +10,7 @@ use panic_semihosting as _;
|
||||||
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
#[rtic::app(device = lm3s6965, dispatchers = [SSI0])]
|
||||||
mod app {
|
mod app {
|
||||||
use cortex_m_semihosting::debug;
|
use cortex_m_semihosting::debug;
|
||||||
use rtic::time::duration::Seconds;
|
use systick_monotonic::*;
|
||||||
use systick_monotonic::Systick;
|
|
||||||
|
|
||||||
#[monotonic(binds = SysTick, default = true)]
|
#[monotonic(binds = SysTick, default = true)]
|
||||||
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
type MyMono = Systick<100>; // 100 Hz / 10 ms granularity
|
||||||
|
@ -40,27 +39,26 @@ mod app {
|
||||||
// Not default
|
// Not default
|
||||||
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
||||||
foo::MyMono::spawn_at(monotonics::MyMono::now());
|
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(1.secs());
|
||||||
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
let _: Result<foo::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||||
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(1.secs());
|
||||||
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
let _: Result<foo::MyMono::SpawnHandle, ()> =
|
||||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
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(1.secs());
|
||||||
let _: Result<(), ()> = handle.unwrap().cancel();
|
let _: Result<(), ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
// Using default
|
// Using default
|
||||||
let _: Result<foo::SpawnHandle, ()> = foo::spawn_at(monotonics::now());
|
let _: Result<foo::SpawnHandle, ()> = foo::spawn_at(monotonics::now());
|
||||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
|
||||||
let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
let _: Result<foo::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||||
|
|
||||||
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(Seconds(1_u32));
|
let handle: Result<foo::SpawnHandle, ()> = foo::spawn_after(1.secs());
|
||||||
let _: Result<foo::SpawnHandle, ()> =
|
let _: Result<foo::SpawnHandle, ()> =
|
||||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
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(1.secs());
|
||||||
let _: Result<(), ()> = handle.unwrap().cancel();
|
let _: Result<(), ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
// Task with single message passing
|
// Task with single message passing
|
||||||
|
@ -68,30 +66,26 @@ mod app {
|
||||||
// Not default
|
// Not default
|
||||||
let _: Result<bar::MyMono::SpawnHandle, u32> =
|
let _: Result<bar::MyMono::SpawnHandle, u32> =
|
||||||
bar::MyMono::spawn_at(monotonics::MyMono::now(), 0);
|
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(1.secs(), 1);
|
||||||
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
let _: Result<bar::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||||
let _: Result<bar::MyMono::SpawnHandle, ()> =
|
|
||||||
handle.unwrap().reschedule_after(Seconds(1_u32));
|
|
||||||
|
|
||||||
let handle: Result<bar::MyMono::SpawnHandle, u32> =
|
let handle: Result<bar::MyMono::SpawnHandle, u32> = bar::MyMono::spawn_after(1.secs(), 1);
|
||||||
bar::MyMono::spawn_after(Seconds(1_u32), 0);
|
|
||||||
let _: Result<bar::MyMono::SpawnHandle, ()> =
|
let _: Result<bar::MyMono::SpawnHandle, ()> =
|
||||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
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(1.secs(), 1);
|
||||||
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(monotonics::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(1.secs(), 1);
|
||||||
let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
let _: Result<bar::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||||
|
|
||||||
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(Seconds(1_u32), 0);
|
let handle: Result<bar::SpawnHandle, u32> = bar::spawn_after(1.secs(), 1);
|
||||||
let _: Result<bar::SpawnHandle, ()> =
|
let _: Result<bar::SpawnHandle, ()> =
|
||||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
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(1.secs(), 1);
|
||||||
let _: Result<u32, ()> = handle.unwrap().cancel();
|
let _: Result<u32, ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
// Task with multiple message passing
|
// Task with multiple message passing
|
||||||
|
@ -100,30 +94,29 @@ mod app {
|
||||||
let _: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
let _: Result<baz::MyMono::SpawnHandle, (u32, u32)> =
|
||||||
baz::MyMono::spawn_at(monotonics::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(1.secs(), 1, 2);
|
||||||
let _: Result<baz::MyMono::SpawnHandle, ()> =
|
let _: Result<baz::MyMono::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||||
handle.unwrap().reschedule_after(Seconds(1_u32));
|
|
||||||
|
|
||||||
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(1.secs(), 1, 2);
|
||||||
let _: Result<baz::MyMono::SpawnHandle, ()> =
|
let _: Result<baz::MyMono::SpawnHandle, ()> =
|
||||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
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(1.secs(), 1, 2);
|
||||||
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
// Using default
|
// Using default
|
||||||
let _: Result<baz::SpawnHandle, (u32, u32)> =
|
let _: Result<baz::SpawnHandle, (u32, u32)> =
|
||||||
baz::spawn_at(monotonics::MyMono::now(), 0, 1);
|
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(1.secs(), 1, 2);
|
||||||
let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_after(Seconds(1_u32));
|
let _: Result<baz::SpawnHandle, ()> = handle.unwrap().reschedule_after(1.secs());
|
||||||
|
|
||||||
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(1.secs(), 1, 2);
|
||||||
let _: Result<baz::SpawnHandle, ()> =
|
let _: Result<baz::SpawnHandle, ()> =
|
||||||
handle.unwrap().reschedule_at(monotonics::MyMono::now());
|
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(1.secs(), 1, 2);
|
||||||
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
let _: Result<(u32, u32), ()> = handle.unwrap().cancel();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -108,10 +108,6 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
let name = &monotonic.ident;
|
let name = &monotonic.ident;
|
||||||
let name_str = &name.to_string();
|
let name_str = &name.to_string();
|
||||||
let ident = util::monotonic_ident(&name_str);
|
let ident = util::monotonic_ident(&name_str);
|
||||||
let panic_str = &format!(
|
|
||||||
"Use of monotonic '{}' before it was passed to the runtime",
|
|
||||||
name_str
|
|
||||||
);
|
|
||||||
let doc = &format!(
|
let doc = &format!(
|
||||||
"This module holds the static implementation for `{}::now()`",
|
"This module holds the static implementation for `{}::now()`",
|
||||||
name_str
|
name_str
|
||||||
|
@ -131,18 +127,13 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 {
|
||||||
pub mod #name {
|
pub mod #name {
|
||||||
|
|
||||||
/// Read the current time from this monotonic
|
/// Read the current time from this monotonic
|
||||||
pub fn now() -> rtic::time::Instant<super::super::#name> {
|
pub fn now() -> <super::super::#name as rtic::Monotonic>::Instant {
|
||||||
rtic::export::interrupt::free(|_| {
|
rtic::export::interrupt::free(|_| {
|
||||||
use rtic::Monotonic as _;
|
use rtic::Monotonic as _;
|
||||||
use rtic::time::Clock as _;
|
|
||||||
if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } {
|
if let Some(m) = unsafe{ &mut *super::super::#ident.get_mut() } {
|
||||||
if let Ok(v) = m.try_now() {
|
m.now()
|
||||||
v
|
|
||||||
} else {
|
|
||||||
unreachable!("Your monotonic is not infallible!")
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
panic!(#panic_str);
|
<super::super::#name as rtic::Monotonic>::zero()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,7 +266,6 @@ pub fn codegen(
|
||||||
let tq = util::tq_ident(&monotonic.ident.to_string());
|
let tq = util::tq_ident(&monotonic.ident.to_string());
|
||||||
let t = util::schedule_t_ident();
|
let t = util::schedule_t_ident();
|
||||||
let m = &monotonic.ident;
|
let m = &monotonic.ident;
|
||||||
let mono_type = &monotonic.ident;
|
|
||||||
let m_ident = util::monotonic_ident(&monotonic_name);
|
let m_ident = util::monotonic_ident(&monotonic_name);
|
||||||
let m_isr = &monotonic.args.binds;
|
let m_isr = &monotonic.args.binds;
|
||||||
let enum_ = util::interrupt_ident();
|
let enum_ = util::interrupt_ident();
|
||||||
|
@ -349,15 +348,17 @@ pub fn codegen(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn reschedule_after<D>(self, duration: D) -> Result<Self, ()>
|
pub fn reschedule_after(
|
||||||
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
self,
|
||||||
D::T: Into<<#mono_type as rtic::time::Clock>::T>,
|
duration: <#m as rtic::Monotonic>::Duration
|
||||||
{
|
) -> Result<Self, ()> {
|
||||||
self.reschedule_at(monotonics::#m::now() + duration)
|
self.reschedule_at(monotonics::#m::now() + duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reschedule_at(self, instant: rtic::time::Instant<#mono_type>) -> Result<Self, ()>
|
pub fn reschedule_at(
|
||||||
{
|
self,
|
||||||
|
instant: <#m as rtic::Monotonic>::Instant
|
||||||
|
) -> Result<Self, ()> {
|
||||||
rtic::export::interrupt::free(|_| unsafe {
|
rtic::export::interrupt::free(|_| unsafe {
|
||||||
let marker = #tq_marker.get().read();
|
let marker = #tq_marker.get().read();
|
||||||
#tq_marker.get_mut().write(marker.wrapping_add(1));
|
#tq_marker.get_mut().write(marker.wrapping_add(1));
|
||||||
|
@ -375,19 +376,12 @@ pub fn codegen(
|
||||||
/// This will use the time `Instant::new(0)` as baseline if called in `#[init]`,
|
/// This will use the time `Instant::new(0)` as baseline if called in `#[init]`,
|
||||||
/// so if you use a non-resetable timer use `spawn_at` when in `#[init]`
|
/// so if you use a non-resetable timer use `spawn_at` when in `#[init]`
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn #internal_spawn_after_ident<D>(
|
pub fn #internal_spawn_after_ident(
|
||||||
duration: D
|
duration: <#m as rtic::Monotonic>::Duration
|
||||||
#(,#args)*
|
#(,#args)*
|
||||||
) -> Result<#name::#m::SpawnHandle, #ty>
|
) -> Result<#name::#m::SpawnHandle, #ty>
|
||||||
where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint,
|
|
||||||
D::T: Into<<#mono_type as rtic::time::Clock>::T>,
|
|
||||||
{
|
{
|
||||||
|
let instant = monotonics::#m::now();
|
||||||
let instant = if rtic::export::interrupt::free(|_| unsafe { (&*#m_ident.get()).is_none() }) {
|
|
||||||
rtic::time::Instant::new(0)
|
|
||||||
} else {
|
|
||||||
monotonics::#m::now()
|
|
||||||
};
|
|
||||||
|
|
||||||
#internal_spawn_at_ident(instant + duration #(,#untupled)*)
|
#internal_spawn_at_ident(instant + duration #(,#untupled)*)
|
||||||
}
|
}
|
||||||
|
@ -396,7 +390,7 @@ pub fn codegen(
|
||||||
/// Spawns the task at a fixed time instant
|
/// Spawns the task at a fixed time instant
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn #internal_spawn_at_ident(
|
pub fn #internal_spawn_at_ident(
|
||||||
instant: rtic::time::Instant<#mono_type>
|
instant: <#m as rtic::Monotonic>::Instant
|
||||||
#(,#args)*
|
#(,#args)*
|
||||||
) -> Result<#name::#m::SpawnHandle, #ty> {
|
) -> Result<#name::#m::SpawnHandle, #ty> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -73,7 +73,7 @@ pub fn codegen(
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
static #instants:
|
static #instants:
|
||||||
rtic::RacyCell<[core::mem::MaybeUninit<rtic::time::Instant<#mono_type>>; #cap_lit]> =
|
rtic::RacyCell<[core::mem::MaybeUninit<<#mono_type as rtic::Monotonic>::Instant>; #cap_lit]> =
|
||||||
rtic::RacyCell::new([#(#elems,)*]);
|
rtic::RacyCell::new([#(#elems,)*]);
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC};
|
use cortex_m::{interrupt::InterruptNumber, peripheral::NVIC};
|
||||||
pub use cortex_m_rtic_macros::app;
|
pub use cortex_m_rtic_macros::app;
|
||||||
pub use rtic_core::{prelude as mutex_prelude, Exclusive, Mutex};
|
pub use rtic_core::{prelude as mutex_prelude, Exclusive, Mutex};
|
||||||
pub use rtic_monotonic::{self, embedded_time as time, Monotonic};
|
pub use rtic_monotonic::{self, Monotonic};
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod export;
|
pub mod export;
|
||||||
|
|
27
src/tq.rs
27
src/tq.rs
|
@ -1,19 +1,7 @@
|
||||||
use crate::{
|
use crate::Monotonic;
|
||||||
time::{Clock, Instant},
|
|
||||||
Monotonic,
|
|
||||||
};
|
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use heapless::sorted_linked_list::{LinkedIndexU16, Min, SortedLinkedList};
|
use heapless::sorted_linked_list::{LinkedIndexU16, Min, SortedLinkedList};
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn unwrapper<T, E>(val: Result<T, E>) -> T {
|
|
||||||
if let Ok(v) = val {
|
|
||||||
v
|
|
||||||
} else {
|
|
||||||
unreachable!("Your monotonic is not infallible")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TimerQueue<Mono, Task, const N: usize>(
|
pub struct TimerQueue<Mono, Task, const N: usize>(
|
||||||
pub SortedLinkedList<NotReady<Mono, Task>, LinkedIndexU16, Min, N>,
|
pub SortedLinkedList<NotReady<Mono, Task>, LinkedIndexU16, Min, N>,
|
||||||
)
|
)
|
||||||
|
@ -87,7 +75,7 @@ where
|
||||||
&mut self,
|
&mut self,
|
||||||
marker: u32,
|
marker: u32,
|
||||||
new_marker: u32,
|
new_marker: u32,
|
||||||
instant: Instant<Mono>,
|
instant: Mono::Instant,
|
||||||
pend_handler: F,
|
pend_handler: F,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
if let Some(mut val) = self.0.find_mut(|nr| nr.marker == marker) {
|
if let Some(mut val) = self.0.find_mut(|nr| nr.marker == marker) {
|
||||||
|
@ -111,23 +99,20 @@ where
|
||||||
mono.clear_compare_flag();
|
mono.clear_compare_flag();
|
||||||
|
|
||||||
if let Some(instant) = self.0.peek().map(|p| p.instant) {
|
if let Some(instant) = self.0.peek().map(|p| p.instant) {
|
||||||
let now = unwrapper(Clock::try_now(mono));
|
if instant <= mono.now() {
|
||||||
// This if statement is like this and not <= due to a bug in embedded-time
|
|
||||||
if instant < now || instant == now {
|
|
||||||
// task became ready
|
// task became ready
|
||||||
let nr = unsafe { self.0.pop_unchecked() };
|
let nr = unsafe { self.0.pop_unchecked() };
|
||||||
|
|
||||||
Some((nr.task, nr.index))
|
Some((nr.task, nr.index))
|
||||||
} else {
|
} else {
|
||||||
// Set compare
|
// Set compare
|
||||||
mono.set_compare(&instant);
|
mono.set_compare(instant);
|
||||||
|
|
||||||
// Double check that the instant we set is really in the future, else
|
// Double check that the instant we set is really in the future, else
|
||||||
// dequeue. If the monotonic is fast enough it can happen that from the
|
// dequeue. If the monotonic is fast enough it can happen that from the
|
||||||
// read of now to the set of the compare, the time can overflow. This is to
|
// read of now to the set of the compare, the time can overflow. This is to
|
||||||
// guard against this.
|
// guard against this.
|
||||||
let now = unwrapper(Clock::try_now(mono));
|
if instant <= mono.now() {
|
||||||
if instant < now || instant == now {
|
|
||||||
let nr = unsafe { self.0.pop_unchecked() };
|
let nr = unsafe { self.0.pop_unchecked() };
|
||||||
|
|
||||||
Some((nr.task, nr.index))
|
Some((nr.task, nr.index))
|
||||||
|
@ -153,7 +138,7 @@ where
|
||||||
Mono: Monotonic,
|
Mono: Monotonic,
|
||||||
{
|
{
|
||||||
pub index: u8,
|
pub index: u8,
|
||||||
pub instant: Instant<Mono>,
|
pub instant: Mono::Instant,
|
||||||
pub task: Task,
|
pub task: Task,
|
||||||
pub marker: u32,
|
pub marker: u32,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue