diff --git a/examples/bare4.rs b/examples/bare4.rs
index 1cf587d5a5affc069208ce87e6ba25775f4f8380..08d633ec001e1f60aa68e48a1acab31a1307f031 100644
--- a/examples/bare4.rs
+++ b/examples/bare4.rs
@@ -7,22 +7,25 @@
 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;
+// Peripheral addresses as constants
+const PERIPH_BASE: u32 = 0x40000000;
+const AHB1PERIPH_BASE: u32 = PERIPH_BASE + 0x00020000;
+const RCC_BASE: u32 = AHB1PERIPH_BASE + 0x3800;
+const RCC_AHB1ENR: u32 = RCC_BASE + 0x30;
+const GBPIA_BASE: u32 = AHB1PERIPH_BASE + 0x0000;
+const GPIOA_MODER: u32 = GBPIA_BASE + 0x00;
+const GPIOA_BSRR: u32 = GBPIA_BASE + 0x18;
 
 // 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 _) }
 }
 
+#[inline(always)]
 fn write_u32(addr: u32, val: u32) {
     unsafe {
         core::ptr::write_volatile(addr as *mut _, val);
@@ -36,14 +39,12 @@ fn wait(i: u32) {
 }
 
 fn main() {
-    // // power on GPIOA, RM0368 6.3.11
-    // p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+    // power on GPIOA, RM0368 6.3.11
 
-    let r = read_u32(RCC_AHPB1ENR); // read
-    write_u32(RCC_AHPB1ENR, r | 1 << (0)); // set enable
+    let r = read_u32(RCC_AHB1ENR); // read
+    write_u32(RCC_AHB1ENR, r | 1); // set enable
 
-    // // configure PA5 as output, RM0368 8.4.1
-    // p.GPIOA.moder.modify(|_, w| w.moder5().bits(1));
+    // configure PA5 as output, RM0368 8.4.1
     let r = read_u32(GPIOA_MODER) & !(0b11 << (5 * 2)); // read and mask
     write_u32(GPIOA_MODER, r | 0b01 << (5 * 2)); // set output mode
 
@@ -53,11 +54,11 @@ fn main() {
 
     loop {
         // set PA5 high, RM0368 8.4.7
-        write_u32(GPIOA_BSRR, r | 1 << 5); // set output mode
+        write_u32(GPIOA_BSRR, 1 << 5); // set bit, output hight (turn on led)
         wait(10_000);
 
         // set PA5 low, RM0368 8.4.7
-        write_u32(GPIOA_BSRR, r | 1 << (5 + 16)); // set output mode
+        write_u32(GPIOA_BSRR, 1 << (5 + 16)); // clear bit, output low (turn off led)
         wait(10_000);
     }
 }
diff --git a/examples/bare5.rs b/examples/bare5.rs
new file mode 100644
index 0000000000000000000000000000000000000000..29f6744f9b76d034d9691d96bc0c71912d8083fd
--- /dev/null
+++ b/examples/bare5.rs
@@ -0,0 +1,166 @@
+//! bare4.rs
+//! Simple bare metal application
+//!
+#![feature(used)]
+#![feature(custom_attribute)]
+#![no_std]
+
+extern crate cortex_m;
+extern crate cortex_m_rt;
+
+// #[macro_use]
+// extern crate cortex_m_debug;
+
+mod stm32f40x {
+    use core::{cell, ptr};
+
+    // C like API...
+    const PERIPH_BASE: u32 = 0x40000000;
+    const AHB1PERIPH_BASE: u32 = PERIPH_BASE + 0x00020000;
+    const RCC_BASE: u32 = AHB1PERIPH_BASE + 0x3800;
+    const GPIOA_BASE: u32 = AHB1PERIPH_BASE;
+
+    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) }
+        }
+    }
+
+    #[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 {
+            RCC_BASE as *mut RCC
+        }
+    }
+
+    #[repr(C)]
+    #[allow(non_snake_case)]
+    #[rustfmt_skip]
+    pub struct GPIOA {
+        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 MODER:      VolatileCell<u32>,      // < GPIO port mode register,               Address offset: 0x00      */
+        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>],    // < GPIO alternate function registers,     Address offset: 0x20-0x24 */
+    }
+
+    // impl GPIOA {
+    //     pub fn get() -> *mut GPIOA {
+    //         GPIOA_BASE as *mut GPIOA
+    //     }
+    // }
+
+    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)
+    }
+}
+
+fn main() {
+    // // power on GPIOA, RM0368 6.3.11
+    // p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+
+    let rcc = RCC::get(); // get the reference to the Rcc in memory
+    unsafe {
+        let r = (*rcc).AHB1ENR.read(); // read
+        (*rcc).AHB1ENR.write(r | 1 << (0)); // set enable
+    }
+
+    // configure PA5 as output, RM0368 8.4.1
+    // let gpioa = GPIOA::get();
+    // unsafe {
+    //     let r = (*gpioa).MODER.read() & !(0b11 << (5 * 2)); // read and mask
+    //     (*gpioa).MODER.write(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
+    //         (*gpioa).BSRRH.write(1 << 5); // set bit, output hight (turn on led)
+    //         wait(10_000);
+
+    //         // set PA5 low, RM0368 8.4.7
+    //         (*gpioa).BSRRH.write(1 << 5); // clear bit, output low (turn off led)
+    //         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();
+}