diff --git a/.vscode/launch.json b/.vscode/launch.json index f6d7a6f0ec37caf6f926ac5b5f1fbb77402482de..a62f4159db5499f3a14fb05e10ad9adbc1bf8208 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -160,6 +160,36 @@ ], "cwd": "${workspaceRoot}" }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "app6 (debug)", + "preLaunchTask": "cargo build --example app6", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/app6", + "configFiles": [ + "./openocd_jlink.cfg", + ], + "postLaunchCommands": [ + "monitor arm semihosting enable" + ], + "cwd": "${workspaceRoot}" + }, + { + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "name": "app7 (debug)", + "preLaunchTask": "cargo build --example app7", + "executable": "./target/thumbv7em-none-eabihf/debug/examples/app7", + "configFiles": [ + "./openocd_jlink.cfg", + ], + "postLaunchCommands": [ + "monitor arm semihosting enable" + ], + "cwd": "${workspaceRoot}" + }, { "type": "cortex-debug", "request": "launch", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index fd89034a8a515faca68392e77a4e8fd9df45e841..aafbd056b2c024aeec2bf0d6b196e5d0f87f6fd4 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -123,6 +123,54 @@ "isDefault": true } }, + { + "type": "shell", + "label": "cargo build --example app6", + "command": "cargo build --example app6 --features timer-queue", + "problemMatcher": [ + "$rustc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "cargo build --example app7", + "command": "cargo build --example app7 --features timer-queue", + "problemMatcher": [ + "$rustc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "cargo build --example app8", + "command": "cargo build --example app8 --features timer-queue", + "problemMatcher": [ + "$rustc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "cargo build --example app9", + "command": "cargo build --example app9 --features timer-queue", + "problemMatcher": [ + "$rustc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, { "type": "shell", "label": "cargo build --example panic", diff --git a/Cargo.toml b/Cargo.toml index 77c34e60231e497ea563c6389f5147e196655253..2eaeae29e6b729e6cf07dd46dd2e8bc889c262ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,10 +5,6 @@ readme = "README.md" name = "app" version = "0.1.0" -# [patch.crates-io] -# # stm32f4xx-hal = { path = "../stm32f4xx-hal" } -# stm32fxx-hal = {git = "https://github.com/stm32-rs/stm32f4xx-hal.git" } - [dependencies] cortex-m-rt = "0.6.8" cortex-m-semihosting = "0.3.2" @@ -27,11 +23,8 @@ embedded-hal = "0.2.2" [dependencies.nrf52832-hal] version = "0.7.0" - - [dependencies.cortex-m-rtfm] -version = "0.4.1" -# optional = true +version = "0.4.2" [dependencies.cortex-m] version = "0.6.0" @@ -53,17 +46,17 @@ version = "0.6.0" # features = ["stm32f413", "rt"] # optional = true -# [features] +[features] # pac = ["stm32f4"] # hal = ["stm32f4xx-hal"] # rtfm = ["cortex-m-rtfm"] -# rtfm-tq = ["cortex-m-rtfm/timer-queue"] +timer-queue = ["cortex-m-rtfm/timer-queue"] -# this lets you use `cargo fix`! -[[bin]] -name = "app" -test = false -bench = false +# # this lets you use `cargo fix`! +# [[bin]] +# name = "app" +# test = false +# bench = false [profile.release] incremental = false # disable incremental build to allow lto on nightly diff --git a/examples/app2.rs b/examples/app2.rs index 44f18c6a3159ab535b0ea5d7729d3b7f71bfb64f..150fafdcf6ff5871b6fbdb826c3c87474d5be87e 100644 --- a/examples/app2.rs +++ b/examples/app2.rs @@ -39,8 +39,7 @@ const APP: () = { hprintln!("SWI0_EGU0 end").unwrap(); } - #[interrupt(priority = 2, - resources = [SHARED])] + #[interrupt(priority = 2, resources = [SHARED])] fn SWI1_EGU1() { hprintln!("SWI1_EGU1").unwrap(); *resources.SHARED += 1; diff --git a/examples/app4.rs b/examples/app4.rs index 398d1627c5b7764e4c15fc72bc8f05e56a6f7031..32c062aea39e432065e61d83e05f258153bbd425 100644 --- a/examples/app4.rs +++ b/examples/app4.rs @@ -37,8 +37,6 @@ const APP: () = { loop { if let Some(data) = resources.C.dequeue() { hprintln!("received message: {}", data).unwrap(); - - } else { rtfm::pend(interrupt::SWI0_EGU0); } @@ -47,7 +45,7 @@ const APP: () = { #[interrupt(resources = [P])] fn SWI0_EGU0() { - static mut NUMBER : u32 = 0; + static mut NUMBER: u32 = 0; hprintln!("SWI0_EGU0: {}", NUMBER).unwrap(); resources.P.enqueue(*NUMBER).unwrap(); *NUMBER += 1; diff --git a/examples/app5.rs b/examples/app5.rs index 0a5ba5a177ff4d427c016b600c43c30fed1537af..3b2b10e041d333d20c21d833a5f5ef70785c1c03 100644 --- a/examples/app5.rs +++ b/examples/app5.rs @@ -19,18 +19,17 @@ use hal::prelude::GpioExt; const APP: () = { // Late resources static mut LED: P0_14<gpio::Output<PushPull>> = (); - + #[init] fn init() -> init::LateResources { - hprintln!("init").unwrap(); + hprintln!("init").unwrap(); let port0 = device.P0.split(); let led = port0.p0_14.into_push_pull_output(Level::High); - init::LateResources { LED : led } + init::LateResources { LED: led } } #[idle(resources = [LED])] fn idle() -> ! { - let led = resources.LED; loop { hprintln!("low").unwrap(); diff --git a/examples/app6.rs b/examples/app6.rs index 8a4ab77f9da54b8bc01eb220f50959ef58133289..69263c93e481266c927b87c6a4a9d5a6a411c20f 100644 --- a/examples/app6.rs +++ b/examples/app6.rs @@ -13,37 +13,33 @@ use hal::gpio::Level; use hal::gpio::*; use hal::prelude::GpioExt; -const PERIOD : u32 = 64_000_000; +const PERIOD: u32 = 64_000_000; #[app(device = crate::hal::target)] const APP: () = { // Late resources static mut LED: P0_14<gpio::Output<PushPull>> = (); - + #[init(spawn = [low])] fn init() -> init::LateResources { - hprintln!("init").unwrap(); + hprintln!("init").unwrap(); let port0 = device.P0.split(); let led = port0.p0_14.into_push_pull_output(Level::High); spawn.low().unwrap(); - init::LateResources { LED : led } + init::LateResources { LED: led } } #[task(schedule = [high], resources = [LED])] fn low() { - resources.LED.set_low(); + resources.LED.set_low(); - schedule.high( - scheduled + PERIOD.cycles() - ).unwrap(); + schedule.high(scheduled + PERIOD.cycles()).unwrap(); } #[task(schedule = [low], resources = [LED])] fn high() { - resources.LED.set_high(); - schedule.low( - scheduled + PERIOD.cycles() - ).unwrap(); + resources.LED.set_high(); + schedule.low(scheduled + PERIOD.cycles()).unwrap(); } extern "C" { diff --git a/examples/app7.rs b/examples/app7.rs index 691656f27c8d88be2a770d7879f1716b7f10c76b..061258b3afcddee0a1992979bf2a0bf9cf25f2eb 100644 --- a/examples/app7.rs +++ b/examples/app7.rs @@ -13,37 +13,33 @@ use hal::gpio::Level; use hal::gpio::*; use hal::prelude::GpioExt; -const PERIOD : u32 = 64_000_000; +const PERIOD: u32 = 64_000_000; #[app(device = crate::hal::target)] const APP: () = { // Late resources static mut LED: P0_14<gpio::Output<PushPull>> = (); - + #[init(spawn = [low])] fn init() -> init::LateResources { - hprintln!("init").unwrap(); + hprintln!("init").unwrap(); let port0 = device.P0.split(); let led = port0.p0_14.into_push_pull_output(Level::High); spawn.low().unwrap(); - init::LateResources { LED : led } + init::LateResources { LED: led } } #[task(schedule = [high], resources = [LED])] fn low() { - toggler(resources.LED, false); + toggler(resources.LED, false); - schedule.high( - scheduled + PERIOD.cycles() - ).unwrap(); + schedule.high(scheduled + PERIOD.cycles()).unwrap(); } #[task(schedule = [low], resources = [LED])] fn high() { - toggler(resources.LED, true); - schedule.low( - scheduled + PERIOD.cycles() - ).unwrap(); + toggler(resources.LED, true); + schedule.low(scheduled + PERIOD.cycles()).unwrap(); } extern "C" { @@ -52,7 +48,7 @@ const APP: () = { }; // Arument is Exclusive access to a specific pin -fn toggler(mut led : Exclusive<P0_14<Output<PushPull>>>, state : bool ) { +fn toggler(mut led: Exclusive<P0_14<Output<PushPull>>>, state: bool) { if state { led.set_high(); } else { diff --git a/examples/app8.rs b/examples/app8.rs index 60ccc1639cccecf1d69584aa80d52316c68829c9..4edfcd51bafcf6c19e24728906c87b7d50693dfa 100644 --- a/examples/app8.rs +++ b/examples/app8.rs @@ -4,7 +4,7 @@ use cortex_m_semihosting::hprintln; use nrf52832_hal as hal; #[allow(unused_imports)] use panic_semihosting; -use rtfm::{app}; +use rtfm::app; use embedded_hal::digital::OutputPin; use hal::gpio; @@ -13,38 +13,34 @@ use hal::gpio::Level; use hal::gpio::*; use hal::prelude::GpioExt; -const PERIOD : u32 = 64_000_000; +const PERIOD: u32 = 64_000_000; #[app(device = crate::hal::target)] const APP: () = { // Late resources // static mut LED: OutputPin = (); <= size not known static mut LED: P0_14<gpio::Output<PushPull>> = (); - + #[init(spawn = [low])] fn init() -> init::LateResources { - hprintln!("init").unwrap(); + hprintln!("init").unwrap(); let port0 = device.P0.split(); let led = port0.p0_14.into_push_pull_output(Level::High); spawn.low().unwrap(); - init::LateResources { LED : led } + init::LateResources { LED: led } } #[task(schedule = [high], resources = [LED])] fn low() { - toggler(&mut *resources.LED, false); + toggler(&mut *resources.LED, false); - schedule.high( - scheduled + PERIOD.cycles() - ).unwrap(); + schedule.high(scheduled + PERIOD.cycles()).unwrap(); } #[task(schedule = [low], resources = [LED])] fn high() { - toggler(&mut *resources.LED, true); - schedule.low( - scheduled + PERIOD.cycles() - ).unwrap(); + toggler(&mut *resources.LED, true); + schedule.low(scheduled + PERIOD.cycles()).unwrap(); } extern "C" { @@ -52,11 +48,14 @@ const APP: () = { } }; -// Arument is an Output pin -fn toggler(led : &mut OutputPin, state : bool ) { +// Argument is a borrowed trait object +fn toggler(led: &mut OutputPin, state: bool) { if state { led.set_high(); } else { led.set_low(); } -} \ No newline at end of file +} + +// The full type is ... +// fn toggler(led : &mut dyn OutputPin, state : bool ) diff --git a/examples/app9.rs b/examples/app9.rs index 51bfa2f5e5374f3cbda090379f376217db56c9ad..86822a614b87da8ef59349c7319a123e7f8d1628 100644 --- a/examples/app9.rs +++ b/examples/app9.rs @@ -4,7 +4,7 @@ use cortex_m_semihosting::hprintln; use nrf52832_hal as hal; #[allow(unused_imports)] use panic_semihosting; -use rtfm::{app}; +use rtfm::app; use embedded_hal::digital::OutputPin; use hal::gpio; @@ -13,38 +13,42 @@ use hal::gpio::Level; use hal::gpio::*; use hal::prelude::GpioExt; -const PERIOD : u32 = 64_000_000; +const PERIOD: u32 = 64_000_000; #[app(device = crate::hal::target)] const APP: () = { // Late resources // static mut LED: OutputPin = (); <= size not known - static mut LED: P0_14<gpio::Output<PushPull>> = (); - + // So unfortunately we cannot use that + // + // static mut LED: impl OutputPin = (); <= impl not allowed here + // That may be possible in the future, hope so... + // + // In the meantime: + // We can use the type alias (defined in a library) + // to make it easier on the eye. + static mut LED: LED1 = (); + #[init(spawn = [low])] fn init() -> init::LateResources { - hprintln!("init").unwrap(); + hprintln!("init").unwrap(); let port0 = device.P0.split(); let led = port0.p0_14.into_push_pull_output(Level::High); spawn.low().unwrap(); - init::LateResources { LED : led } + init::LateResources { LED: led } } #[task(schedule = [high], resources = [LED])] fn low() { - toggler(&mut *resources.LED, false); + toggler(&mut *resources.LED, false); - schedule.high( - scheduled + PERIOD.cycles() - ).unwrap(); + schedule.high(scheduled + PERIOD.cycles()).unwrap(); } #[task(schedule = [low], resources = [LED])] fn high() { - toggler(&mut *resources.LED, true); - schedule.low( - scheduled + PERIOD.cycles() - ).unwrap(); + toggler(&mut *resources.LED, true); + schedule.low(scheduled + PERIOD.cycles()).unwrap(); } extern "C" { @@ -52,11 +56,42 @@ const APP: () = { } }; -// Arument is an Output pin -fn toggler(led : &mut impl OutputPin, state : bool ) { +// toggler is generic over OutputPin implementers +fn toggler(led: &mut impl OutputPin, state: bool) { if state { led.set_high(); } else { led.set_low(); } -} \ No newline at end of file +} + +// the full type is... +// fn toggler<P>(led: &mut P, state: bool) where P: OutputPin +// +// Why is this important you may ask? +// Well, the Rust compiler/LLVM is very good at momonorphing generics +// while trait objects may be harder to optimize. +// In certain cases, we need dynamic dispatch but in this case not. +// So here (and similar cases) generics are preferrable. +// +// Thanks to Jorge Aparicio for pointing me in the right direction:) +// +// ----------------------------------------------------------------- +// +// Define the type alias in the library +type LED1 = P0_14<gpio::Output<PushPull>>; +// Notice, +// This is a poor mans solution, we cannot make resource +// definitions type generic with concrete type inferred. +// +// This is not specific to RTFM but a rather a +// shortcoming of the Rust type system, that requires +// explicit types for statics. A possible workaround would +// be to have a run once (at Init time) allocator. +// Drawback is that LLVM would not be able to optimize out +// the indirections, thus we stick with static allocation. +// +// Side note: The Timber language (a fore-runner to RTFM) +// has a static heap collected after init (as above), +// but Timber cannot compete with Rust-RTFM from a performance +// perspektive.