diff --git a/.vscode/launch.json b/.vscode/launch.json
index 822733975745f91aebca8adc45f67da9da4e1e3e..3ff1ffe70c09208c57b589d1e8a2d7ad7f893150 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -76,5 +76,95 @@
             ],
             "cwd": "${workspaceRoot}"
         },
+        {
+            "type": "gdb",
+            "request": "attach",
+            "name": "gpio_raw",
+            "gdbpath": "/usr/bin/arm-none-eabi-gdb",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/gpio_raw",
+            "target": ":3333",
+            "remote": true,
+            "autorun": [
+                "monitor reset init",
+                "monitor arm semihosting enable",
+                "monitor tpiu config internal /tmp/itm.log uart off 64000000",
+                "monitor itm port 0 on",
+                "load",
+                "monitor reset init"
+            ],
+            "cwd": "${workspaceRoot}"
+        },
+        {
+            "type": "gdb",
+            "request": "attach",
+            "name": "bare1",
+            "gdbpath": "/usr/bin/arm-none-eabi-gdb",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare1",
+            "target": ":3333",
+            "remote": true,
+            "autorun": [
+                "monitor reset init",
+                "monitor arm semihosting enable",
+                "monitor tpiu config internal /tmp/itm.log uart off 64000000",
+                "monitor itm port 0 on",
+                "load",
+                "monitor reset init"
+            ],
+            "cwd": "${workspaceRoot}"
+        },
+        {
+            "type": "gdb",
+            "request": "attach",
+            "name": "bare2",
+            "gdbpath": "/usr/bin/arm-none-eabi-gdb",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare2",
+            "target": ":3333",
+            "remote": true,
+            "autorun": [
+                "monitor reset init",
+                "monitor arm semihosting enable",
+                "monitor tpiu config internal /tmp/itm.log uart off 64000000",
+                "monitor itm port 0 on",
+                "load",
+                "monitor reset init"
+            ],
+            "cwd": "${workspaceRoot}"
+        },
+        {
+            "type": "gdb",
+            "request": "attach",
+            "name": "bare3",
+            "gdbpath": "/usr/bin/arm-none-eabi-gdb",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare3",
+            "target": ":3333",
+            "remote": true,
+            "autorun": [
+                "monitor reset init",
+                "monitor arm semihosting enable",
+                "monitor tpiu config internal /tmp/itm.log uart off 64000000",
+                "monitor itm port 0 on",
+                "load",
+                "monitor reset init"
+            ],
+            "cwd": "${workspaceRoot}"
+        },
+        {
+            "type": "gdb",
+            "request": "attach",
+            "name": "bare4",
+            "gdbpath": "/usr/bin/arm-none-eabi-gdb",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare4",
+            "target": ":3333",
+            "remote": true,
+            "autorun": [
+                "monitor reset init",
+                "monitor arm semihosting enable",
+                "monitor tpiu config internal /tmp/itm.log uart off 64000000",
+                "monitor itm port 0 on",
+                "load",
+                "monitor reset init"
+            ],
+            "cwd": "${workspaceRoot}"
+        },
     ]
 }
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index d2d5a4664d418c9789dc34933231b4ab644f4fc1..760e36e48ef828d6684034a1aafa7d04ec45a8de 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -51,5 +51,65 @@
                 "isDefault": true
             }
         },
+        {
+            "type": "shell",
+            "label": "xargo build --example gpio_raw",
+            "command": "xargo build --example gpio_raw",
+            "problemMatcher": [
+                "$rustc"
+            ],
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
+        {
+            "type": "shell",
+            "label": "xargo build --example bare1",
+            "command": "xargo build --example bare1",
+            "problemMatcher": [
+                "$rustc"
+            ],
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
+        {
+            "type": "shell",
+            "label": "xargo build --example bare2",
+            "command": "xargo build --example bare2",
+            "problemMatcher": [
+                "$rustc"
+            ],
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
+        {
+            "type": "shell",
+            "label": "xargo build --example bare3",
+            "command": "xargo build --example bare3",
+            "problemMatcher": [
+                "$rustc"
+            ],
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
+        {
+            "type": "shell",
+            "label": "xargo build --example bare4",
+            "command": "xargo build --example bare4",
+            "problemMatcher": [
+                "$rustc"
+            ],
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
     ]
 }
\ No newline at end of file
diff --git a/examples/bare1.rs b/examples/bare1.rs
new file mode 100644
index 0000000000000000000000000000000000000000..16931d37ea55359086f33d852a9765de0ae575b8
--- /dev/null
+++ b/examples/bare1.rs
@@ -0,0 +1,41 @@
+//! bare1.rs
+//! Simple bare metal application
+
+// feature to ensure symbols to be linked
+#![feature(used)]
+// build without the Rust standard library
+#![no_std]
+
+// API to the ARM Cortex M Peripherals
+extern crate cortex_m;
+
+// Minimal runtime / startup for Cortex-M microcontrollers
+extern crate cortex_m_rt;
+
+// Convenient tracing over semihosting and ITM
+#[macro_use]
+extern crate cortex_m_debug;
+
+#[inline(never)]
+fn main() {
+    // ITM trace (fast)
+    // start `itmdump` before `openocd`
+    ipln!("ITM: Hello World");
+
+    // semihosting trace (slow)
+    sprintln!("SEMIHOSTING: Hello World");
+
+    // to prevent returning
+    loop {
+        cortex_m::asm::nop();
+    }
+}
+
+// As we are not using interrupts, we just register a dummy catch all handler
+#[link_section = ".vector_table.interrupts"]
+#[used]
+static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
+
+extern "C" fn default_handler() {
+    cortex_m::asm::bkpt();
+}
diff --git a/examples/bare2.rs b/examples/bare2.rs
new file mode 100644
index 0000000000000000000000000000000000000000..bf49b9243f1e1c2919b7068a0a8379e18ab2af22
--- /dev/null
+++ b/examples/bare2.rs
@@ -0,0 +1,40 @@
+//! bare2.rs
+//! Simple bare metal application
+#![feature(used)]
+#![no_std]
+
+extern crate cortex_m;
+extern crate cortex_m_rt;
+
+#[macro_use]
+extern crate cortex_m_debug;
+
+// burns CPU cycles by just looping `i` times
+fn wait(i: u32) {
+    for _ in 0..i {
+        // no operation (ensured not optimized out)
+        cortex_m::asm::nop();
+    }
+}
+
+fn main() {
+    ipln!("Start");
+
+    // a "mutable" (changeable) variable
+    let mut s = 0;
+
+    loop {
+        ipln!("s = {}", s);
+        s += 1;
+        wait(100_000);
+    }
+}
+
+// As we are not using interrupts, we just register a dummy catch all handler
+#[link_section = ".vector_table.interrupts"]
+#[used]
+static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
+
+extern "C" fn default_handler() {
+    cortex_m::asm::bkpt();
+}
diff --git a/examples/bare3.rs b/examples/bare3.rs
new file mode 100644
index 0000000000000000000000000000000000000000..964a4fb9da7b2350eca6d51511997f38feff3c14
--- /dev/null
+++ b/examples/bare3.rs
@@ -0,0 +1,33 @@
+//! bare3.rs
+//! Simple bare metal application
+//!
+#![feature(used)]
+#![no_std]
+
+extern crate cortex_m;
+extern crate cortex_m_rt;
+
+#[macro_use]
+extern crate cortex_m_debug;
+
+fn main() {
+    let s = "ABCD";
+    ipln!("s = {:?}", s);
+
+    // iterate over the byte repr. of s
+    for c in s.as_bytes() {
+        ip!("{},", c)
+    }
+
+    ipln!();
+    loop {}
+}
+
+// As we are not using interrupts, we just register a dummy catch all handler
+#[link_section = ".vector_table.interrupts"]
+#[used]
+static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
+
+extern "C" fn default_handler() {
+    cortex_m::asm::bkpt();
+}
diff --git a/examples/bare4.rs b/examples/bare4.rs
new file mode 100644
index 0000000000000000000000000000000000000000..1cf587d5a5affc069208ce87e6ba25775f4f8380
--- /dev/null
+++ b/examples/bare4.rs
@@ -0,0 +1,72 @@
+//! bare4.rs
+//! Simple bare metal application
+//!
+#![feature(used)]
+#![no_std]
+
+extern crate cortex_m;
+extern crate cortex_m_rt;
+
+#[macro_use]
+extern crate cortex_m_debug;
+
+const RCC_AHPB1ENR: u32 = 0x4002_3810;
+const GPIOA_MODER: u32 = 0x4002_0000;
+//const GPIOA_ODR: u32 = 0x4002_0014;
+const GPIOA_BSRR: u32 = 0x4002_0018;
+
+// see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
+// rcc,     chapter 6
+// gpio,    chapter 8
+
+fn read_u32(addr: u32) -> u32 {
+    unsafe { core::ptr::read_volatile(addr as *const _) }
+}
+
+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)
+    }
+}
+
+fn main() {
+    // // power on GPIOA, RM0368 6.3.11
+    // p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+
+    let r = read_u32(RCC_AHPB1ENR); // read
+    write_u32(RCC_AHPB1ENR, r | 1 << (0)); // set enable
+
+    // // configure PA5 as output, RM0368 8.4.1
+    // p.GPIOA.moder.modify(|_, w| w.moder5().bits(1));
+    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 (in modify)
+    // is not needed.
+
+    loop {
+        // set PA5 high, RM0368 8.4.7
+        write_u32(GPIOA_BSRR, r | 1 << 5); // set output mode
+        wait(10_000);
+
+        // set PA5 low, RM0368 8.4.7
+        write_u32(GPIOA_BSRR, r | 1 << (5 + 16)); // set output mode
+        wait(10_000);
+    }
+}
+
+// As we are not using interrupts, we just register a dummy catch all handler
+#[link_section = ".vector_table.interrupts"]
+#[used]
+static INTERRUPTS: [extern "C" fn(); 240] = [default_handler; 240];
+
+extern "C" fn default_handler() {
+    cortex_m::asm::bkpt();
+}
diff --git a/examples/gpio_raw.rs b/examples/gpio_raw.rs
new file mode 100644
index 0000000000000000000000000000000000000000..75e6c59035121f8e6f08d35122becf9ea4d40832
--- /dev/null
+++ b/examples/gpio_raw.rs
@@ -0,0 +1,78 @@
+//! Simple access to gpio
+
+// build without the Rust standard library
+#![no_std]
+
+// API to the ARM Cortex M Peripherals
+extern crate cortex_m;
+
+// API to the ST stm32f401x Micro controller
+extern crate stm32f40x;
+
+// Convenient tracing over semihosting and ITM
+#[macro_use]
+extern crate cortex_m_debug;
+
+fn main() {
+    ipln!("ITM: Hello World");
+    sprintln!("SEMIHOSTING: Hello World");
+
+    // to prevent returning
+    loop {}
+}
+
+// use rtfm::app;
+
+// app! {
+//     device: stm32f40x,
+// }
+
+// fn wait(i: u32) {
+//     for _ in 0..i {
+//         cortex_m::asm::nop(); // no operation (cannot be optimized out)
+//     }
+// }
+
+// // see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
+// // rcc,     chapter 6
+// // gpio,    chapter 8
+
+// fn init(p: init::Peripherals) {
+//     // power on GPIOA, RM0368 6.3.11
+//     p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+
+//     // configure PA5 as output, RM0368 8.4.1
+//     p.GPIOA.moder.modify(|_, w| w.moder5().bits(1));
+
+//     // loop {
+//     //     // set PA5 high, RM0368 8.4.6
+//     //     p.GPIOA.odr.modify(|_, w| w.odr5().bit(true));
+//     //     wait(10_000);
+
+//     //     // set PA5 low, RM0368 8.4.6
+//     //     p.GPIOA.odr.modify(|_, w| w.odr5().bit(false));
+//     //     wait(10_000);
+//     // }
+
+//     // rewrite the above code to have the GPIO as output
+//     // and alter the data output through the BSRR register
+//     // this is more efficient as the read register (in modify)
+//     // is not needed.
+
+//     loop {
+//         // set PA5 high, RM0368 8.4.7
+//         p.GPIOA.bsrr.write(|w| w.bs5().set_bit());
+//         wait(10_000);
+
+//         // set PA5 low, RM0368 8.4.7
+//         p.GPIOA.bsrr.write(|w| w.br5().set_bit());
+//         wait(10_000);
+//     }
+// }
+
+// #[inline(never)]
+// fn idle() -> ! {
+//     loop {
+//         rtfm::wfi();
+//     }
+// }