diff --git a/Cargo.toml b/Cargo.toml index 98bed66006..2b3528ba76 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,38 @@ version = "0.6.0-alpha.0" [lib] name = "rtic" +[[example]] +name = "periodic" +required-features = ["__v7"] + +[[example]] +name = "pool" +required-features = ["__v7"] + +[[example]] +name = "schedule" +required-features = ["__v7"] + +[[example]] +name = "t-cfg" +required-features = ["__v7"] + +[[example]] +name = "t-cfg-resources" +required-features = ["__min_r1_43"] + +[[example]] +name = "t-schedule" +required-features = ["__v7"] + +[[example]] +name = "types" +required-features = ["__v7"] + +[[example]] +name = "double_schedule" +required-features = ["__v7"] + [dependencies] cortex-m = "0.7.0" cortex-m-rtic-macros = { path = "macros", version = "0.6.0-alpha.0" } @@ -27,6 +59,11 @@ rtic-monotonic = { git = "https://github.com/rtic-rs/rtic-monotonic", branch = " heapless = "0.5.0" bare-metal = "1.0.0" +[dependencies.dwt-systick-monotonic] +git = "https://github.com/rtic-rs/dwt-systick-monotonic" +branch = "master" +optional = true + [build-dependencies] version_check = "0.9" @@ -42,6 +79,11 @@ version = "0.5.2" [target.x86_64-unknown-linux-gnu.dev-dependencies] trybuild = "1" +[features] +# used for testing this crate; do not use in applications +__v7 = ["dwt-systick-monotonic"] +__min_r1_43 = [] + [profile.release] codegen-units = 1 lto = true diff --git a/examples/double_schedule.rs b/examples/double_schedule.rs index 77a8e38e91..403f35830f 100644 --- a/examples/double_schedule.rs +++ b/examples/double_schedule.rs @@ -9,20 +9,35 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { + use dwt_systick_monotonic::{ + consts::{U0, U8}, + DwtSystick, + }; + use rtic::time::duration::Seconds; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = DwtSystick; // 8 MHz + #[init] - fn init(_: init::Context) -> (init::LateResources, init::Monotonics) { + fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) { task1::spawn().ok(); - (init::LateResources {}, init::Monotonics()) + let mut dcb = cx.core.DCB; + let dwt = cx.core.DWT; + let systick = cx.core.SYST; + + let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000); + + (init::LateResources {}, init::Monotonics(mono)) } #[task] fn task1(_cx: task1::Context) { - task2::schedule(_cx.scheduled + 100.cycles()).ok(); + task2::spawn_after(Seconds(1_u32)).ok(); } #[task] fn task2(_cx: task2::Context) { - task1::schedule(_cx.scheduled + 100.cycles()).ok(); + task1::spawn_after(Seconds(1_u32)).ok(); } } diff --git a/examples/periodic.rs b/examples/periodic.rs index 29fa6bd999..82c21280e1 100644 --- a/examples/periodic.rs +++ b/examples/periodic.rs @@ -10,25 +10,31 @@ use panic_semihosting as _; // NOTE: does NOT work on QEMU! #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { - use cortex_m_semihosting::hprintln; - use rtic::cyccnt::{Instant, U32Ext}; + use dwt_systick_monotonic::{ + consts::{U0, U8}, + DwtSystick, + }; + use rtic::time::duration::Seconds; - const PERIOD: u32 = 8_000_000; + #[monotonic(binds = SysTick, default = true)] + type MyMono = DwtSystick; // 8 MHz #[init] fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) { - // omitted: initialization of `CYCCNT` + let mut dcb = cx.core.DCB; + let dwt = cx.core.DWT; + let systick = cx.core.SYST; - foo::schedule(cx.start + PERIOD.cycles()).unwrap(); + let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000); - (init::LateResources {}, init::Monotonics()) + foo::spawn_after(Seconds(1_u32)).unwrap(); + + (init::LateResources {}, init::Monotonics(mono)) } #[task] - fn foo(cx: foo::Context) { - let now = Instant::now(); - hprintln!("foo(scheduled = {:?}, now = {:?})", cx.scheduled, now).unwrap(); - - foo::schedule(cx.scheduled + PERIOD.cycles()).unwrap(); + fn foo(_cx: foo::Context) { + // Periodic + foo::spawn_after(Seconds(1_u32)).unwrap(); } } diff --git a/examples/schedule.rs b/examples/schedule.rs index 6f6f8cb60b..cdbdc0dedd 100644 --- a/examples/schedule.rs +++ b/examples/schedule.rs @@ -10,40 +10,42 @@ use panic_halt as _; // NOTE: does NOT work on QEMU! #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { - use cortex_m::peripheral::DWT; use cortex_m_semihosting::hprintln; - use rtic::cyccnt::{Instant, U32Ext as _}; + use dwt_systick_monotonic::{ + consts::{U0, U8}, + DwtSystick, + }; + use rtic::time::duration::Seconds; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = DwtSystick; // 8 MHz #[init()] - fn init(mut cx: init::Context) -> (init::LateResources, init::Monotonics) { - // Initialize (enable) the monotonic timer (CYCCNT) - cx.core.DCB.enable_trace(); - // required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7) - DWT::unlock(); - cx.core.DWT.enable_cycle_counter(); + fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) { + let mut dcb = cx.core.DCB; + let dwt = cx.core.DWT; + let systick = cx.core.SYST; - // semantically, the monotonic timer is frozen at time "zero" during `init` - // NOTE do *not* call `Instant::now` in this context; it will return a nonsense value - let now = cx.start; // the start time of the system + let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000); - hprintln!("init @ {:?}", now).unwrap(); + hprintln!("init").unwrap(); - // Schedule `foo` to run 8e6 cycles (clock cycles) in the future - foo::schedule(now + 8_000_000.cycles()).unwrap(); + // Schedule `foo` to run 1 second in the future + foo::spawn_after(Seconds(1_u32)).unwrap(); - // Schedule `bar` to run 4e6 cycles in the future - bar::schedule(now + 4_000_000.cycles()).unwrap(); + // Schedule `bar` to run 2 seconds in the future + bar::spawn_after(Seconds(2_u32)).unwrap(); - (init::LateResources {}, init::Monotonics()) + (init::LateResources {}, init::Monotonics(mono)) } #[task] fn foo(_: foo::Context) { - hprintln!("foo @ {:?}", Instant::now()).unwrap(); + hprintln!("foo").unwrap(); } #[task] fn bar(_: bar::Context) { - hprintln!("bar @ {:?}", Instant::now()).unwrap(); + hprintln!("bar").unwrap(); } } diff --git a/examples/t-schedule.rs b/examples/t-schedule.rs index 1771d4195f..259b22655f 100644 --- a/examples/t-schedule.rs +++ b/examples/t-schedule.rs @@ -9,48 +9,43 @@ use panic_halt as _; #[rtic::app(device = lm3s6965, dispatchers = [SSI0])] mod app { - use rtic::cyccnt::{Instant, U32Ext as _}; + use dwt_systick_monotonic::{ + consts::{U0, U8}, + DwtSystick, + }; + use rtic::time::duration::Seconds; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = DwtSystick; // 8 MHz #[init] - fn init(c: init::Context) -> (init::LateResources, init::Monotonics) { - let _: Result<(), ()> = foo::schedule(c.start + 10.cycles()); - let _: Result<(), u32> = bar::schedule(c.start + 20.cycles(), 0); - let _: Result<(), (u32, u32)> = baz::schedule(c.start + 30.cycles(), 0, 1); + fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) { + let mut dcb = cx.core.DCB; + let dwt = cx.core.DWT; + let systick = cx.core.SYST; - (init::LateResources {}, init::Monotonics()) + let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000); + + let _: Result<(), ()> = foo::spawn_after(Seconds(1_u32)); + let _: Result<(), u32> = bar::spawn_after(Seconds(2_u32), 0); + let _: Result<(), (u32, u32)> = baz::spawn_after(Seconds(3_u32), 0, 1); + + (init::LateResources {}, init::Monotonics(mono)) } #[idle] fn idle(_: idle::Context) -> ! { - let _: Result<(), ()> = foo::schedule(Instant::now() + 40.cycles()); - let _: Result<(), u32> = bar::schedule(Instant::now() + 50.cycles(), 0); - let _: Result<(), (u32, u32)> = baz::schedule(Instant::now() + 60.cycles(), 0, 1); + let _: Result<(), ()> = foo::spawn_at(MyMono::now() + Seconds(3_u32)); + let _: Result<(), u32> = bar::spawn_at(MyMono::now() + Seconds(4_u32), 0); + let _: Result<(), (u32, u32)> = baz::spawn_at(MyMono::now() + Seconds(5_u32), 0, 1); loop { cortex_m::asm::nop(); } } - #[task(binds = SVCall)] - fn svcall(c: svcall::Context) { - let _: Result<(), ()> = foo::schedule(c.start + 70.cycles()); - let _: Result<(), u32> = bar::schedule(c.start + 80.cycles(), 0); - let _: Result<(), (u32, u32)> = baz::schedule(c.start + 90.cycles(), 0, 1); - } - - #[task(binds = UART0)] - fn uart0(c: uart0::Context) { - let _: Result<(), ()> = foo::schedule(c.start + 100.cycles()); - let _: Result<(), u32> = bar::schedule(c.start + 110.cycles(), 0); - let _: Result<(), (u32, u32)> = baz::schedule(c.start + 120.cycles(), 0, 1); - } - #[task] - fn foo(c: foo::Context) { - let _: Result<(), ()> = foo::schedule(c.scheduled + 130.cycles()); - let _: Result<(), u32> = bar::schedule(c.scheduled + 140.cycles(), 0); - let _: Result<(), (u32, u32)> = baz::schedule(c.scheduled + 150.cycles(), 0, 1); - } + fn foo(_: foo::Context) {} #[task] fn bar(_: bar::Context, _x: u32) {} diff --git a/examples/types.rs b/examples/types.rs index 8411eecd9c..ff7deb844d 100644 --- a/examples/types.rs +++ b/examples/types.rs @@ -10,6 +10,13 @@ use panic_semihosting as _; #[rtic::app(device = lm3s6965, peripherals = true, dispatchers = [SSI0])] mod app { use cortex_m_semihosting::debug; + use dwt_systick_monotonic::{ + consts::{U0, U8}, + DwtSystick, + }; + + #[monotonic(binds = SysTick, default = true)] + type MyMono = DwtSystick; // 8 MHz #[resources] struct Resources { @@ -19,13 +26,18 @@ mod app { #[init] fn init(cx: init::Context) -> (init::LateResources, init::Monotonics) { - let _: cyccnt::Instant = cx.start; - let _: rtic::Peripherals = cx.core; + let _: cortex_m::Peripherals = cx.core; let _: lm3s6965::Peripherals = cx.device; debug::exit(debug::EXIT_SUCCESS); - (init::LateResources {}, init::Monotonics()) + let mut dcb = cx.core.DCB; + let dwt = cx.core.DWT; + let systick = cx.core.SYST; + + let mono = DwtSystick::new(&mut dcb, dwt, systick, 8_000_000); + + (init::LateResources {}, init::Monotonics(mono)) } #[idle] @@ -37,13 +49,11 @@ mod app { #[task(binds = UART0, resources = [shared])] fn uart0(cx: uart0::Context) { - let _: cyccnt::Instant = cx.start; let _: resources::shared = cx.resources.shared; } #[task(priority = 2, resources = [shared])] fn foo(cx: foo::Context) { - let _: cyccnt::Instant = cx.scheduled; let _: resources::shared = cx.resources.shared; let _: foo::Resources = cx.resources; } diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index b1e87ca837..32e7da0543 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -116,7 +116,10 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let ty = &monotonic.ty; let mangled_name = util::mangle_monotonic_type(&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 panic_str = &format!( + "Use of monotonic '{}' before it was passed to the runtime", + name_str + ); quote! { pub use rtic::Monotonic as _; diff --git a/macros/src/codegen/module.rs b/macros/src/codegen/module.rs index b0ac65f3ed..e480b86559 100644 --- a/macros/src/codegen/module.rs +++ b/macros/src/codegen/module.rs @@ -263,7 +263,7 @@ pub fn codegen( pub mod #m { #(#cfgs)* pub fn spawn_after( - duration: D, + duration: D #(,#args)* ) -> Result<(), #ty> where D: rtic::time::duration::Duration + rtic::time::fixed_point::FixedPoint, @@ -276,7 +276,7 @@ pub fn codegen( #app_path::#m::now() }; - spawn_at(instant + duration, #(,#untupled)*) + spawn_at(instant + duration #(,#untupled)*) } #(#cfgs)*