diff --git a/.vscode/launch.json b/.vscode/launch.json
index ce1e88afb03dd476aff5212c1c052f7826a6b7f3..c361322ac1d36a74642c3dcc579a82217cc642be 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -36,7 +36,7 @@
             "request": "launch",
             "servertype": "openocd",
             "name": "itm internal (debug)",
-            "preLaunchTask": "cargo build --examples",
+            "preLaunchTask": "cargo build --example",
             "executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
             "configFiles": [
                 //"interface/stlink.cfg",
@@ -72,7 +72,57 @@
             "request": "launch",
             "servertype": "openocd",
             "name": "itm fifo (debug)",
-            "preLaunchTask": "cargo build --examples",
+            "preLaunchTask": "cargo build --example",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
+            "configFiles": [
+                "interface/stlink.cfg",
+                // "interface/stlink-v2-1.cfg", // deprecated setup script
+                "target/stm32f4x.cfg"
+            ],
+            "postLaunchCommands": [
+                "monitor arm semihosting enable",
+                "monitor tpiu config internal /tmp/itm.fifo uart off 16000000",
+                "monitor itm port 0 on"
+            ],
+            "runToMain": true,
+            "cwd": "${workspaceRoot}"
+        },
+        // Launch configuration for `examples`
+        // - debug
+        // - semihosting
+        // - ITM/SWO tracing to file/fifo `/tmp/itm.fifo`
+        // - run to main   
+        {
+            "type": "cortex-debug",
+            "request": "launch",
+            "servertype": "openocd",
+            "name": "itm fifo (debug) stm32f4",
+            "preLaunchTask": "cargo build --example --features stm32f4",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
+            "configFiles": [
+                "interface/stlink.cfg",
+                // "interface/stlink-v2-1.cfg", // deprecated setup script
+                "target/stm32f4x.cfg"
+            ],
+            "postLaunchCommands": [
+                "monitor arm semihosting enable",
+                "monitor tpiu config internal /tmp/itm.fifo uart off 16000000",
+                "monitor itm port 0 on"
+            ],
+            "runToMain": true,
+            "cwd": "${workspaceRoot}"
+        },
+        // Launch configuration for `examples`
+        // - debug
+        // - semihosting
+        // - ITM/SWO tracing to file/fifo `/tmp/itm.fifo`
+        // - run to main   
+        {
+            "type": "cortex-debug",
+            "request": "launch",
+            "servertype": "openocd",
+            "name": "itm fifo (debug) rtfm",
+            "preLaunchTask": "cargo build --example --features rtfm",
             "executable": "./target/thumbv7em-none-eabihf/debug/examples/${fileBasenameNoExtension}",
             "configFiles": [
                 //"interface/stlink.cfg",
@@ -97,7 +147,7 @@
             "request": "launch",
             "servertype": "openocd",
             "name": "itm fifo (release)",
-            "preLaunchTask": "cargo build --examples --release",
+            "preLaunchTask": "cargo build --example --release",
             "executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
             "configFiles": [
                 //"interface/stlink.cfg",
@@ -121,8 +171,8 @@
             "type": "cortex-debug",
             "request": "launch",
             "servertype": "openocd",
-            "name": "itm fifo 64MHz (release)",
-            "preLaunchTask": "cargo build --examples --release",
+            "name": "itm fifo 64MHz (release) stm32f4",
+            "preLaunchTask": "cargo build --example --release --features stm32f4",
             "executable": "./target/thumbv7em-none-eabihf/release/examples/${fileBasenameNoExtension}",
             "configFiles": [
                 //"interface/stlink.cfg",
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 42f4b03ab8cafe8c01c41cd9e4c930c6196c94da..c5dc1cfeb28edfcc0b42b4a4b44f2d993738d597 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,4 +1,7 @@
 {
+    // See https://go.microsoft.com/fwlink/?LinkId=733558
+    // for the documentation about the tasks.json format
+    "version": "2.0.0",
     "tasks": [
         {
             "type": "shell",
@@ -26,8 +29,8 @@
         },
         {
             "type": "shell",
-            "label": "cargo build --examples",
-            "command": "cargo build --examples",
+            "label": "cargo build --example",
+            "command": "cargo build --example ${fileBasenameNoExtension}",
             "group": {
                 "kind": "build",
                 "isDefault": true
@@ -38,8 +41,32 @@
         },
         {
             "type": "shell",
-            "label": "cargo build --examples --release",
-            "command": "cargo build --examples --release",
+            "label": "cargo build --example --features stm32f4",
+            "command": "cargo build --example ${fileBasenameNoExtension} --features stm32f4",
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            },
+            "problemMatcher": [
+                "$rustc"
+            ]
+        },
+        {
+            "type": "shell",
+            "label": "cargo build --example --features rtfm",
+            "command": "cargo build --example ${fileBasenameNoExtension} --features rtfm",
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            },
+            "problemMatcher": [
+                "$rustc"
+            ]
+        },
+        {
+            "type": "shell",
+            "label": "cargo build --example --release --features stm32f4",
+            "command": "cargo build --example ${fileBasenameNoExtension} --release --features stm32f4",
             "group": {
                 "kind": "build",
                 "isDefault": true
diff --git a/Cargo.lock b/Cargo.lock
index 99b09adfe0e5a85a3694bb49059f47ebedf89556..65280df958cd7842d88cfaa8b11e88aee5e3cde2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,6 +18,7 @@ dependencies = [
  "cortex-m-rt",
  "cortex-m-rtfm",
  "cortex-m-semihosting",
+ "heapless",
  "nb",
  "panic-halt",
  "panic-itm",
diff --git a/Cargo.toml b/Cargo.toml
index 3a3532ef17d3fc7c78563661fc58d8b80f2c5aeb..c4aa6bc397141c6009cb9a49f74cd4ac001ea1f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,18 +5,19 @@ authors = ["Per Lindgren <per.lindgren@ltu.se>"]
 description = "Example project (app)"
 keywords = ["arm", "cortex-m", "rtfm", "e7020e"]
 license = "MIT OR Apache-2.0"
-repository = "https://github.com/korken89/trustflight_firmware"
+repository = "https://gitlab.henriktjader.com/pln/e7020e_2020"
 version = "0.1.0"
 edition = "2018"
 
 [dependencies]
 panic-halt              = "0.2"
-panic-semihosting       = "0.5"
+panic-semihosting       = "0.5" # comment out for `cargo doc`
+panic-itm               = "0.4.1" # comment out for `cargo doc`
 cortex-m-semihosting    = "0.3.5"
 aligned                 = "0.3.2"
 ufmt                    = "0.1.0"
-panic-itm               = "0.4.1"
 nb                      = "0.1.2"
+heapless = "0.5.3"
 
 [dependencies.cortex-m]
 version         = "0.6.2"
@@ -53,14 +54,33 @@ bench           = false
 name                = "device"
 required-features   = ["stm32f4"]
 
+[[example]]
+name                = "bare6"
+required-features   = ["stm32f4"]
+
 [[example]]
 name                = "serial"
 required-features   = ["stm32f4xx-hal"]
 
 [[example]]
-name                = "rtfm_itm"
+name                = "bare7"
+required-features   = ["stm32f4xx-hal"]
+
+[[example]]
+name                = "bare8"
+required-features   = ["rtfm"]
+
+[[example]]
+name                = "bare9"
 required-features   = ["rtfm"]
 
+[[example]]
+name                = "bare10"
+required-features   = ["rtfm"]
+
+[[example]]
+name                = "rtfm_itm"
+required-features   = ["rtfm"]
 [[example]]
 name                = "rtfm_itm_spawn"
 required-features   = ["rtfm"]
@@ -85,9 +105,14 @@ required-features   = ["rtfm"]
 name                = "rtfm_blinky_msg3"
 required-features   = ["rtfm"]
 
+[[example]]
+name                = "rtfm_blinky_sw_reset"
+required-features   = ["rtfm"]
+
+# for more info see, https://doc.rust-lang.org/rustc/codegen-options/index.html
 [profile.dev]
-opt-level       = 1
-codegen-units   = 16
+# opt-level       = 1 # better optimization (may optimize out symbols)
+# codegen-units   = 16
 debug           = true
 lto             = false
 
diff --git a/examples/bare0.rs b/examples/bare0.rs
index f54e9509402fbee65ecdd8df8a14ced982d58f2e..f435828bcd5557e847ba8fa44cc1a38f99f41718 100644
--- a/examples/bare0.rs
+++ b/examples/bare0.rs
@@ -15,12 +15,8 @@
 // no standard main, we declare main using [entry]
 #![no_main]
 
-// Minimal runtime / startup for Cortex-M microcontrollers
-//extern crate cortex_m_rt as rt;
 // Panic handler, for textual output using semihosting
-extern crate panic_semihosting;
-// Panic handler, infinite loop on panic
-// extern crate panic_halt;
+use panic_semihosting as _;
 
 // import entry point
 use cortex_m_rt::entry;
@@ -65,10 +61,10 @@ fn main() -> ! {
 
 // Here we assume you are using `vscode` with `cortex-debug`.
 //
-// 0. Compile/build the example in debug (dev) mode.
+// 0. Compile/build and run the example in debug (dev) mode.
 //
-//    > cargo build --example bare0
-//    (or use the vscode build task)
+//    > cargo run --example bare0
+//    (or use vscode)
 //
 // 1. Run the program in the debugger, let the program run for a while and
 //    then press pause.
diff --git a/examples/bare1.rs b/examples/bare1.rs
index ce46e5ca1167f739d5ab4589ef0b9b241848fcb9..7f8b6429863535501515033e92afb2456b222bea 100644
--- a/examples/bare1.rs
+++ b/examples/bare1.rs
@@ -3,14 +3,14 @@
 //! Inspecting the generated assembly
 //!
 //! What it covers
-//! - ITM tracing
+//! - Rust panic tracing using ITM
 //! - assembly calls and inline assembly
 //! - more on arithmetics
 
 #![no_main]
 #![no_std]
 
-extern crate panic_itm;
+use panic_itm as _;
 
 use cortex_m_rt::entry;
 
@@ -45,18 +45,18 @@ fn main() -> ! {
 //
 //    You may need/want to install additional components also.
 //    To that end look at the install section in the README.md.
-//    If you change toolchain, you may need to exit and re-start `vscode`.
+//    (If you change toolchain, you may need to exit and re-start `vscode`.)
 //
 // 1. Build and run the application
 //
-//    > cargo build --example bare1
-//    (or use the vscode build task)
+//    > cargo run --example bare1
+//    (or use the `itm fifo (debug)` or the `itm internal (debug)` launch configuration.)
 //
-//    Make sure you have followed the instructions for fifo `ITM` tracing.
-//    Debug using the `itm fifo (debug)` launch configuration.
+//    Make sure you have followed the instructions for fifo `ITM` tracing accordingly.
 //
 //    When debugging the application it should hit the `bkpt` instruction.
 //    What happens when you continue (second iteration of the loop)?
+//    (passing 3 breakpoints)
 //
 //    ** your answer here **
 //    The program panics "panicked at 'attempt to add with overflow', examples/bare1.rs:23:9 "
@@ -64,6 +64,7 @@ fn main() -> ! {
 //    What is the `ITM` output.
 //
 //    ** your answer here **
+//    panicked at 'attempt to add with overflow', examples/bare1.rs:23:9
 //
 //    Commit your answer (bare1_1)
 //
@@ -92,7 +93,7 @@ fn main() -> ! {
 //    Rebuild `bare1.rs` in release (optimized mode).
 //
 //    > cargo build --example bare1 --release
-//    (or using the vscode build task)
+//    (or using the vscode)
 //
 //    Compare the generated assembly for the loop
 //    between the dev (un-optimized) and release (optimized) build.
@@ -110,6 +111,11 @@ fn main() -> ! {
 //
 //    ** your answer here **
 //
+//    Is there now any reference to the panic handler?
+//    If not, why is that the case?
+//
+//    ** your answer here **
+//
 //    commit your answers (bare1_3)
 //
 //    Discussion:
@@ -132,7 +138,32 @@ fn main() -> ! {
 //    Later we will demonstrate how we can get guarantees of panic free execution.
 //    This is very important to improve reliability.
 //
-// 4. *Optional
+// 4. Now comment out the `read_volatile`.
+//
+//    > cargo build --example bare1 --release
+//    (or using the vscode)
+//
+//    Compare the generated assembly for the loop
+//    between the dev (un-optimized) and release (optimized) build.
+//
+//    What is the output of:
+//    > disassemble
+//
+//    ** your answer here **
+//
+//    How many instructions are in between the two `bkpt` instructions.
+//
+//    ** your answer here **
+//
+//    Where is the local variable stored?
+//    What happened, and why is Rust + LLVM allowed to do that?
+//
+//    ** your answer here **
+//
+//    commit your answers (bare1_4)
+//
+//
+// 5. *Optional
 //    You can pass additional flags to the Rust `rustc` compiler.
 //
 //    `-Z force-overflow-checks=off`
@@ -145,11 +176,11 @@ fn main() -> ! {
 //
 //    ** your answer here **
 //
-//    commit your answers (bare1_4)
+//    commit your answers (bare1_5)
 //
 //    Now restore the `.cargo/config` to its original state.
 //
-// 5. *Optional
+// 6. *Optional
 //    There is another way to conveniently use wrapping arithmetics
 //    without passing flags to the compiler.
 //
@@ -165,7 +196,7 @@ fn main() -> ! {
 //
 //    ** your answer here **
 //
-//    commit your answers (bare1_5)
+//    commit your answers (bare1_6)
 //
 //    Final discussion:
 //
diff --git a/examples/bare10.rs b/examples/bare10.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ac819564e8eec60cb9188bca1a13786e50bf3429
--- /dev/null
+++ b/examples/bare10.rs
@@ -0,0 +1,225 @@
+//! The RTFM framework
+//!
+//! What it covers:
+//! - Priority based scheduling
+//! - Message passing
+
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m::{asm, iprintln};
+
+extern crate stm32f4xx_hal as hal;
+use crate::hal::prelude::*;
+use crate::hal::serial::{config::Config, Event, Rx, Serial, Tx};
+use hal::stm32::ITM;
+
+use nb::block;
+use rtfm::app;
+
+// Our error type
+#[derive(Debug)]
+pub enum Error {
+    RingBufferOverflow,
+    UsartSendOverflow,
+    UsartReceiveOverflow,
+}
+
+#[app(device = hal::stm32, peripherals = true)]
+const APP: () = {
+    struct Resources {
+        // Late resources
+        TX: Tx<hal::stm32::USART2>,
+        RX: Rx<hal::stm32::USART2>,
+        ITM: ITM,
+    }
+    // init runs in an interrupt free section>
+    #[init]
+    fn init(cx: init::Context) -> init::LateResources {
+        let mut core = cx.core;
+        let device = cx.device;
+
+        let stim = &mut core.ITM.stim[0];
+        iprintln!(stim, "bare10");
+
+        let rcc = device.RCC.constrain();
+
+        // 16 MHz (default, all clocks)
+        let clocks = rcc.cfgr.freeze();
+
+        let gpioa = device.GPIOA.split();
+
+        let tx = gpioa.pa2.into_alternate_af7();
+        let rx = gpioa.pa3.into_alternate_af7(); // try comment out
+
+        let mut serial = Serial::usart2(
+            device.USART2,
+            (tx, rx),
+            Config::default().baudrate(115_200.bps()),
+            clocks,
+        )
+        .unwrap();
+
+        // generate interrupt on Rxne
+        serial.listen(Event::Rxne);
+        // Separate out the sender and receiver of the serial port
+        let (tx, rx) = serial.split();
+
+        // Late resources
+        init::LateResources {
+            // Our split serial
+            TX: tx,
+            RX: rx,
+
+            // For debugging
+            ITM: core.ITM,
+        }
+    }
+
+    // idle may be interrupted by other interrupt/tasks in the system
+    #[idle]
+    fn idle(_cx: idle::Context) -> ! {
+        loop {
+            asm::wfi();
+        }
+    }
+
+    #[task(priority = 1, resources = [ITM])]
+    fn trace_data(cx: trace_data::Context, byte: u8) {
+        let stim = &mut cx.resources.ITM.stim[0];
+        iprintln!(stim, "data {}", byte);
+        // for _ in 0..10000 {
+        //     asm::nop();
+        // }
+    }
+
+    #[task(priority = 1, resources = [ITM])]
+    fn trace_error(cx: trace_error::Context, error: Error) {
+        let stim = &mut cx.resources.ITM.stim[0];
+        iprintln!(stim, "{:?}", error);
+    }
+
+    #[task(priority = 2, resources = [TX], spawn = [trace_error])]
+    fn echo(cx: echo::Context, byte: u8) {
+        let tx = cx.resources.TX;
+
+        if block!(tx.write(byte)).is_err() {
+            let _ = cx.spawn.trace_error(Error::UsartSendOverflow);
+        }
+    }
+
+    #[task(binds = USART2, priority = 3, resources = [RX], spawn = [trace_data, trace_error, echo])]
+    fn usart2(cx: usart2::Context) {
+        let rx = cx.resources.RX;
+
+        match rx.read() {
+            Ok(byte) => {
+                let _ = cx.spawn.echo(byte);
+                if cx.spawn.trace_data(byte).is_err() {
+                    let _ = cx.spawn.trace_error(Error::RingBufferOverflow);
+                }
+            }
+            Err(_err) => {
+                let _ = cx.spawn.trace_error(Error::UsartReceiveOverflow);
+            }
+        }
+    }
+
+    // Set of interrupt vectors, free to use for RTFM tasks
+    // 1 per priority level suffices
+    extern "C" {
+        fn EXTI0();
+        fn EXTI1();
+    }
+};
+
+// Optional
+// 0. Compile and run the project at 16MHz in release mode
+//    make sure its running (not paused).
+//
+//    > cargo build --example bare10 --features "rtfm" --release
+//    (or use the vscode build task)
+//
+//    Connect a terminal program.
+//    Verify that it works as bare9.
+//
+// 1. Now, comment out the loop in `trace_data`.
+//    The loop is just there to simulate some workload...
+//
+//    Try now to send a sequence `abcd`
+//
+//    Did you loose any data (was the data correctly echoed)?
+//
+//    ** your answer here **
+//
+//    Was the data correctly traced over the ITM?
+//
+//    ** your answer here **
+//
+//    Why did you loose trace information?
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare10_1)
+//
+// 2. Read the RTFM manual (book).
+//    Figure out a way to accomodate for 4 outstanding messages to the `trace_data` task.
+//
+//    Verify that you can now correctly trace sequences of 4 characters sent.
+//
+//    Can you think of how to determine a safe bound on the message buffer size?
+//    (Safe meaning, that message would never be lost due to the buffer being full.)
+//
+//    What information would you need?
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare10_2)
+//
+// 3. Implement a command line interpreter as a new task.
+//    It should:
+//    - have priority 1.
+//    - take a byte as an argument (passed from the USART2 interrupt).
+//    - have a local buffer B of 10 characters
+//    - have sufficient capacity to receive 10 characters sent in a sequence
+//    - analyse the input buffer B checking the commands
+//      set <int> <RETURN>       // to set blinking frequency
+//      on <RETURN>              // to enable the led blinking
+//      of <RETURN>              // to disable the led blinking
+//
+//      <int> should be decoded to an integer value T, and <RETURN> accept either <CR> or <LF>.
+//
+//    The set value should blink the LED in according the set value in Hertz,
+//    (so `set 1 <RETURN>` should blink with 1Hz)
+//
+//    Tips:
+//    Create two tasks, (`on', that turns the led on, and a task `off` that turns the led off).
+//    `on` calls `off` with a timer offset (check the RTFM manual).
+//    `off` calls `on` with a timer offset.
+//
+//    The timing offset can implemented as a shared resource T between the command line interpreter and
+//    the  'on/off ' tasks. From `init` you can give an initial timing offset T, and send an
+//    initial message to `on` triggering the periodic behavior.
+//
+//    The 'on/off ' tasks can have a high priority 4, and use locking (in the low priority task)
+//    parsing the input. This way, the led will have a very low jitter.
+//
+//    (You can even use an atomic data structure, which allows for lock free access.)
+//
+//
+//    The on/off is easiest implemented by having another shared variable used as a condition
+//    for the `on` task to set the GPIO. Other solutions could be to stop the sequence (i.e.)
+//    conditionally call the `off` task instead. Then the command interpreted would
+//    trigger a new sequence when an "on" command is detected. (Should you allow multiple, overlapping)
+//    sequences? Why not, could be cool ;)
+//    The main advantage of the stopping approach is that the system will be truly idle
+//    if not blinking, and thus more power efficient.
+//
+//    You can reuse the code for setting up and controlling the GPIO/led.
+//
+//    You can come up with various extensions to this application, setting the
+//    the duty cycle (on/off ratio in %), etc.
+//
+//    Commit your solution (bare10_3)
diff --git a/examples/bare2.rs b/examples/bare2.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ce6acb20fb9221507961a8586a4ba8211917db1c
--- /dev/null
+++ b/examples/bare2.rs
@@ -0,0 +1,101 @@
+//! bare2.rs
+//!
+//! Measuring execution time
+//!
+//! What it covers
+//! - Generating documentation
+//! - Using core peripherals
+//! - Measuring time using the DWT
+//! - ITM tracing using `iprintln`
+//! - Panic halt
+//!
+
+#![no_main]
+#![no_std]
+
+use panic_halt as _;
+
+use cortex_m::{iprintln, peripheral::DWT, Peripherals};
+use cortex_m_rt::entry;
+
+// burns CPU cycles by just looping `i` times
+#[inline(never)]
+fn wait(i: u32) {
+    for _ in 0..i {
+        // no operation (ensured not optimized out)
+        cortex_m::asm::nop();
+    }
+}
+
+#[entry]
+fn main() -> ! {
+    let mut p = Peripherals::take().unwrap();
+    let stim = &mut p.ITM.stim[0];
+    let mut dwt = p.DWT;
+
+    iprintln!(stim, "bare2");
+
+    dwt.enable_cycle_counter();
+
+    // Reading the cycle counter can be done without `owning` access
+    // the DWT (since it has no side effect).
+    //
+    // Look in the docs:
+    // pub fn enable_cycle_counter(&mut self)
+    // pub fn get_cycle_count() -> u32
+    //
+    // Notice the difference in the function signature!
+
+    let start = DWT::get_cycle_count();
+    wait(1_000_000);
+    let end = DWT::get_cycle_count();
+
+    // notice all printing outside of the section to measure!
+    iprintln!(stim, "Start {:?}", start);
+    iprintln!(stim, "End {:?}", end);
+    iprintln!(stim, "Diff {:?}", end - start);
+
+    loop {}
+}
+
+// 0. Setup
+//    > cargo doc --open
+//
+//    This will document your crate, and open the docs in your browser.
+//    If it does not auto-open, then copy paste the path in your browser.
+//    (Notice, it will try to document all dependencies, you may have only one
+//    one panic handler, so comment out all but one in `Cargo.toml`.)
+//
+//    In the docs, search (`S`) for DWT, and click `cortex_m::peripheral::DWT`.
+//    Read the API docs.
+//
+// 1. Build and run the application (debug build).
+//    Setup ITM tracing (see `bare1.rs`) and `openocd` (if not using vscode).
+//
+//    > cargo run --example bare2
+//    (or use the vscode build task)
+//
+//    What is the output in the ITM console?
+//
+//    ** your answer here **
+//
+//    Rebuild and run in release mode
+//
+//    > cargo build --example bare2 --release
+//
+//    ** your answer here **
+//
+//    Compute the ratio between debug/release optimized code
+//    (the speedup).
+//
+//    ** your answer here **
+//
+//    commit your answers (bare2_1)
+//
+// 3. *Optional
+//    Inspect the generated binaries, and try stepping through the code
+//    for both debug and release binaries. How do they differ?
+//
+//    ** your answer here **
+//
+//    commit your answers (bare2_2)
diff --git a/examples/bare3.rs b/examples/bare3.rs
new file mode 100644
index 0000000000000000000000000000000000000000..665b4da687d3ca0285abdf1ae5268b9ba0a4c340
--- /dev/null
+++ b/examples/bare3.rs
@@ -0,0 +1,148 @@
+//! bare3.rs
+//!
+//! String types in Rust
+//!
+//! What it covers:
+//! - Types, str, arrays ([u8; usize]), slices (&[u8])
+//! - Iteration, copy
+//! - Semihosting (tracing using `hprintln`
+
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m_rt::entry;
+use cortex_m_semihosting::{hprint, hprintln};
+
+#[entry]
+fn main() -> ! {
+    hprintln!("bare3").unwrap();
+    let s = "ABCD";
+    let bs = s.as_bytes();
+
+    hprintln!("s = {}", s).unwrap();
+    hprintln!("bs = {:?}", bs).unwrap();
+
+    hprintln!("iterate over slice").unwrap();
+    for c in bs {
+        hprint!("{},", c).unwrap();
+    }
+
+    hprintln!("iterate iterate using (raw) indexing").unwrap();
+    for i in 0..s.len() {
+        hprintln!("{},", bs[i]).unwrap();
+    }
+
+    hprintln!("").unwrap();
+
+    let a = [65u8; 4];
+    // let mut a = [0u8; 4];
+
+    hprintln!("").unwrap();
+    hprintln!("a = {}", core::str::from_utf8(&a).unwrap()).unwrap();
+
+    loop {
+        continue;
+    }
+}
+
+// 0. Build and run the application (debug build).
+//
+//    > cargo run --example bare3
+//    (or use the vscode build task)
+//
+// 1. What is the output in the `openocd` (Adapter Output) console?
+//
+//    ** your answer here **
+//
+//    What is the type of `s`?
+//
+//    ** your answer here **
+//
+//    What is the type of `bs`?
+//
+//    ** your answer here **
+//
+//    What is the type of `c`?
+//
+//    ** your answer here **
+//
+//    What is the type of `a`?
+//
+//    ** your answer here **
+//
+//    What is the type of `i`?
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare3_1)
+//
+// 2. Make types of `s`, `bs`, `c`, `a`, `i` explicit.
+//
+//    Commit your answers (bare3_2)
+//
+// 3. Uncomment line `let mut a = [0u8; 4];
+//`
+//    Run the program, what happens and why?
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare3_3)
+//
+// 4. Alter the program so that the data from `bs` is copied byte
+//    by byte into `a` using a loop and raw indexing.
+//
+//    Test that it works as intended.
+//
+//    Commit your answers (bare3_4)
+//
+// 5. Look for a way to make this copy done without a loop.
+//    https://doc.rust-lang.org/std/primitive.slice.html
+//
+//    Implement and test your solution.
+//
+//    Commit your answers (bare3_5)
+//
+// 6. Optional
+//    Rust is heavily influenced by functional languages.
+//    Figure out how you can use an iterator to work over both
+//    the `a` and `bs` to copy the content of `bs` to `a`.
+//
+//    You may use
+//    - `iter` (to turn a slice into an iterator)
+//    - `zip` (to merge two slices into an iterator)
+//    - a for loop to assign the elements
+//
+//    Commit your solution (bare3_6)
+//
+// 7. Optional
+//    Iter using `foreach` and a closure instead of the for loop.
+//
+//    Commit your solution (bare3_7)
+//
+// 8. Optional*
+//    Now benchmark your different solutions using the cycle accurate
+//    DWT based approach (in release mode).
+//
+//    Cycle count for `raw` indexing
+//
+//    ** your answer here **
+//
+//    Cycle count for the primitive slice approach.
+//
+//    ** your answer here **
+//
+//    Cycle count for the primitive slice approach.
+//
+//    ** your answer here **
+//
+//    Cycle count for the zip + for loop approach.
+//
+//    ** your answer here **
+//
+//    Cycle count for the zip + for_each approach.
+//
+//    What conclusions can you draw, does Rust give you zero-cost abstractions?
+//
+//    ** your answer here **
diff --git a/examples/bare4.rs b/examples/bare4.rs
new file mode 100644
index 0000000000000000000000000000000000000000..07ce483f31f97174ac046b5a43a6548af79a212d
--- /dev/null
+++ b/examples/bare4.rs
@@ -0,0 +1,134 @@
+//! bare4.rs
+//!
+//! Access to Peripherals
+//!
+//! What it covers:
+//! - Raw pointers
+//! - Volatile read/write
+//! - Busses and clocking
+//! - GPIO (a primitive abstraction)
+
+#![no_std]
+#![no_main]
+
+extern crate panic_halt;
+
+extern crate cortex_m;
+use cortex_m_rt::entry;
+
+// Peripheral addresses as constants
+#[rustfmt::skip]
+mod address {
+    pub const PERIPH_BASE: u32      = 0x40000000;
+    pub const AHB1PERIPH_BASE: u32  = PERIPH_BASE + 0x00020000;
+    pub const RCC_BASE: u32         = AHB1PERIPH_BASE + 0x3800;
+    pub const RCC_AHB1ENR: u32      = RCC_BASE + 0x30;
+    pub const GBPIA_BASE: u32       = AHB1PERIPH_BASE + 0x0000;
+    pub const GPIOA_MODER: u32      = GBPIA_BASE + 0x00;
+    pub const GPIOA_BSRR: u32       = GBPIA_BASE + 0x18;
+}
+
+use address::*;
+
+// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
+// rcc,     chapter 6
+// gpio,    chapter 8
+
+#[inline(always)]
+fn read_u32(addr: u32) -> u32 {
+    unsafe { core::ptr::read_volatile(addr as *const _) }
+    //core::ptr::read_volatile(addr as *const _)
+}
+
+#[inline(always)]
+fn write_u32(addr: u32, val: u32) {
+    unsafe {
+        core::ptr::write_volatile(addr as *mut _, val);
+    }
+}
+
+fn wait(i: u32) {
+    for _ in 0..i {
+        cortex_m::asm::nop(); // no operation (cannot be optimized out)
+    }
+}
+
+#[entry]
+fn main() -> ! {
+    // power on GPIOA
+    let r = read_u32(RCC_AHB1ENR); // read
+    write_u32(RCC_AHB1ENR, r | 1); // set enable
+
+    // configure PA5 as output
+    let r = read_u32(GPIOA_MODER) & !(0b11 << (5 * 2)); // read and mask
+    write_u32(GPIOA_MODER, r | 0b01 << (5 * 2)); // set output mode
+
+    // and alter the data output through the BSRR register
+    // this is more efficient as the read register is not needed.
+
+    loop {
+        // set PA5 high
+        write_u32(GPIOA_BSRR, 1 << 5); // set bit, output hight (turn on led)
+        wait(10_000);
+
+        // set PA5 low
+        write_u32(GPIOA_BSRR, 1 << (5 + 16)); // clear bit, output low (turn off led)
+        wait(10_000);
+    }
+}
+
+// 0.  Build and run the application (debug build).
+//
+//    > cargo run --example bare4
+//    (or use the vscode)
+//
+// 1.  Did you enjoy the blinking?
+//
+//    ** your answer here **
+//
+//    Now lookup the data-sheets, and read each section referred,
+//    6.3.11, 8.4.1, 8.4.7
+//
+//    Document each low level access *code* by the appropriate section in the
+//    data sheet.
+//
+//    Commit your answers (bare4_1)
+//
+// 2. Comment out line 40 and uncomment line 41 (essentially omitting the `unsafe`)
+//
+//    //unsafe { core::ptr::read_volatile(addr as *const _) }
+//    core::ptr::read_volatile(addr as *const _)
+//
+//    What was the error message and explain why.
+//
+//    ** your answer here **
+//
+//    Digging a bit deeper, why do you think `read_volatile` is declared `unsafe`.
+//    (https://doc.rust-lang.org/core/ptr/fn.read_volatile.html, for some food for thought )
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare4_2)
+//
+// 3. Volatile read/writes are explicit *volatile operations* in Rust, while in C they
+//    are declared at type level (i.e., access to varibles declared volatile amounts to
+//    volatile reads/and writes).
+//
+//    Both C and Rust (even more) allows code optimization to re-order operations, as long
+//    as data dependencies are preserved.
+//
+//    Why is it important that ordering of volatile operations are ensured by the compiler?
+//
+//    ** your answer here **
+//
+//    Give an example in the above code, where reordering might make things go horribly wrong
+//    (hint, accessing a peripheral not being powered...)
+//
+//    ** your answer here **
+//
+//    Without the non-reordering property of `write_volatile/read_volatile` could that happen in theory
+//    (argue from the point of data dependencies).
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare4_3)
diff --git a/examples/bare5.rs b/examples/bare5.rs
new file mode 100644
index 0000000000000000000000000000000000000000..138c7ee46881c9fb933de665b8d78a65eb6cc0fc
--- /dev/null
+++ b/examples/bare5.rs
@@ -0,0 +1,253 @@
+//! bare5.rs
+//!
+//! C Like Peripheral API
+//!
+//! What it covers:
+//! - abstractions in Rust
+//! - structs and implementations
+
+#![no_std]
+#![no_main]
+
+extern crate panic_halt;
+
+extern crate cortex_m;
+use cortex_m_rt::entry;
+
+// C like API...
+mod stm32f40x {
+    #[allow(dead_code)]
+    use core::{cell, ptr};
+
+    #[rustfmt::skip]
+    mod address {
+        pub const PERIPH_BASE: u32      = 0x40000000;
+        pub const AHB1PERIPH_BASE: u32  = PERIPH_BASE + 0x00020000;
+        pub const RCC_BASE: u32         = AHB1PERIPH_BASE + 0x3800;
+        pub const GPIOA_BASE: u32       = AHB1PERIPH_BASE + 0x0000;
+    }
+    use address::*;
+
+    pub struct VolatileCell<T> {
+        value: cell::UnsafeCell<T>,
+    }
+
+    impl<T> VolatileCell<T> {
+        #[inline(always)]
+        pub fn read(&self) -> T
+        where
+            T: Copy,
+        {
+            unsafe { ptr::read_volatile(self.value.get()) }
+        }
+
+        #[inline(always)]
+        pub fn write(&self, value: T)
+        where
+            T: Copy,
+        {
+            unsafe { ptr::write_volatile(self.value.get(), value) }
+        }
+    }
+
+    // modify (reads, modifies a field, and writes the volatile cell)
+    //
+    // parameters:
+    // offset (field offset)
+    // width  (field width)
+    // value  (new value that the field should take)
+    //
+    // impl VolatileCell<u32> {
+    //     #[inline(always)]
+    //     pub fn modify(&self, offset: u8, width: u8, value: u32) {
+    //         // your code here
+    //     }
+    // }
+
+    #[repr(C)]
+    #[allow(non_snake_case)]
+    #[rustfmt::skip]
+    pub struct RCC {
+        pub CR:         VolatileCell<u32>,      // < RCC clock control register,                                    Address offset: 0x00 
+        pub PLLCFGR:    VolatileCell<u32>,      // < RCC PLL configuration register,                                Address offset: 0x04 
+        pub CFGR:       VolatileCell<u32>,      // < RCC clock configuration register,                              Address offset: 0x08 
+        pub CIR:        VolatileCell<u32>,      // < RCC clock interrupt register,                                  Address offset: 0x0C 
+        pub AHB1RSTR:   VolatileCell<u32>,      // < RCC AHB1 peripheral reset register,                            Address offset: 0x10 
+        pub AHB2RSTR:   VolatileCell<u32>,      // < RCC AHB2 peripheral reset register,                            Address offset: 0x14 
+        pub AHB3RSTR:   VolatileCell<u32>,      // < RCC AHB3 peripheral reset register,                            Address offset: 0x18 
+        pub RESERVED0:  VolatileCell<u32>,      // < Reserved, 0x1C                                                                      
+        pub APB1RSTR:   VolatileCell<u32>,      // < RCC APB1 peripheral reset register,                            Address offset: 0x20 
+        pub APB2RSTR:   VolatileCell<u32>,      // < RCC APB2 peripheral reset register,                            Address offset: 0x24 
+        pub RESERVED1:  [VolatileCell<u32>; 2], // < Reserved, 0x28-0x2C                                                                 
+        pub AHB1ENR:    VolatileCell<u32>,      // < RCC AHB1 peripheral clock register,                            Address offset: 0x30 
+        pub AHB2ENR:    VolatileCell<u32>,      // < RCC AHB2 peripheral clock register,                            Address offset: 0x34 
+        pub AHB3ENR:    VolatileCell<u32>,      // < RCC AHB3 peripheral clock register,                            Address offset: 0x38 
+        pub RESERVED2:  VolatileCell<u32>,      // < Reserved, 0x3C                                                                      
+        pub APB1ENR:    VolatileCell<u32>,      // < RCC APB1 peripheral clock enable register,                     Address offset: 0x40 
+        pub APB2ENR:    VolatileCell<u32>,      // < RCC APB2 peripheral clock enable register,                     Address offset: 0x44 
+        pub RESERVED3:  [VolatileCell<u32>; 2], // < Reserved, 0x48-0x4C                                                                 
+        pub AHB1LPENR:  VolatileCell<u32>,      // < RCC AHB1 peripheral clock enable in low power mode register,   Address offset: 0x50 
+        pub AHB2LPENR:  VolatileCell<u32>,      // < RCC AHB2 peripheral clock enable in low power mode register,   Address offset: 0x54 
+        pub AHB3LPENR:  VolatileCell<u32>,      // < RCC AHB3 peripheral clock enable in low power mode register,   Address offset: 0x58 
+        pub RESERVED4:  VolatileCell<u32>,      // < Reserved, 0x5C                                                                      
+        pub APB1LPENR:  VolatileCell<u32>,      // < RCC APB1 peripheral clock enable in low power mode register,   Address offset: 0x60 
+        pub APB2LPENR:  VolatileCell<u32>,      // < RCC APB2 peripheral clock enable in low power mode register,   Address offset: 0x64 
+        pub RESERVED5:  [VolatileCell<u32>; 2], // < Reserved, 0x68-0x6C                                                                 
+        pub BDCR:       VolatileCell<u32>,      // < RCC Backup domain control register,                            Address offset: 0x70 
+        pub CSR:        VolatileCell<u32>,      // < RCC clock control & status register,                           Address offset: 0x74 
+        pub RESERVED6:  [VolatileCell<u32>; 2], // < Reserved, 0x78-0x7C                                                                 
+        pub SSCGR:      VolatileCell<u32>,      // < RCC spread spectrum clock generation register,                 Address offset: 0x80 
+        pub PLLI2SCFGR: VolatileCell<u32>,      // < RCC PLLI2S configuration register,                             Address offset: 0x84 
+    }
+
+    impl RCC {
+        pub fn get() -> *mut RCC {
+            address::RCC_BASE as *mut RCC
+        }
+    }
+
+    #[repr(C)]
+    #[allow(non_snake_case)]
+    #[rustfmt::skip]
+    pub struct GPIOA {
+        pub MODER:      VolatileCell<u32>,      // < GPIO port mode register,                                       Address offset: 0x00     
+        pub OTYPER:     VolatileCell<u32>,      // < GPIO port output type register,                                Address offset: 0x04     
+        pub OSPEEDR:    VolatileCell<u32>,      // < GPIO port output speed register,                               Address offset: 0x08     
+        pub PUPDR:      VolatileCell<u32>,      // < GPIO port pull-up/pull-down register,                          Address offset: 0x0C     
+        pub IDR:        VolatileCell<u32>,      // < GPIO port input data register,                                 Address offset: 0x10     
+        pub ODR:        VolatileCell<u32>,      // < GPIO port output data register,                                Address offset: 0x14     
+        pub BSRRL:      VolatileCell<u16>,      // < GPIO port bit set/reset low register,                          Address offset: 0x18     
+        pub BSRRH:      VolatileCell<u16>,      // < GPIO port bit set/reset high register,                         Address offset: 0x1A     
+        pub LCKR:       VolatileCell<u32>,      // < GPIO port configuration lock register,                         Address offset: 0x1C     
+        pub AFR:        [VolatileCell<u32>;2],  // < GPIO alternate function registers,                             Address offset: 0x20-0x24
+    }
+
+    impl GPIOA {
+        pub fn get() -> *mut GPIOA {
+            GPIOA_BASE as *mut GPIOA
+        }
+    }
+}
+use stm32f40x::*;
+
+// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
+// rcc,     chapter 6
+// gpio,    chapter 8
+
+fn wait(i: u32) {
+    for _ in 0..i {
+        cortex_m::asm::nop(); // no operation (cannot be optimized out)
+    }
+}
+
+// simple test of Your `modify`
+//fn test() {
+// let t:VolatileCell<u32> = unsafe {  core::mem::uninitialized() };
+// t.write(0);
+// assert!(t.read() == 0);
+// t.modify(3, 3, 0b10101);
+// //
+// //     10101
+// //    ..0111000
+// //    ---------
+// //    000101000
+// assert!(t.read() == 0b101 << 3);
+// t.modify(4, 3, 0b10001);
+// //    000101000
+// //      111
+// //      001
+// //    000011000
+// assert!(t.read() == 0b011 << 3);
+
+// if << is used, your code will panic in dev (debug), but not in release mode
+// t.modify(32, 3, 1);
+//}
+
+// system startup, can be hidden from the user
+#[entry]
+fn main() -> ! {
+    let rcc = unsafe { &mut *RCC::get() }; // get the reference to RCC in memory
+    let gpioa = unsafe { &mut *GPIOA::get() }; // get the reference to GPIOA in memory
+
+    // test(); // uncomment to run test
+    idle(rcc, gpioa);
+    loop {
+        continue;
+    }
+}
+
+// user application
+fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) {
+    // power on GPIOA
+    let r = rcc.AHB1ENR.read(); // read
+    rcc.AHB1ENR.write(r | 1 << (0)); // set enable
+
+    // configure PA5 as output
+    let r = gpioa.MODER.read() & !(0b11 << (5 * 2)); // read and mask
+    gpioa.MODER.write(r | 0b01 << (5 * 2)); // set output mode
+
+    loop {
+        // set PA5 high
+        gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led)
+
+        // alternatively to set the bit high we can
+        // read the value, or with PA5 (bit 5) and write back
+        // gpioa.ODR.write(gpioa.ODR.read() | (1 << 5));
+
+        wait(10_000);
+
+        // set PA5 low
+        gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led)
+
+        // alternatively to clear the bit we can
+        // read the value, mask out PA5 (bit 5) and write back
+        // gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5));
+        wait(10_000);
+    }
+}
+
+// 0. Build and run the application.
+//
+//    > cargo build --example bare5
+//    (or use the vscode)
+//
+// 1. C like API.
+//    Using C the .h files are used for defining interfaces, like function signatures (prototypes),
+//    structs and macros (but usually not the functions themselves).
+//
+//    Here is a peripheral abstraction quite similar to what you would find in the .h files
+//    provided by ST (and other companies). Actually, the file presented here is mostly a
+//    cut/paste/replace of the stm32f40x.h, just Rustified.
+//
+//    In this case we pass mutable pointers of the peripherals to the `idle` function.
+//
+//    In the loop we access PA5 through bit set/clear operations.
+//    Comment out those operations and uncomment the the ODR accesses.
+//    (They should have the same behavior, but is a bit less efficient.)
+//
+//    Run and see that the program behaves the same.
+//
+//    Commit your answers (bare5_1)
+//
+// 2. Extend the read/write API with a `modify` for u32, taking the
+//    - address (&mut u32),
+//    - field offset (in bits, u8),
+//    - field width (in bits, u8),
+//    - and value (u32).
+//
+//    Implement and check that running `test` gives you expected behavior.
+//
+//    Change the code into using your new API.
+//
+//    Run and see that the program behaves the same.
+//
+//    Commit your answers (bare5_2)
+//
+//    Discussion:
+//    As with arithmetic operations, default semantics differ in between
+//    debug/dev and release builds. E.g., debug << rhs is checked, rhs must be less
+//    than 32 (for 32 bit datatypes).
+//
+//    Notice, over-shifting (where bits are spilled) is always considered legal,
+//    its just the shift amount that is checked.
+//    There are explicit unchecked versions available if so wanted.
diff --git a/examples/bare6.rs b/examples/bare6.rs
new file mode 100644
index 0000000000000000000000000000000000000000..fe91a1398a516097a29b3c7727ef156b5752fe43
--- /dev/null
+++ b/examples/bare6.rs
@@ -0,0 +1,212 @@
+//! bare6.rs
+//!
+//! Clocking
+//!
+//! What it covers:
+//! - using svd2rust generated API
+//! - setting the clock via script (again)
+//! - routing the clock to a PIN for monitoring by an oscilloscope
+
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m::{iprintln, peripheral::itm::Stim};
+use cortex_m_rt::entry;
+
+use stm32f4::stm32f401::{self, DWT, GPIOA, GPIOC, RCC};
+
+#[entry]
+fn main() -> ! {
+    let p = stm32f401::Peripherals::take().unwrap();
+    let mut c = stm32f401::CorePeripherals::take().unwrap();
+
+    let stim = &mut c.ITM.stim[0];
+    iprintln!(stim, "bare6");
+
+    c.DWT.enable_cycle_counter();
+    unsafe {
+        c.DWT.cyccnt.write(0);
+    }
+    let t = DWT::get_cycle_count();
+    iprintln!(stim, "{}", t);
+
+    clock_out(&p.RCC, &p.GPIOC);
+    idle(stim, p.RCC, p.GPIOA);
+}
+
+// user application
+fn idle(stim: &mut Stim, rcc: RCC, gpioa: GPIOA) -> ! {
+    iprintln!(stim, "idle");
+
+    // power on GPIOA, RM0368 6.3.11
+    rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+
+    // configure PA5 as output, RM0368 8.4.1
+    gpioa.moder.modify(|_, w| w.moder5().bits(1));
+
+    // at 16 Mhz, 8_000_000 cycles = period 0.5s
+    // at 64 Mhz, 4*8_000_000 cycles = period 0.5s
+    // let cycles = 8_000_000;
+    let cycles = 4 * 8_000_000;
+
+    loop {
+        iprintln!(stim, "on {}", DWT::get_cycle_count());
+        // set PA5 high, RM0368 8.4.7
+        gpioa.bsrr.write(|w| w.bs5().set_bit());
+        wait_cycles(cycles);
+
+        iprintln!(stim, "off {}", DWT::get_cycle_count());
+        // set PA5 low, RM0368 8.4.7
+        gpioa.bsrr.write(|w| w.br5().set_bit());
+        wait_cycles(cycles);
+    }
+}
+
+// uses the DWT.CYCNT
+// doc: ARM trm_100166_0001_00_en.pdf, chapter 9.2
+// we use the `cortex-m` abstraction, as re-exported by the stm32f40x
+fn wait_cycles(nr_cycles: u32) {
+    let t = DWT::get_cycle_count().wrapping_add(nr_cycles);
+    while (DWT::get_cycle_count().wrapping_sub(t) as i32) < 0 {}
+}
+
+// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
+// rcc,     chapter 6
+// gpio,    chapter 8
+fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
+    // output MCO2 to pin PC9
+
+    // mco2 	: SYSCLK = 0b00
+    // mcopre 	: divide by 4 = 0b110
+    rcc.cfgr
+        .modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) });
+   
+    // power on GPIOC, RM0368 6.3.11
+    rcc.ahb1enr.modify(|_, w| w.gpiocen().set_bit());
+
+    // MCO_2 alternate function AF0, STM32F401xD STM32F401xE data sheet
+    // table 9
+    // AF0, gpioc reset value = AF0
+
+    // configure PC9 as alternate function 0b10, RM0368 6.2.10
+    gpioc.moder.modify(|_, w| w.moder9().bits(0b10));
+    
+    // otyper reset state push/pull, in reset state (don't need to change)
+
+    // ospeedr 0b11 = very high speed
+    gpioc.ospeedr.modify(|_, w| w.ospeedr9().bits(0b11));
+}
+
+// Optional assignment
+// 0. Compile and run the example, in 16Mhz
+//
+//    > cargo build --example bare6 --features "stm32f4"
+//    (or use the vscode build task)
+//
+//    The "stm32f4" feature enables the optional dependency "stm32f4", with the "stm32f401" feature set
+//
+//    Cargo.toml:
+// 
+//    [dependencies.stm32f4]
+//    version         = "0.9.0"
+//    features        = ["stm32f401", "rt"]
+//    optional        = true
+//    (this will provide the "stm32f401" interrupt vector through the "rt" feature)
+//
+//    [[example]]
+//    name                = "bare6"
+//    required-features   = ["stm32f4"]
+//    (this will require/force you to use the stm32f4 feature)
+//
+// 1. The processor SYSCLK defaults to HCI 16Mhz
+//    (this is what you get after a `monitor reset halt`).
+//
+//    Confirm that your ITM dump traces the init, idle and led on/off.
+//    Make sure your TPIU is set to a system clock at 16Mhz
+//
+//    What is the frequency of blinking?
+//
+//    ** your answer here **
+//
+//    commit your answers (bare6_1)
+//
+// 2. Now connect an oscilloscope to PC9, which is set to
+//    output the MCO2.
+//
+//    What is the frequency of MCO2 read by the oscilloscope?
+//
+//    ** your answer here **
+//
+//    Compute the value of SYSCLK based on the oscilloscope reading
+//
+//    ** your answer here **
+//
+//    What is the peak to peak reading of the signal?
+//
+//    ** your answer here **
+//
+//    Make a folder called "pictures" in your git project.
+//    Make a screen dump or photo of the oscilloscope output.
+//    Save the the picture as "bare_6_16mhz_high_speed".
+//
+//    Commit your answers (bare6_2)
+//
+// 3. Now run the example in 64Mz
+//    You can do that by issuing a `monitor reset init`
+//    which reprograms SYSCLK to 4*HCI.
+//
+//
+//    Confirm that your ITM dump traces the init, idle and led on/off
+//    (make sure your TPIU is set to a system clock at 64Mhz)
+//
+//    Uncommnet: `let cycles = 4 * 8_000_000;
+//`
+//    What is the frequency of blinking?
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare6_3)
+//
+// 4. Repeat experiment 2
+//
+//    What is the frequency of MCO2 read by the oscilloscope?
+//
+//    ** your answer here **
+//
+//    Compute the value of SYSCLK based on the oscilloscope reading.
+//
+//    ** your answer here **
+//
+//    What is the peak to peak reading of the signal?
+//
+//    ** your answer here **
+//
+//    Make a screen dump or photo of the oscilloscope output.
+//    Save the the picture as "bare_6_64mhz_high_speed".
+//
+//    Commit your answers (bare6_4)
+//
+// 5. In the `clock_out` function, the setup of registers is done through
+//    setting bit-pattens manually, e.g. 
+//     rcc.cfgr
+//        .modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) });
+//
+//    However based on the vendor SVD file the svd2rust API provides  
+//    a better abstraction, based on pattern enums and functions.
+//
+//    To view the API you can generate documentation for your crate:
+//
+//    > cargo doc --features "stm32f4" --open
+//
+//    By searching for `mco2` you find the enumerations and functions.
+//    So here 
+//       `w.mco2().bits{0b00}` is equivalent to 
+//       `w.mco2().sysclk()` and improves readability. 
+//
+//    Replace all bit-patterns used by the function name equivalents.
+//
+//    Test that the application still runs as before.
+//
+//    Commit your code (bare6_4)
\ No newline at end of file
diff --git a/examples/bare7.rs b/examples/bare7.rs
new file mode 100644
index 0000000000000000000000000000000000000000..e43cd841e48101b123711a68b11d8762fbd99f56
--- /dev/null
+++ b/examples/bare7.rs
@@ -0,0 +1,240 @@
+//! bare7.rs
+//!
+//! Serial echo
+//!
+//! What it covers:
+//! - changing the clock using Rust code
+//! - working with the svd2rust API
+//! - working with the HAL (Hardware Abstraction Layer)
+//! - USART polling (blocking wait)
+
+#![deny(unsafe_code)]
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m::iprintln;
+use cortex_m_rt::entry;
+use nb::block;
+
+extern crate stm32f4xx_hal as hal;
+use crate::hal::prelude::*;
+use crate::hal::serial::{config::Config, Serial};
+
+#[entry]
+fn main() -> ! {
+    let mut c = hal::stm32::CorePeripherals::take().unwrap();
+    let stim = &mut c.ITM.stim[0];
+
+    let p = hal::stm32::Peripherals::take().unwrap();
+
+    let rcc = p.RCC.constrain();
+
+    // 16 MHz (default, all clocks)
+    let clocks = rcc.cfgr.freeze();
+    // 84 MHz (with valid config for pclk1 and pclk2)
+    // let clocks = rcc.cfgr.sysclk(84.mhz()).pclk1(42.mhz()).pclk2(84.mhz()).freeze();
+
+    let gpioa = p.GPIOA.split();
+
+    let tx = gpioa.pa2.into_alternate_af7();
+    let rx = gpioa.pa3.into_alternate_af7(); // try comment out
+                                             
+    // let rx = gpioa.pa3.into_alternate_af6(); // try uncomment
+
+    let serial = Serial::usart2(
+        p.USART2,
+        (tx, rx),
+        Config::default().baudrate(115_200.bps()),
+        clocks,
+    )
+    .unwrap();
+    iprintln!(stim, "bare7");
+
+    // Separate out the sender and receiver of the serial port
+    let (mut tx, mut rx) = serial.split();
+
+    loop {
+        match block!(rx.read()) {
+            Ok(byte) => {
+                iprintln!(stim, "Ok {:?}", byte);
+                tx.write(byte).unwrap();
+            }
+            Err(err) => {
+                iprintln!(stim, "Error {:?}", err);
+            }
+        }
+    }
+}
+
+// Optional assignment
+// 0. Background reading:
+//    STM32F401xD STM32F401xE, section 3.11
+//    We have two AMBA High-performance Bus (AHB)
+//    APB1 low speed bus (max freq 42 MHz)
+//    APB2 high speed bus (max frex 84 MHz)
+//
+//    RM0368 Section 6.2
+//    Some important/useful clock acronyms and their use:
+//
+//    SYSCLK - the clock that drives the `core`
+//    HCLK   - the clock that drives the AMBA bus(es), memory, DMA, trace unit, etc.
+//
+//    Typically we set HCLK = SYSCLK / 1 (no prescale) for our applications
+//
+//    FCLK   - Free running clock runing at HCLK
+//
+//    CST    - CoreSystemTimer drives the SysTick counter, HCLK/(1 or 8)
+//    PCLK1  - The clock driving the APB1 (<= 42 MHz)
+//             Timers on the APB1 bus will be triggered at PCLK1 * 2
+//    PCLK2  - The clock driving the APB2 (<= 84 MHz)
+//             Timers on the APB2 bus will be triggered at PCLK2
+//
+//    Compliation:
+//    > cargo build --example bare7 --features "stm32fxx-hal"
+//    (or use the vscode build task)
+//
+//
+//    Cargo.toml:
+//
+//    [dependencies.stm32f4]
+//    version = "0.5.0"
+//    features = ["stm32f413", "rt"]
+//    optional = true
+//
+//    [dependencies.stm32f4xx-hal]
+//    version         = "0.6.0"
+//    features        = ["stm32f401", "rt"]
+//    optional        = true
+//
+//    Notice, stm32f4xx-hal internally enables the dependency to stm32f4,
+//    so we don't need to explicitly enable it.
+//
+//    The HAL provides a generic abstraction over the whole stm32f4 family.
+//
+// 1. The rcc.cfgr.x.freeze() sets the clock according to the configuration x given.
+//
+//    rcc.cfgr.freeze(); sets a default configuration.
+//    sysclk = hclk = pclk1 = pclk2 = 16MHz
+//
+//    What is wrong with the following configurations?
+//
+//    rcc.cfgr.sysclk(64.mhz()).pclk1(64.mhz()).pclk2(64.mhz()).freeze();
+//
+//    ** your answer here **
+//
+//    rcc.cfgr.sysclk(84.mhz()).pclk1(42.mhz()).pclk2(64.mhz()).freeze();
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare7_1)
+//
+//    Tip: You may use `stm32cubemx` to get a graphical view for experimentation.
+//
+// 2. Now give the system with a valid clock, sysclk of 84 MHz.
+//
+//    Include the code for outputting the clock to MCO2.
+//
+//    Repeat the experiment bare6_2.
+//
+//    What is the frequency of MCO2 read by the oscilloscope.
+//
+//    ** your answer here **
+//
+//    Compute the value of SYSCLK based on the oscilloscope reading.
+//
+//    ** your answer here **
+//
+//    What is the peak to peak reading of the signal.
+//
+//    ** your answer here **
+//
+//    Make a screen dump or photo of the oscilloscope output.
+//    Save the the picture as "bare_7_84mhz_high_speed"
+//
+//    Commit your answers (bare7_2)
+//
+// 3. Now reprogram the PC9 to be "Low Speed", and re-run at 84Mz.
+//
+//    Did the frequency change in comparison to assignment 6?
+//
+//    ** your answer here **
+//
+//    What is the peak to peak reading of the signal (and why did it change)?
+//
+//    ** your answer here **
+//
+//    Make a screen dump or photo of the oscilloscope output.
+//    Save the the picture as "bare_7_84mhz_low_speed".
+//
+//    Commit your answers (bare7_3)
+//
+// 4. Revisit the `README.md` regarding serial communication.
+//    start a terminal program, e.g., `moserial`.
+//    Connect to the port
+//
+//    Device       /dev/ttyACM0
+//    Baude Rate   115200
+//    Data Bits    8
+//    Stop Bits    1
+//    Parity       None
+//
+//    This setting is typically abbreviated as 115200 8N1.
+//
+//    Run the example, make sure your ITM is set to 84MHz.
+//
+//    Send a single character (byte), (set the option No end in moserial).
+//    Verify that sent bytes are echoed back, and that ITM tracing is working.
+//
+//    If not go back check your ITM setting, clocks etc.
+//
+//    Try sending: "abcd" as a single sequence, don't send the quotation marks, just abcd.
+//
+//    What did you receive, and what was the output of the ITM trace.
+//
+//    ** your answer here **
+//
+//    commit your answers (bare7_4)
+//
+// 5. Now, set the CPU to run at 16MHz.
+//    Repeat the experiment 7.4 (make sure your ITM is set to 16MHz)
+//
+//    Try sending: "abcd" as a single sequence, don't send the quotation marks, just abcd.
+//
+//    What did you receive, and what was the output of the ITM trace.
+//
+//    ** your answer here **
+//
+//    Explain why the buffer overflows.
+//
+//    ** your answer here **
+//
+//    commit your answers (bare7_4)
+//
+//    Discussion:
+//    Common to all MCUs is that they have multiple clocking options.
+//    Understanding the possibilities and limitations of clocking is fundamental
+//    to designing both the embedded hardware and software. Tools like
+//    `stm32cubemx` can be helpful to give you the big picture.
+//
+//    The `stm32f4xx-hal` gives you an abstraction for programming,
+//    setting up clocks, assigning pins, etc.
+//
+//    The hal overs basic functionality like serial communication.
+//    Still, in order to fully understand what is going on under the hood you need to
+//    check the documentation (data sheets, user manuals etc.)
+//
+//    Your crate can be documented by:
+//
+//    > cargo doc --open --features "stm32f4xx-hal"
+//
+//    This will document both your crate and its dependencies besides the `core` library.
+//
+//    You can open the `core` library documentation by
+//
+//    > rustup doc
+//
+//    or just show the path to the doc (to open it manually)
+//
+//    > rustup doc --path
diff --git a/examples/bare8.rs b/examples/bare8.rs
new file mode 100644
index 0000000000000000000000000000000000000000..c902fe1b834b359b702ee4c5a3f3643c84621850
--- /dev/null
+++ b/examples/bare8.rs
@@ -0,0 +1,126 @@
+//! bare8.rs
+//!
+//! The RTFM framework
+//!
+//! What it covers:
+//! - utilizing the RTFM framework for serial communication
+//! - singletons (entities with a singe instance)
+//! - owned resources
+//! - peripheral access in RTFM
+//! - polling in `idle`
+
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m_semihosting::hprintln;
+use nb::block;
+
+extern crate stm32f4xx_hal as hal;
+use crate::hal::prelude::*;
+use crate::hal::serial::{config::Config, Rx, Serial, Tx};
+use hal::stm32::{ITM, USART2};
+
+use rtfm::app;
+
+#[app(device = hal::stm32, peripherals = true)]
+const APP: () = {
+    struct Resources {
+        // Late resources
+        TX: Tx<USART2>,
+        RX: Rx<USART2>,
+    }
+
+    // init runs in an interrupt free section
+    #[init]
+    fn init(cx: init::Context) -> init::LateResources {
+        let mut core = cx.core;
+        let device = cx.device;
+
+        hprintln!("bare8");
+
+        let rcc = device.RCC.constrain();
+
+        // 16 MHz (default, all clocks)
+        let clocks = rcc.cfgr.freeze();
+
+        let gpioa = device.GPIOA.split();
+
+        let tx = gpioa.pa2.into_alternate_af7();
+        let rx = gpioa.pa3.into_alternate_af7();
+
+        let serial = Serial::usart2(
+            device.USART2,
+            (tx, rx),
+            Config::default().baudrate(9_600.bps()),
+            clocks,
+        )
+        .unwrap();
+
+        // Separate out the sender and receiver of the serial port
+        let (tx, rx) = serial.split();
+
+        // Late resources
+        init::LateResources {
+            TX: tx,
+            RX: rx,
+        }
+    }
+
+    // idle may be interrupted by other interrupts/tasks in the system
+    #[idle(resources = [RX, TX])]
+    fn idle(cx: idle::Context) -> ! {
+        let rx = cx.resources.RX;
+        let tx = cx.resources.TX;
+
+        loop {
+            match block!(rx.read()) {
+                Ok(byte) => {
+                    hprintln!("Ok {:?}", byte);
+                    tx.write(byte).unwrap();
+                }
+                Err(err) => {
+                    hprintln!("Error {:?}", err);
+                }
+            }
+        }
+    }
+};
+
+// Optional assignment
+// 0. Compile and run the example. Notice, we use the default 16MHz clock.
+//
+//    > cargo build --example bare8 --features "rtfm"
+//    (or use the vscode build task)
+//
+// 1. What is the behavior in comparison to bare7.4 and bare7.5
+//
+//    ** your answer here **
+//
+//    Commit your answer (bare8_1)
+//
+// 2. Add a local variable `received` that counts the number of bytes received.
+//    Add a local variable `errors` that counts the number of errors.
+//
+//    Adjust the ITM trace to include the additional information.
+//
+//    Commit your development (bare8_2)
+//
+// 3. The added tracing, how did that effect the performance,
+//    (are you know loosing more data)?
+//
+//    ** your answer here **
+//
+//    Commit your answer (bare8_3)
+//
+// 4. *Optional
+//    Compile and run the program in release mode.
+//    If using vscode, look at the `.vscode` folder `task.json` and `launch.json`,
+//    you may need to add a new "profile" (a bit of copy paste).
+//
+//    How did the optimized build compare to the debug build (performance/lost bytes)
+//
+//    ** your answer here **
+//
+//    Commit your answer (bare8_4)
diff --git a/examples/bare9.rs b/examples/bare9.rs
new file mode 100644
index 0000000000000000000000000000000000000000..cf8a2c4ad67689aea6d043a845fd5e05b4e05a9b
--- /dev/null
+++ b/examples/bare9.rs
@@ -0,0 +1,248 @@
+//! bare9.rs
+//!
+//! Heapless
+//!
+//! What it covers:
+//! - Heapless Ringbuffer
+//! - Heapless Producer/Consumer lockfree data access
+//! - Interrupt driven I/O
+//!
+
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m::{asm, iprintln};
+
+extern crate stm32f4xx_hal as hal;
+use crate::hal::prelude::*;
+use crate::hal::serial::{config::Config, Event, Rx, Serial, Tx};
+use hal::stm32::ITM;
+
+use heapless::consts::*;
+use heapless::spsc::{Consumer, Producer, Queue};
+use nb::block;
+
+use rtfm::app;
+
+#[app(device = hal::stm32, peripherals = true)]
+const APP: () = {
+    struct Resources {
+        // Late resources
+        TX: Tx<hal::stm32::USART2>,
+        RX: Rx<hal::stm32::USART2>,
+        PRODUCER: Producer<'static, u8, U3>,
+        CONSUMER: Consumer<'static, u8, U3>,
+        ITM: ITM,
+        // An initialized resource
+        #[init(None)]
+        RB: Option<Queue<u8, U3>>,
+    }
+    // init runs in an interrupt free section
+    #[init(resources = [RB])]
+    fn init(cx: init::Context) -> init::LateResources {
+        let mut core = cx.core;
+        let device = cx.device;
+        // A ring buffer for our data
+        *cx.resources.RB = Some(Queue::new());
+
+        // Split into producer/consumer pair
+        let (producer, consumer) = cx.resources.RB.as_mut().unwrap().split();
+
+        let stim = &mut core.ITM.stim[0];
+        iprintln!(stim, "bare9");
+
+        let rcc = device.RCC.constrain();
+
+        // 16 MHz (default, all clocks)
+        let clocks = rcc.cfgr.freeze();
+
+        let gpioa = device.GPIOA.split();
+
+        let tx = gpioa.pa2.into_alternate_af7();
+        let rx = gpioa.pa3.into_alternate_af7();
+
+        let mut serial = Serial::usart2(
+            device.USART2,
+            (tx, rx),
+            Config::default().baudrate(115_200.bps()),
+            clocks,
+        )
+        .unwrap();
+
+        // generate interrupt on Rxne
+        serial.listen(Event::Rxne);
+        // Separate out the sender and receiver of the serial port
+        let (tx, rx) = serial.split();
+
+        // Late resources
+        init::LateResources {
+            // Our split queue
+            PRODUCER: producer,
+            CONSUMER: consumer,
+
+            // Our split serial
+            TX: tx,
+            RX: rx,
+
+            // For debugging
+            ITM: core.ITM,
+        }
+    }
+
+    // idle may be interrupted by other interrupt/tasks in the system
+    #[idle(resources = [ITM, CONSUMER])]
+    fn idle(cx: idle::Context) -> ! {
+        let stim = &mut cx.resources.ITM.stim[0];
+
+        loop {
+            while let Some(byte) = cx.resources.CONSUMER.dequeue() {
+                iprintln!(stim, "data {}", byte);
+            }
+
+            iprintln!(stim, "goto sleep");
+            asm::wfi();
+
+            iprintln!(stim, "woken..");
+        }
+    }
+
+    // task run on USART2 interrupt (set to fire for each byte received)
+    #[task(binds = USART2, resources = [RX, TX, PRODUCER])]
+    fn usart2(cx: usart2::Context) {
+        let rx = cx.resources.RX;
+        let tx = cx.resources.TX;
+
+        // at this point we know there must be a byte to read
+        match rx.read() {
+            Ok(byte) => {
+                tx.write(byte).unwrap();
+
+                match cx.resources.PRODUCER.enqueue(byte) {
+                    Ok(_) => {}
+                    Err(_) => asm::bkpt(),
+                }
+            }
+            Err(_err) => asm::bkpt(),
+        }
+    }
+};
+
+// Optional
+// 0. Compile and run the project at 16MHz in release mode
+//    make sure its running (not paused).
+//
+//    > cargo build --example bare9 --features "rtfm" --release
+//    (or use the vscode build task)
+//
+// 1. Start a terminal program, connect with 15200 8N1
+//
+//    You should now be able to send data and receive an echo from the MCU
+//
+//    Try sending: "abcd" as a single sequence (set the option No end in moserial),
+//    don't send the quotation marks, just abcd.
+//
+//    What did you receive, and what was the output of the ITM trace.
+//
+//    ** your answer here **
+//
+//    Did you experience any over-run errors?
+//
+//    ** your answer here **
+//
+//    Why does it behave differently than bare7/bare8?
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare9_1)
+//
+// 2. Compile and run the project at 16MHz in debug mode.
+//
+//    > cargo build --example bare9 --features "hal rtfm"
+//    (or use the vscode build task)
+//
+//    Try sending: "abcd" as a single sequence (set the option No end in moserial),
+//    don't send the quotation marks, just abcd.
+//
+//    What did you receive, and what was the output of the ITM trace.
+//
+//    ** your answer here **
+//
+//    Did you experience any over-run errors?
+//
+//    ** your answer here **
+//
+//    Why does it behave differently than in release mode?
+//    Recall how the execution overhead changed with optimization level.
+//
+//    ** your answer here **
+//
+//    Commit your answers (bare9_2)
+//
+//    Discussion:
+//
+//    The concurrency model behind RTFM offers
+//    1. Race-free resource access
+//
+//    2. Deadlock-free execution
+//
+//    3. Shared execution stack (no pre-allocated stack regions)
+//
+//    4. Bound priority inversion
+//
+//    5. Theoretical underpinning ->
+//       + (pen and paper) proofs of soundness
+//       + schedulability analysis
+//       + response time analysis
+//       + stack memory analysis
+//       + ... leverages on >25 years of research in the real-time community
+//         based on the seminal work of Baker in the early 1990s
+//         (known as the Stack Resource Policy, SRP)
+//
+//    Our implementation in Rust offers
+//    1. compile check and analysis of tasks and resources
+//       + the API implementation together with the Rust compiler will ensure that
+//          both RTFM (SRP) soundness and the Rust memory model invariants
+//          are upheld (under all circumstances).
+//
+//    2. arguably the worlds fastest real time scheduler *
+//       + task invocation 0-cycle OH on top of HW interrupt handling
+//       + 2 cycle OH for locking a shared resource (on lock/claim entry)
+//       + 1 cycle OH for releasing a shared resource (on lock/claim exit)
+//
+//    3. arguably the worlds most memory efficient scheduler *
+//       + 1 byte stack memory OH for each (nested) lock/claim
+//         (no additional book-keeping during run-time)
+//
+//       * applies to static task/resource models with single core
+//         pre-emptive, static priority scheduling
+//
+//    In comparison "real-time" schedulers for threaded models (like FreeRTOS)
+//       - CPU and memory OH magnitudes larger 
+//       - ... and what's worse OH is typically unbound (no proofs of worst case)
+//    And additionally threaded models typically imposes
+//       - potential race conditions (up to the user to verify)
+//       - potential dead-locks (up to the implementation)
+//       - potential unbound priority inversion (up to the implementation)
+//
+//    However, Rust RTFM (currently) target ONLY STATIC SYSTEMS, 
+//    there is no notion of dynamically creating new executions contexts/threads
+//    so a direct comparison is not completely fair.
+//
+//    On the other hand, embedded applications are typically static by nature
+//    so a STATIC model is to that end better suitable.
+//
+//    RTFM is reactive by nature, a task execute to end, triggered
+//    by an internal or external event, (where an interrupt is an external event
+//    from the environment, like a HW peripheral such as the USART2).
+//
+//    Threads on the other hand are concurrent and infinite by nature and
+//    actively blocking/yielding awaiting stischedulers
+//    The scheduler then needs to keep track of all threads and at some point choose
+//    to dispatch the awaiting thread. So reactivity is bottle-necked to the point
+//    of scheduling by queue management, context switching and other additional
+//    book keeping.
+//
+//    In essence, the thread scheduler tries to re-establish the reactivity that
+//    were there from the beginning (interrupts), a battle that cannot be won...
diff --git a/examples/rtfm_blinky_sw_reset.rs b/examples/rtfm_blinky_sw_reset.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bf8367568a1420cbb0f02a1e8dbdfc622fdd8aad
--- /dev/null
+++ b/examples/rtfm_blinky_sw_reset.rs
@@ -0,0 +1,73 @@
+#![deny(unsafe_code)]
+// #![deny(warnings)]
+#![no_main]
+#![no_std]
+
+use cortex_m;
+use cortex_m::peripheral::DWT;
+use panic_halt as _;
+use rtfm::cyccnt::U32Ext;
+use stm32f4xx_hal::stm32;
+
+#[rtfm::app(device = stm32f4xx_hal::stm32, monotonic = rtfm::cyccnt::CYCCNT, peripherals = true)]
+const APP: () = {
+    #[init(schedule = [toggle])]
+    fn init(cx: init::Context) {
+        let mut core = cx.core;
+        let device = cx.device;
+
+        // Initialize (enable) the monotonic timer (CYCCNT)
+        core.DCB.enable_trace();
+        // required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7)
+        DWT::unlock();
+        core.DWT.enable_cycle_counter();
+
+        // 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
+
+        // power on GPIOA, RM0368 6.3.11
+        device.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+        // configure PA5 as output, RM0368 8.4.1
+        device.GPIOA.moder.modify(|_, w| w.moder5().bits(1));
+
+        cx.schedule
+            .toggle(now + 8_000_000.cycles(), true, device.GPIOA, core.SCB, 1)
+            .ok();
+    }
+
+    #[task(schedule= [toggle])]
+    fn toggle(
+        cx: toggle::Context,
+        toggle: bool,
+        gpioa: stm32::GPIOA,
+        mut scb: stm32::SCB,
+        mut state: u8,
+    ) {
+        if toggle {
+            gpioa.bsrr.write(|w| w.bs5().set_bit());
+        } else {
+            gpioa.bsrr.write(|w| w.br5().set_bit());
+        }
+
+        state += 1;
+        if state == 10 {
+            //state = 0;
+            //            scb.system_reset();
+            cortex_m::peripheral::SCB::sys_reset();
+        };
+        cx.schedule
+            .toggle(
+                cx.scheduled + (state as u32 * 400_000).cycles(),
+                !toggle,
+                gpioa,
+                scb,
+                state,
+            )
+            .ok();
+    }
+
+    extern "C" {
+        fn EXTI0();
+    }
+};