diff --git a/.gdbinit b/.gdbinit
index 20081866bdcb03873b40bed200d1603d076ebd67..85aae410edf40562cf3261c60d80015e13638ff8 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -1,6 +1,6 @@
 target remote :3333
 
-# monitor arm semihosting enable
+monitor arm semihosting enable
 
 # # send captured ITM to the file itm.fifo
 # # (the microcontroller SWO pin must be connected to the programmer SWO pin)
diff --git a/Cargo.toml b/Cargo.toml
index a3beb7788358341d2f20dbb122474c61a8cd7ee1..3e6c0c7ffb97ae92ab4b83b908cb3641a22cfa95 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,9 +5,9 @@ description = "Board Support Crate for the STM32F3DISCOVERY"
 documentation = "https://docs.rs/f3"
 keywords = ["arm", "cortex-m", "stm32"]
 license = "MIT OR Apache-2.0"
-name = "f3"
+name = "f4"
 repository = "https://github.com/japaric/f3"
-version = "0.5.0"
+version = "0.1.0"
 
 [dependencies]
 static-ref = "0.2.0"
@@ -23,9 +23,10 @@ rev = "7d904f515d15fd5fe7ea34e18820ea83e2651fa2"
 [dependencies.nb]
 git = "https://github.com/japaric/nb"
 
-[dependencies.stm32f30x]
+[dependencies.stm32f40x]
 features = ["rt"]
-version = "0.5.0"
+#version = "0.5.0"
+git = "https://gitlab.henriktjader.com/pln/STM32F40x"
 
 [dev-dependencies]
 cortex-m = "0.3.0"
diff --git a/README.md b/README.md
index 9dbc32f2ef778435509f6bbf55830e08fcc2b796..561b8683dcfeb9c30caecb6ea541e829299fb158 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,8 @@
-[![Build status](https://travis-ci.org/japaric/f3.svg?branch=master)](https://travis-ci.org/japaric/f3)
-[![crates.io](https://img.shields.io/crates/d/f3.svg)](https://crates.io/crates/f3)
-[![crates.io](https://img.shields.io/crates/v/f3.svg)](https://crates.io/crates/f3)
+# `f4`
 
-# `f3`
+> Board Support Crate for the NUCLEO-F411RE
 
-> Board Support Crate for the STM32F3DISCOVERY
-
-[STM32F3DISCOVERY]: http://www.st.com/en/evaluation-tools/stm32f3discovery.html
+[NUCLEO-F411RE]: http://www.st.com/en/evaluation-tools/nucleo-f411re.html
 
 ## [Documentation](https://docs.rs/f3)
 
diff --git a/examples/blinky.rs b/examples/blinky.rs
index eb12f7dd47876ab055a0cfab1e059688d5766807..f048a4e867d74dec04d19d9a88058d5d056f4476 100644
--- a/examples/blinky.rs
+++ b/examples/blinky.rs
@@ -4,12 +4,12 @@
 #![feature(proc_macro)]
 #![no_std]
 
-extern crate f3;
+extern crate f4;
 extern crate cortex_m;
 extern crate cortex_m_rtfm as rtfm;
 
 use cortex_m::peripheral::SystClkSource;
-use f3::led::{self, LEDS};
+use f4::led::{self, LEDS};
 use rtfm::{app, Threshold};
 
 // CONFIGURATION
@@ -17,7 +17,7 @@ const FREQUENCY: u32 = 4; // Hz
 
 // TASKS & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 
     resources: {
         static ON: bool = false;
@@ -33,10 +33,10 @@ app! {
 
 // INITIALIZATION PHASE
 fn init(p: init::Peripherals, _r: init::Resources) {
-    led::init(p.GPIOE, p.RCC);
+    led::init(p.GPIOA, p.RCC);
 
     p.SYST.set_clock_source(SystClkSource::Core);
-    p.SYST.set_reload(8_000_000 / FREQUENCY);
+    p.SYST.set_reload(16_000_000 / FREQUENCY);
     p.SYST.enable_interrupt();
     p.SYST.enable_counter();
 }
diff --git a/examples/concurrency.rs b/examples/concurrency.rs
index 45739ba6a7d364f61a6bf9619e1364ece6fd856d..44058a57fe60adb56292bb48e821d3df81e16b43 100644
--- a/examples/concurrency.rs
+++ b/examples/concurrency.rs
@@ -7,13 +7,13 @@
 extern crate cast;
 extern crate cortex_m;
 extern crate cortex_m_rtfm as rtfm;
-extern crate f3;
+extern crate f4;
 
-use f3::Serial;
-use f3::led::{self, LEDS};
-use f3::prelude::*;
-use f3::serial::Event;
-use f3::time::Hertz;
+use f4::Serial;
+use f4::led::{self, LEDS};
+use f4::prelude::*;
+use f4::serial::Event;
+use f4::time::Hertz;
 use cortex_m::peripheral::SystClkSource;
 use cast::{usize, u8};
 use rtfm::{app, Threshold};
@@ -25,7 +25,7 @@ const DIVISOR: u32 = 4;
 
 // TASKS & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 
     resources: {
         static STATE: u8 = 0;
@@ -37,23 +37,23 @@ app! {
             resources: [STATE],
         },
 
-        USART1_EXTI25: {
+        USART2: {
             path: loopback,
-            resources: [USART1],
+            resources: [USART2],
         },
     }
 }
 
 // INITIALIZATION PHASE
 fn init(p: init::Peripherals, _r: init::Resources) {
-    led::init(p.GPIOE, p.RCC);
+    led::init(p.GPIOA, p.RCC);
 
-    let serial = Serial(p.USART1);
+    let serial = Serial(p.USART2);
     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
     serial.listen(Event::Rxne);
 
     p.SYST.set_clock_source(SystClkSource::Core);
-    p.SYST.set_reload(8_000_000 / DIVISOR);
+    p.SYST.set_reload(16_000_000 / DIVISOR);
     p.SYST.enable_interrupt();
     p.SYST.enable_counter();
 }
@@ -67,8 +67,8 @@ fn idle() -> ! {
 }
 
 // TASKS
-fn loopback(_t: &mut Threshold, r: USART1_EXTI25::Resources) {
-    let serial = Serial(&**r.USART1);
+fn loopback(_t: &mut Threshold, r: USART2::Resources) {
+    let serial = Serial(&**r.USART2);
 
     if let Ok(byte) = serial.read() {
         if serial.write(byte).is_err() {
diff --git a/examples/hello.rs b/examples/hello.rs
index 24e2fc3b4c2216bdb87c25c52a489729f7969229..cd6a36549f58257ca56b830121be882f1f08559c 100644
--- a/examples/hello.rs
+++ b/examples/hello.rs
@@ -6,7 +6,7 @@
 
 extern crate cortex_m_rtfm as rtfm;
 extern crate cortex_m_semihosting as semihosting;
-extern crate f3;
+extern crate f4;
 
 use core::fmt::Write;
 
@@ -15,7 +15,7 @@ use semihosting::hio;
 
 // TASKS & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 }
 
 // INITIALIZATION PHASE
diff --git a/examples/itm.rs b/examples/itm.rs
index d791d3c401a99f0869e7bc1088951d1a649f77fe..822b6c8c404f731767fe349402c5342534d5d65e 100644
--- a/examples/itm.rs
+++ b/examples/itm.rs
@@ -12,13 +12,13 @@
 #[macro_use]
 extern crate cortex_m;
 extern crate cortex_m_rtfm as rtfm;
-extern crate f3;
+extern crate f4;
 
 use rtfm::{app, Threshold};
 
 // TASK & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 
     idle: {
         resources: [ITM],
diff --git a/examples/led.rs b/examples/led.rs
index 0a647850f2ef3a4d5e2e31814a05404727f57035..fca8d7b03aab39eed519930f1622bb62b72f625d 100644
--- a/examples/led.rs
+++ b/examples/led.rs
@@ -5,19 +5,19 @@
 #![no_std]
 
 extern crate cortex_m_rtfm as rtfm;
-extern crate f3;
+extern crate f4;
 
-use f3::led::{self, LEDS};
+use f4::led::{self, LEDS};
 use rtfm::app;
 
 // TASKS & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 }
 
 // INITIALIZATION PHASE
 fn init(p: init::Peripherals) {
-    led::init(&p.GPIOE, &p.RCC);
+    led::init(&p.GPIOA, &p.RCC);
 }
 
 // IDLE LOOP
diff --git a/examples/loopback.rs b/examples/loopback.rs
index bb345e03d26b4e505090d7fcb082431c87f13970..df1d2f50276d4c98e18850d4b0caad018fd59049 100644
--- a/examples/loopback.rs
+++ b/examples/loopback.rs
@@ -5,12 +5,12 @@
 #![no_std]
 
 extern crate cortex_m_rtfm as rtfm;
-extern crate f3;
+extern crate f4;
 
-use f3::prelude::*;
-use f3::Serial;
-use f3::serial::Event;
-use f3::time::Hertz;
+use f4::prelude::*;
+use f4::Serial;
+use f4::serial::Event;
+use f4::time::Hertz;
 use rtfm::{app, Threshold};
 
 // CONFIGURATION
@@ -18,19 +18,19 @@ const BAUD_RATE: Hertz = Hertz(115_200);
 
 // TASKS & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 
     tasks: {
-        USART1_EXTI25: {
+        USART2: {
             path: loopback,
-            resources: [USART1],
+            resources: [USART2],
         },
     }
 }
 
 // INITIALIZATION PHASE
 fn init(p: init::Peripherals) {
-    let serial = Serial(p.USART1);
+    let serial = Serial(p.USART2);
 
     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
     serial.listen(Event::Rxne);
@@ -46,8 +46,8 @@ fn idle() -> ! {
 
 // TASKS
 // Send back the received byte
-fn loopback(_t: &mut Threshold, r: USART1_EXTI25::Resources) {
-    let serial = Serial(&**r.USART1);
+fn loopback(_t: &mut Threshold, r: USART2::Resources) {
+    let serial = Serial(&**r.USART2);
 
     let byte = serial.read().unwrap();
     serial.write(byte).unwrap();
diff --git a/examples/preemption.rs b/examples/preemption.rs
index 2a193e698d11a3e6f6ac9faff4594bf091c38b27..d8937a75d7cd28e4c0e752082d32e997dc7040c0 100644
--- a/examples/preemption.rs
+++ b/examples/preemption.rs
@@ -15,18 +15,18 @@
 extern crate cast;
 extern crate cortex_m;
 extern crate cortex_m_rtfm as rtfm;
-extern crate f3;
+extern crate f4;
 extern crate heapless;
 
 use cast::{usize, u8};
 use cortex_m::peripheral::SystClkSource;
-use f3::Serial;
-use f3::led::{self, LEDS};
-use f3::prelude::*;
-use f3::serial::Event;
+use f4::Serial;
+use f4::led::{self, LEDS};
+use f4::prelude::*;
+use f4::serial::Event;
 use heapless::Vec;
 use rtfm::{app, Resource, Threshold};
-use f3::time::Hertz;
+use f4::time::Hertz;
 
 // CONFIGURATION
 const BAUD_RATE: Hertz = Hertz(115_200);
@@ -34,7 +34,7 @@ const DIVISOR: u32 = 4;
 
 // TASK & RESOURCES
 app!{
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 
     resources: {
         static BUFFER: Vec<u8, [u8; 16]> = Vec::new([0; 16]);
@@ -43,10 +43,10 @@ app!{
     },
 
     tasks: {
-        USART1_EXTI25: {
+        USART2: {
             path: receive,
             priority: 1,
-            resources: [BUFFER, SHARED, USART1],
+            resources: [BUFFER, SHARED, USART2],
         },
 
         SYS_TICK: {
@@ -59,9 +59,9 @@ app!{
 
 // INITIALIZATION PHASE
 fn init(p: init::Peripherals, _r: init::Resources) {
-    led::init(&p.GPIOE, &p.RCC);
+    led::init(&p.GPIOA, &p.RCC);
 
-    let serial = Serial(p.USART1);
+    let serial = Serial(p.USART2);
     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
     serial.listen(Event::Rxne);
 
@@ -80,8 +80,8 @@ fn idle() -> ! {
 }
 
 // TASKS
-fn receive(t: &mut Threshold, mut r: USART1_EXTI25::Resources) {
-    let serial = Serial(&**r.USART1);
+fn receive(t: &mut Threshold, mut r: USART2::Resources) {
+    let serial = Serial(&**r.USART2);
 
     let byte = serial.read().unwrap();
     if serial.write(byte).is_err() {
diff --git a/examples/resource.rs b/examples/resource.rs
index 66f35efed610b7b7e7906459e91f8851b5864754..c39e71e68e0dd28bb814e4c82bbca80de93d5ee6 100644
--- a/examples/resource.rs
+++ b/examples/resource.rs
@@ -18,16 +18,16 @@
 extern crate cast;
 extern crate cortex_m;
 extern crate cortex_m_rtfm as rtfm;
-extern crate f3;
+extern crate f4;
 extern crate heapless;
 
 use cast::{usize, u8};
 use cortex_m::peripheral::SystClkSource;
-use f3::Serial;
-use f3::led::{self, LEDS};
-use f3::prelude::*;
-use f3::serial::Event;
-use f3::time::Hertz;
+use f4::Serial;
+use f4::led::{self, LEDS};
+use f4::prelude::*;
+use f4::serial::Event;
+use f4::time::Hertz;
 use heapless::Vec;
 use rtfm::{app, Threshold};
 
@@ -37,7 +37,7 @@ const DIVISOR: u32 = 4;
 
 // TASKS & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 
     resources: {
         // 16 byte buffer
@@ -47,9 +47,9 @@ app! {
     },
 
     tasks: {
-        USART1_EXTI25: {
+        USART2: {
             path: receive,
-            resources: [BUFFER, SHARED, USART1],
+            resources: [BUFFER, SHARED, USART2],
         },
 
         SYS_TICK: {
@@ -61,15 +61,15 @@ app! {
 
 // INITIALIZATION PHASE
 fn init(p: init::Peripherals, _r: init::Resources) {
-    led::init(&p.GPIOE, &p.RCC);
+    led::init(&p.GPIOA, &p.RCC);
 
-    let serial = Serial(p.USART1);
+    let serial = Serial(p.USART2);
     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
     serial.listen(Event::Rxne);
 
 
     p.SYST.set_clock_source(SystClkSource::Core);
-    p.SYST.set_reload(8_000_000 / DIVISOR);
+    p.SYST.set_reload(16_000_000 / DIVISOR);
     p.SYST.enable_interrupt();
     p.SYST.enable_counter();
 }
@@ -83,8 +83,8 @@ fn idle() -> ! {
 }
 
 // TASKS
-fn receive(_t: &mut Threshold, r: USART1_EXTI25::Resources) {
-    let serial = Serial(&**r.USART1);
+fn receive(_t: &mut Threshold, r: USART2::Resources) {
+    let serial = Serial(&**r.USART2);
 
     let byte = serial.read().unwrap();
 
diff --git a/examples/roulette.rs b/examples/roulette.rs
index c3b48c6a1df315a097cb071a74ab4bfe5e3812de..e691e407895d0cdd936aaee3e597a74a7466853b 100644
--- a/examples/roulette.rs
+++ b/examples/roulette.rs
@@ -5,13 +5,13 @@
 #![no_std]
 
 extern crate cast;
-extern crate f3;
+extern crate f4;
 extern crate cortex_m;
 extern crate cortex_m_rtfm as rtfm;
 
 use cast::{usize, u8};
 use cortex_m::peripheral::SystClkSource;
-use f3::led::{self, LEDS};
+use f4::led::{self, LEDS};
 use rtfm::{app, Threshold};
 
 // CONFIGURATION
@@ -19,7 +19,7 @@ const DIVISOR: u32 = 4;
 
 // TASKS & RESOURCES
 app! {
-    device: f3::stm32f30x,
+    device: f4::stm32f40x,
 
     resources: {
         static STATE: u8 = 0;
@@ -35,10 +35,10 @@ app! {
 
 // INITIALIZATION PHASE
 fn init(p: init::Peripherals, _r: init::Resources) {
-    led::init(p.GPIOE, p.RCC);
+    led::init(p.GPIOA, p.RCC);
 
     p.SYST.set_clock_source(SystClkSource::Core);
-    p.SYST.set_reload(8_000_000 / DIVISOR);
+    p.SYST.set_reload(16_000_000 / DIVISOR);
     p.SYST.enable_interrupt();
     p.SYST.enable_counter();
 }
diff --git a/gen-examples.sh b/gen-examples.sh
old mode 100644
new mode 100755
diff --git a/memory.x b/memory.x
index ff76f43e7bf6a38aa7b53b6f7a4c95d0579ddfae..f7a67d6812f80566eae4a4a015a62babc84e600b 100644
--- a/memory.x
+++ b/memory.x
@@ -1,8 +1,20 @@
 MEMORY
 {
-  CCRAM : ORIGIN = 0x10000000, LENGTH = 8K
-  FLASH : ORIGIN = 0x08000000, LENGTH = 256K
-  RAM : ORIGIN = 0x20000000, LENGTH = 40K
+  /* NOTE K = KiBi = 1024 bytes */
+  /* TODO Adjust these memory regions to match your device memory layout */
+  FLASH : ORIGIN =  0x08000000, LENGTH = 512K
+  RAM : ORIGIN = 0x20000000, LENGTH = 96K
 }
 
-_stack_start = ORIGIN(CCRAM) + LENGTH(CCRAM);
+/* This is where the call stack will be allocated. */
+/* The stack is of the full descending type. */
+/* You may want to use this variable to locate the call stack and static
+   variables in different memory regions. Below is shown the default value */
+/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */
+
+/* You can use this symbol to customize the location of the .text section */
+/* If omitted the .text section will be placed right after the .vector_table
+   section */
+/* This is required only on microcontrollers that store some configuration right
+   after the vector table */
+/* _stext = ORIGIN(FLASH) + 0x400; */
diff --git a/src/dma.rs b/src/dma.rs
index a207f03c00b5b919ea1eed5602058cb5173084a8..3fecd54a09fd3b0efb84082e233cf182d27d44af 100644
--- a/src/dma.rs
+++ b/src/dma.rs
@@ -5,7 +5,7 @@ use core::marker::PhantomData;
 use core::ops;
 
 use nb;
-use stm32f30x::DMA1;
+use stm32f40x::DMA1;
 
 /// DMA error
 #[derive(Debug)]
@@ -24,8 +24,8 @@ pub struct Dma1Channel2 {
     _0: (),
 }
 
-/// Channel 4 of DMA1
-pub struct Dma1Channel4 {
+/// Channel 6 of DMA1
+pub struct Dma1Channel6 {
     _0: (),
 }
 
@@ -201,12 +201,12 @@ impl<T> Buffer<T, Dma1Channel2> {
             return Ok(());
         }
 
-        if dma1.isr.read().teif2().bit_is_set() {
+        if dma1.lisr.read().teif2().bit_is_set() {
             Err(nb::Error::Other(Error::Transfer))
-        } else if dma1.isr.read().tcif2().bit_is_set() {
+        } else if dma1.lisr.read().tcif2().bit_is_set() {
             unsafe { self.unlock(state) }
-            dma1.ifcr.write(|w| w.ctcif2().set_bit());
-            dma1.ccr2.modify(|_, w| w.en().clear_bit());
+            dma1.lifcr.write(|w| w.ctcif2().set_bit());
+            dma1.s2cr.modify(|_, w| w.en().clear_bit());
             Ok(())
         } else {
             Err(nb::Error::WouldBlock)
@@ -214,7 +214,7 @@ impl<T> Buffer<T, Dma1Channel2> {
     }
 }
 
-impl<T> Buffer<T, Dma1Channel4> {
+impl<T> Buffer<T, Dma1Channel6> {
     /// Waits until the DMA releases this buffer
     pub fn release(&self, dma1: &DMA1) -> nb::Result<(), Error> {
         let state = self.state.get();
@@ -223,12 +223,12 @@ impl<T> Buffer<T, Dma1Channel4> {
             return Ok(());
         }
 
-        if dma1.isr.read().teif4().bit_is_set() {
+        if dma1.hisr.read().teif6().bit_is_set() {
             Err(nb::Error::Other(Error::Transfer))
-        } else if dma1.isr.read().tcif4().bit_is_set() {
+        } else if dma1.hisr.read().tcif6().bit_is_set() {
             unsafe { self.unlock(state) }
-            dma1.ifcr.write(|w| w.ctcif4().set_bit());
-            dma1.ccr4.modify(|_, w| w.en().clear_bit());
+            dma1.hifcr.write(|w| w.ctcif6().set_bit());
+            dma1.s6cr.modify(|_, w| w.en().clear_bit());
             Ok(())
         } else {
             Err(nb::Error::WouldBlock)
@@ -245,12 +245,12 @@ impl<T> Buffer<T, Dma1Channel5> {
             return Ok(());
         }
 
-        if dma1.isr.read().teif5().bit_is_set() {
+        if dma1.hisr.read().teif5().bit_is_set() {
             Err(nb::Error::Other(Error::Transfer))
-        } else if dma1.isr.read().tcif5().bit_is_set() {
+        } else if dma1.hisr.read().tcif5().bit_is_set() {
             unsafe { self.unlock(state) }
-            dma1.ifcr.write(|w| w.ctcif5().set_bit());
-            dma1.ccr5.modify(|_, w| w.en().clear_bit());
+            dma1.hifcr.write(|w| w.ctcif5().set_bit());
+            dma1.s5cr.modify(|_, w| w.en().clear_bit());
             Ok(())
         } else {
             Err(nb::Error::WouldBlock)
diff --git a/src/examples/_0_hello.rs b/src/examples/_0_hello.rs
index f4ca56a5049d9383415042f731adaa3512b47415..7656cc60b00b178297993ffb72ad7e50c25f1c90 100644
--- a/src/examples/_0_hello.rs
+++ b/src/examples/_0_hello.rs
@@ -1,39 +1,32 @@
-//! Prints "Hello" and then "World" on the OpenOCD console
+//! Prints "Hello, world" on the OpenOCD console
 //!
 //! ```
-//! 
-//! #![feature(used)]
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.6"
-//! #[macro_use]
-//! extern crate cortex_m;
-//! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
 //! extern crate cortex_m_rtfm as rtfm;
+//! extern crate cortex_m_semihosting as semihosting;
+//! extern crate f4;
 //! 
-//! extern crate f3;
+//! use core::fmt::Write;
 //! 
-//! use f3::stm32f30x;
-//! use rtfm::{P0, T0, TMax};
+//! use rtfm::app;
+//! use semihosting::hio;
 //! 
-//! // TASKS
-//! tasks!(stm32f30x, {});
+//! // TASKS & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
+//! }
 //! 
 //! // INITIALIZATION PHASE
-//! fn init(_priority: P0, _threshold: &TMax) {
-//!     hprintln!("Hello");
-//! }
+//! fn init(_p: init::Peripherals) {}
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
-//!     hprintln!("World");
+//! fn idle() -> ! {
+//!     writeln!(hio::hstdout().unwrap(), "Hello, world!").unwrap();
 //! 
-//!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
 //!     }
diff --git a/src/examples/_1_itm.rs b/src/examples/_1_itm.rs
index 476690c74e72865fb424598be36472ab42c54453..a5b687ba6d01905867ea6fd7a009e8f7a60a1bf3 100644
--- a/src/examples/_1_itm.rs
+++ b/src/examples/_1_itm.rs
@@ -6,55 +6,40 @@
 //! [`itm`]: https://docs.rs/itm/0.1.1/itm/
 //!
 //! ```
-//! 
-//! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.6"
 //! #[macro_use]
 //! extern crate cortex_m;
-//! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
 //! extern crate cortex_m_rtfm as rtfm;
+//! extern crate f4;
 //! 
-//! extern crate f3;
+//! use rtfm::{app, Threshold};
 //! 
-//! use f3::stm32f30x;
-//! use rtfm::{P0, T0, TMax};
+//! // TASK & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
 //! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     ITM: Peripheral {
-//!         register_block: Itm,
-//!         ceiling: C0,
+//!     idle: {
+//!         resources: [ITM],
 //!     },
-//! });
+//! }
 //! 
 //! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let itm = ITM.access(priority, threshold);
-//! 
-//!     iprintln!(&itm.stim[0], "Hello");
+//! fn init(p: init::Peripherals) {
+//!     iprintln!(&p.ITM.stim[0], "Hello");
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(ref priority: P0, ref threshold: T0) -> ! {
-//!     let itm = ITM.access(priority, threshold);
-//! 
-//!     iprintln!(&itm.stim[0], "World");
+//! fn idle(_t: &mut Threshold, r: idle::Resources) -> ! {
+//!     iprintln!(&r.ITM.stim[0], "World");
 //! 
 //!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
 //!     }
 //! }
-//! 
-//! // TASKS
-//! tasks!(stm32f30x, {});
 //! ```
 // Auto-generated. Do not modify.
diff --git a/src/examples/_2_led.rs b/src/examples/_2_led.rs
index 9f8e0ba182de5aa5541455e6ceaf966a990e4a2f..e5ee63663478ec8551b4b296566ce42494a64ba0 100644
--- a/src/examples/_2_led.rs
+++ b/src/examples/_2_led.rs
@@ -1,46 +1,29 @@
 //! Turns all the user LEDs on
 //!
 //! ```
-//! 
-//! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
 //! extern crate cortex_m_rtfm as rtfm;
+//! extern crate f4;
 //! 
-//! extern crate f3;
-//! 
-//! use f3::led::{self, LEDS};
-//! use f3::stm32f30x;
-//! use rtfm::{P0, T0, TMax};
+//! use f4::led::{self, LEDS};
+//! use rtfm::app;
 //! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     GPIOE: Peripheral {
-//!         register_block: Gpioe,
-//!         ceiling: C0,
-//!     },
-//!     RCC: Peripheral {
-//!         register_block: Rcc,
-//!         ceiling: C0,
-//!     },
-//! });
+//! // TASKS & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
+//! }
 //! 
 //! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let gpioe = GPIOE.access(priority, threshold);
-//!     let rcc = RCC.access(priority, threshold);
-//! 
-//!     led::init(&gpioe, &rcc);
+//! fn init(p: init::Peripherals) {
+//!     led::init(&p.GPIOA, &p.RCC);
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
+//! fn idle() -> ! {
 //!     for led in &LEDS {
 //!         led.on();
 //!     }
@@ -50,8 +33,5 @@
 //!         rtfm::wfi();
 //!     }
 //! }
-//! 
-//! // TASKS
-//! tasks!(stm32f30x, {});
 //! ```
 // Auto-generated. Do not modify.
diff --git a/src/examples/_3_blinky.rs b/src/examples/_3_blinky.rs
index 3c440a56e749268661e763eb733b77d3c5b7a218..932aa2f72e2a2e466d61c51936738714df88fe37 100644
--- a/src/examples/_3_blinky.rs
+++ b/src/examples/_3_blinky.rs
@@ -1,64 +1,50 @@
 //! Blinks an LED
 //!
 //! ```
-//! 
-//! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
+//! extern crate f4;
+//! extern crate cortex_m;
 //! extern crate cortex_m_rtfm as rtfm;
 //! 
-//! extern crate f3;
-//! 
-//! use f3::led::{self, LEDS};
-//! use f3::stm32f30x::interrupt::Tim7;
-//! use f3::stm32f30x;
-//! use f3::timer::Timer;
-//! use rtfm::{Local, P0, P1, T0, T1, TMax};
+//! use cortex_m::peripheral::SystClkSource;
+//! use f4::led::{self, LEDS};
+//! use rtfm::{app, Threshold};
 //! 
 //! // CONFIGURATION
-//! const FREQUENCY: u32 = 1; // Hz
+//! const FREQUENCY: u32 = 4; // Hz
 //! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     GPIOE: Peripheral {
-//!         register_block: Gpioe,
-//!         ceiling: C0,
-//!     },
-//!     RCC: Peripheral {
-//!         register_block: Rcc,
-//!         ceiling: C0,
+//! // TASKS & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
+//! 
+//!     resources: {
+//!         static ON: bool = false;
 //!     },
-//!     TIM7: Peripheral {
-//!         register_block: Tim7,
-//!         ceiling: C1,
+//! 
+//!     tasks: {
+//!         SYS_TICK: {
+//!             path: toggle,
+//!             resources: [ON],
+//!         },
 //!     },
-//! });
+//! }
 //! 
 //! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let gpioe = GPIOE.access(priority, threshold);
-//!     let rcc = RCC.access(priority, threshold);
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
+//! fn init(p: init::Peripherals, _r: init::Resources) {
+//!     led::init(p.GPIOA, p.RCC);
 //! 
-//!     // Configure the PEx pins as output pins
-//!     led::init(&gpioe, &rcc);
-//! 
-//!     // Configure TIM7 for periodic update events
-//!     timer.init(&rcc, FREQUENCY);
-//! 
-//!     // Start the timer
-//!     timer.resume();
+//!     p.SYST.set_clock_source(SystClkSource::Core);
+//!     p.SYST.set_reload(16_000_000 / FREQUENCY);
+//!     p.SYST.enable_interrupt();
+//!     p.SYST.enable_counter();
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
+//! fn idle() -> ! {
 //!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
@@ -66,35 +52,14 @@
 //! }
 //! 
 //! // TASKS
-//! tasks!(stm32f30x, {
-//!     periodic: Task {
-//!         interrupt: Tim7,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//! });
-//! 
-//! fn periodic(mut task: Tim7, ref priority: P1, ref threshold: T1) {
-//!     // Task local data
-//!     static STATE: Local<bool, Tim7> = Local::new(false);
-//! 
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
-//! 
-//!     if timer.clear_update_flag().is_ok() {
-//!         let state = STATE.borrow_mut(&mut task);
-//! 
-//!         *state = !*state;
+//! // Toggle the state of the LED
+//! fn toggle(_t: &mut Threshold, r: SYS_TICK::Resources) {
+//!     **r.ON = !**r.ON;
 //! 
-//!         if *state {
-//!             LEDS[0].on();
-//!         } else {
-//!             LEDS[0].off();
-//!         }
+//!     if **r.ON {
+//!         LEDS[0].on();
 //!     } else {
-//!         // Only reachable through `rtfm::request(periodic)`
-//!         #[cfg(debug_assertion)]
-//!         unreachable!()
+//!         LEDS[0].off();
 //!     }
 //! }
 //! ```
diff --git a/src/examples/_4_roulette.rs b/src/examples/_4_roulette.rs
index 06bed34e897d74e3967db1cd479d8176e699a7ab..9cfce2a5fb4dcb0ac4c7df33d44eab189d0d544f 100644
--- a/src/examples/_4_roulette.rs
+++ b/src/examples/_4_roulette.rs
@@ -1,63 +1,52 @@
 //! A LED roulette!
 //!
 //! ```
-//! 
-//! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.2", default-features = false
 //! extern crate cast;
-//! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
+//! extern crate f4;
+//! extern crate cortex_m;
 //! extern crate cortex_m_rtfm as rtfm;
 //! 
-//! extern crate f3;
-//! 
-//! use cast::{u8, usize};
-//! use f3::led::{self, LEDS};
-//! use f3::stm32f30x::interrupt::Tim7;
-//! use f3::stm32f30x;
-//! use f3::timer::Timer;
-//! use rtfm::{Local, P0, P1, T0, T1, TMax};
+//! use cast::{usize, u8};
+//! use cortex_m::peripheral::SystClkSource;
+//! use f4::led::{self, LEDS};
+//! use rtfm::{app, Threshold};
 //! 
 //! // CONFIGURATION
-//! const FREQUENCY: u32 = 4; // Hz
+//! const DIVISOR: u32 = 4;
 //! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     GPIOE: Peripheral {
-//!         register_block: Gpioe,
-//!         ceiling: C0,
-//!     },
-//!     RCC: Peripheral {
-//!         register_block: Rcc,
-//!         ceiling: C0,
+//! // TASKS & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
+//! 
+//!     resources: {
+//!         static STATE: u8 = 0;
 //!     },
-//!     TIM7: Peripheral {
-//!         register_block: Tim7,
-//!         ceiling: C1,
+//! 
+//!     tasks: {
+//!         SYS_TICK: {
+//!             path: roulette,
+//!             resources: [STATE],
+//!         },
 //!     },
-//! });
+//! }
 //! 
 //! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let gpioe = GPIOE.access(priority, threshold);
-//!     let rcc = RCC.access(priority, threshold);
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
+//! fn init(p: init::Peripherals, _r: init::Resources) {
+//!     led::init(p.GPIOA, p.RCC);
 //! 
-//!     led::init(&gpioe, &rcc);
-//!     timer.init(&rcc, FREQUENCY);
-//!     timer.resume();
+//!     p.SYST.set_clock_source(SystClkSource::Core);
+//!     p.SYST.set_reload(16_000_000 / DIVISOR);
+//!     p.SYST.enable_interrupt();
+//!     p.SYST.enable_counter();
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
+//! fn idle() -> ! {
 //!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
@@ -65,35 +54,14 @@
 //! }
 //! 
 //! // TASKS
-//! tasks!(stm32f30x, {
-//!     roulette: Task {
-//!         interrupt: Tim7,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//! });
-//! 
-//! fn roulette(mut task: Tim7, ref priority: P1, ref threshold: T1) {
-//!     static STATE: Local<u8, Tim7> = Local::new(0);
-//! 
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
+//! fn roulette(_t: &mut Threshold, r: SYS_TICK::Resources) {
+//!     let curr = **r.STATE;
+//!     let next = (curr + 1) % u8(LEDS.len()).unwrap();
 //! 
-//!     if timer.clear_update_flag().is_ok() {
-//!         let state = STATE.borrow_mut(&mut task);
+//!     LEDS[usize(curr)].off();
+//!     LEDS[usize(next)].on();
 //! 
-//!         let curr = *state;
-//!         let next = (curr + 1) % u8(LEDS.len()).unwrap();
-//! 
-//!         LEDS[usize(curr)].off();
-//!         LEDS[usize(next)].on();
-//! 
-//!         *state = next;
-//!     } else {
-//!         // Only reachable through `rtfm::request(roulette)`
-//!         #[cfg(debug_assertion)]
-//!         unreachable!()
-//!     }
+//!     **r.STATE = next;
 //! }
 //! ```
 // Auto-generated. Do not modify.
diff --git a/src/examples/_5_loopback.rs b/src/examples/_5_loopback.rs
index e6c04de3f81fb82cec611b5f8838f056f9d0a236..3bede5e9908d43813302d3dbd19bd2eaa5818570 100644
--- a/src/examples/_5_loopback.rs
+++ b/src/examples/_5_loopback.rs
@@ -1,57 +1,45 @@
 //! Serial interface loopback
 //!
 //! ```
-//! 
-//! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
 //! extern crate cortex_m_rtfm as rtfm;
+//! extern crate f4;
 //! 
-//! extern crate f3;
-//! 
-//! use f3::serial::Serial;
-//! use f3::stm32f30x::interrupt::Usart1Exti25;
-//! use f3::stm32f30x;
-//! use rtfm::{P0, P1, T0, T1, TMax};
+//! use f4::prelude::*;
+//! use f4::Serial;
+//! use f4::serial::Event;
+//! use f4::time::Hertz;
+//! use rtfm::{app, Threshold};
 //! 
 //! // CONFIGURATION
-//! pub const BAUD_RATE: u32 = 115_200; // bits per second
+//! const BAUD_RATE: Hertz = Hertz(115_200);
 //! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     GPIOA: Peripheral {
-//!         register_block: Gpioa,
-//!         ceiling: C0,
-//!     },
-//!     RCC: Peripheral {
-//!         register_block: Rcc,
-//!         ceiling: C0,
-//!     },
-//!     USART1: Peripheral {
-//!         register_block: Usart1,
-//!         ceiling: C1,
-//!     },
-//! });
+//! // TASKS & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
 //! 
-//! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let gpioa = GPIOA.access(priority, threshold);
-//!     let rcc = RCC.access(priority, threshold);
-//!     let usart1 = USART1.access(priority, threshold);
+//!     tasks: {
+//!         USART2: {
+//!             path: loopback,
+//!             resources: [USART2],
+//!         },
+//!     }
+//! }
 //! 
-//!     let serial = Serial(&usart1);
+//! // INITIALIZATION PHASE
+//! fn init(p: init::Peripherals) {
+//!     let serial = Serial(p.USART2);
 //! 
-//!     serial.init(&gpioa, &rcc, BAUD_RATE);
+//!     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
+//!     serial.listen(Event::Rxne);
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
+//! fn idle() -> ! {
 //!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
@@ -59,31 +47,12 @@
 //! }
 //! 
 //! // TASKS
-//! tasks!(stm32f30x, {
-//!     loopback: Task {
-//!         interrupt: Usart1Exti25,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//! });
-//! 
 //! // Send back the received byte
-//! fn loopback(_task: Usart1Exti25, ref priority: P1, ref threshold: T1) {
-//!     let usart1 = USART1.access(priority, threshold);
-//!     let serial = Serial(&usart1);
+//! fn loopback(_t: &mut Threshold, r: USART2::Resources) {
+//!     let serial = Serial(&**r.USART2);
 //! 
-//!     if let Ok(byte) = serial.read() {
-//!         if serial.write(byte).is_err() {
-//!             // As we are echoing the bytes as soon as they arrive, it should
-//!             // be impossible to have a TX buffer overrun
-//!             #[cfg(debug_assertions)]
-//!             unreachable!()
-//!         }
-//!     } else {
-//!         // Only reachable through `rtfm::request(loopback)`
-//!         #[cfg(debug_assertions)]
-//!         unreachable!()
-//!     }
+//!     let byte = serial.read().unwrap();
+//!     serial.write(byte).unwrap();
 //! }
 //! ```
 // Auto-generated. Do not modify.
diff --git a/src/examples/_6_concurrency.rs b/src/examples/_6_concurrency.rs
index 54110074cb98bd7192c9704fc3153d78b11a11c0..bb61b4c882b197f899f812832901c15adad4d859 100644
--- a/src/examples/_6_concurrency.rs
+++ b/src/examples/_6_concurrency.rs
@@ -1,79 +1,67 @@
 //! LED roulette and serial loopback running concurrently
 //!
 //! ```
-//! 
-//! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.2", default-features = false
 //! extern crate cast;
+//! extern crate cortex_m;
+//! extern crate cortex_m_rtfm as rtfm;
+//! extern crate f4;
 //! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
+//! use f4::Serial;
+//! use f4::led::{self, LEDS};
+//! use f4::prelude::*;
+//! use f4::serial::Event;
+//! use f4::time::Hertz;
+//! use cortex_m::peripheral::SystClkSource;
+//! use cast::{usize, u8};
+//! use rtfm::{app, Threshold};
 //! 
-//! // version = "0.1.0"
-//! #[macro_use]
-//! extern crate cortex_m_rtfm as rtfm;
+//! // CONFIGURATION
+//! const BAUD_RATE: Hertz = Hertz(115_200);
+//! const DIVISOR: u32 = 4;
 //! 
-//! extern crate f3;
 //! 
-//! use cast::{u8, usize};
-//! use f3::led::{self, LEDS};
-//! use f3::serial::Serial;
-//! use f3::stm32f30x::interrupt::{Tim7, Usart1Exti25};
-//! use f3::stm32f30x;
-//! use f3::timer::Timer;
-//! use rtfm::{Local, P0, P1, T0, T1, TMax};
+//! // TASKS & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
 //! 
-//! // CONFIGURATION
-//! pub const BAUD_RATE: u32 = 115_200; // bits per second
-//! const FREQUENCY: u32 = 4; // Hz
-//! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     GPIOA: Peripheral {
-//!         register_block: Gpioa,
-//!         ceiling: C0,
-//!     },
-//!     GPIOE: Peripheral {
-//!         register_block: Gpioe,
-//!         ceiling: C0,
+//!     resources: {
+//!         static STATE: u8 = 0;
 //!     },
-//!     RCC: Peripheral {
-//!         register_block: Rcc,
-//!         ceiling: C0,
-//!     },
-//!     TIM7: Peripheral {
-//!         register_block: Tim7,
-//!         ceiling: C1,
-//!     },
-//!     USART1: Peripheral {
-//!         register_block: Usart1,
-//!         ceiling: C1,
-//!     },
-//! });
 //! 
-//! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let gpioa = GPIOA.access(priority, threshold);
-//!     let gpioe = GPIOE.access(priority, threshold);
-//!     let rcc = RCC.access(priority, threshold);
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let usart1 = USART1.access(priority, threshold);
+//!     tasks: {
+//!         SYS_TICK: {
+//!             path: roulette,
+//!             resources: [STATE],
+//!         },
 //! 
-//!     let timer = Timer(&tim7);
-//!     let serial = Serial(&usart1);
+//!         USART2: {
+//!             path: loopback,
+//!             resources: [USART2],
+//!         },
+//!     }
+//! }
 //! 
-//!     led::init(&gpioe, &rcc);
-//!     timer.init(&rcc, FREQUENCY);
-//!     serial.init(&gpioa, &rcc, BAUD_RATE);
+//! // INITIALIZATION PHASE
+//! fn init(p: init::Peripherals, _r: init::Resources) {
+//!     led::init(p.GPIOA, p.RCC);
+//! 
+//!     let serial = Serial(p.USART2);
+//!     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
+//!     serial.listen(Event::Rxne);
 //! 
-//!     timer.resume();
+//!     p.SYST.set_clock_source(SystClkSource::Core);
+//!     p.SYST.set_reload(16_000_000 / DIVISOR);
+//!     p.SYST.enable_interrupt();
+//!     p.SYST.enable_counter();
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
+//! fn idle() -> ! {
 //!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
@@ -81,22 +69,8 @@
 //! }
 //! 
 //! // TASKS
-//! tasks!(stm32f30x, {
-//!     loopback: Task {
-//!         interrupt: Usart1Exti25,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//!     roulette: Task {
-//!         interrupt: Tim7,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//! });
-//! 
-//! fn loopback(_task: Usart1Exti25, ref priority: P1, ref threshold: T1) {
-//!     let usart1 = USART1.access(priority, threshold);
-//!     let serial = Serial(&usart1);
+//! fn loopback(_t: &mut Threshold, r: USART2::Resources) {
+//!     let serial = Serial(&**r.USART2);
 //! 
 //!     if let Ok(byte) = serial.read() {
 //!         if serial.write(byte).is_err() {
@@ -112,27 +86,14 @@
 //!     }
 //! }
 //! 
-//! fn roulette(mut task: Tim7, ref priority: P1, ref threshold: T1) {
-//!     static STATE: Local<u8, Tim7> = Local::new(0);
-//! 
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
+//! fn roulette(_t: &mut Threshold, r: SYS_TICK::Resources) {
+//!     let curr = **r.STATE;
+//!     let next = (curr + 1) % u8(LEDS.len()).unwrap();
 //! 
-//!     if timer.clear_update_flag().is_ok() {
-//!         let state = STATE.borrow_mut(&mut task);
+//!     LEDS[usize(curr)].off();
+//!     LEDS[usize(next)].on();
 //! 
-//!         let curr = *state;
-//!         let next = (curr + 1) % u8(LEDS.len()).unwrap();
-//! 
-//!         LEDS[usize(curr)].off();
-//!         LEDS[usize(next)].on();
-//! 
-//!         *state = next;
-//!     } else {
-//!         // Only reachable through `rtfm::request(roulette)`
-//!         #[cfg(debug_assertion)]
-//!         unreachable!()
-//!     }
+//!     **r.STATE = next;
 //! }
 //! ```
 // Auto-generated. Do not modify.
diff --git a/src/examples/_7_resource.rs b/src/examples/_7_resource.rs
index 073e80ee4778022346550f0a50bf2e95ae51676e..98b87186a50e406f51c88fec5b4c266c987e3fa4 100644
--- a/src/examples/_7_resource.rs
+++ b/src/examples/_7_resource.rs
@@ -11,121 +11,73 @@
 //!   spinning in the same direction.
 //!
 //! ```
-//! 
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
 //! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.2", default-features = false
 //! extern crate cast;
-//! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
+//! extern crate cortex_m;
 //! extern crate cortex_m_rtfm as rtfm;
-//! 
-//! extern crate f3;
-//! 
-//! // version = "0.1.0"
+//! extern crate f4;
 //! extern crate heapless;
 //! 
-//! use core::cell::Cell;
-//! 
-//! use cast::{u8, usize};
-//! use f3::led::{self, LEDS};
-//! use f3::serial::Serial;
-//! use f3::stm32f30x::interrupt::{Tim7, Usart1Exti25};
-//! use f3::stm32f30x;
-//! use f3::timer::Timer;
+//! use cast::{usize, u8};
+//! use cortex_m::peripheral::SystClkSource;
+//! use f4::Serial;
+//! use f4::led::{self, LEDS};
+//! use f4::prelude::*;
+//! use f4::serial::Event;
+//! use f4::time::Hertz;
 //! use heapless::Vec;
-//! use rtfm::{C1, Local, P0, P1, Resource, T0, T1, TMax};
+//! use rtfm::{app, Threshold};
 //! 
-//! // SUPPORT CODE
-//! struct State {
-//!     direction: Cell<Direction>,
-//!     mode: Cell<Mode>,
-//! }
+//! // CONFIGURATION
+//! const BAUD_RATE: Hertz = Hertz(115_200);
+//! const DIVISOR: u32 = 4; 
+//! 
+//! // TASKS & RESOURCES
+//! app! {
+//!     device: f4::stm32f40x,
+//! 
+//!     resources: {
+//!         // 16 byte buffer
+//!         static BUFFER: Vec<u8, [u8; 16]> = Vec::new([0; 16]);
+//!         static SHARED: State = State::new();
+//!         static STATE: u8 = 0;
+//!     },
 //! 
-//! impl State {
-//!     const fn new() -> Self {
-//!         State {
-//!             direction: Cell::new(Direction::Clockwise),
-//!             mode: Cell::new(Mode::Continuous),
-//!         }
-//!     }
-//! }
+//!     tasks: {
+//!         USART2: {
+//!             path: receive,
+//!             resources: [BUFFER, SHARED, USART2],
+//!         },
 //! 
-//! #[derive(Clone, Copy)]
-//! enum Direction {
-//!     Clockwise,
-//!     Counterclockwise,
-//! }
-//! 
-//! impl Direction {
-//!     fn reverse(self) -> Self {
-//!         match self {
-//!             Direction::Clockwise => Direction::Counterclockwise,
-//!             Direction::Counterclockwise => Direction::Clockwise,
-//!         }
+//!         SYS_TICK: {
+//!             path: roulette,
+//!             resources: [SHARED, STATE],
+//!         },
 //!     }
 //! }
 //! 
-//! #[derive(Clone, Copy, PartialEq)]
-//! enum Mode {
-//!     Bounce,
-//!     Continuous,
-//! }
+//! // INITIALIZATION PHASE
+//! fn init(p: init::Peripherals, _r: init::Resources) {
+//!     led::init(&p.GPIOA, &p.RCC);
 //! 
-//! // CONFIGURATION
-//! pub const BAUD_RATE: u32 = 115_200; // bits per second
-//! const FREQUENCY: u32 = 4; // Hz
-//! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     GPIOA: Peripheral {
-//!         register_block: Gpioa,
-//!         ceiling: C0,
-//!     },
-//!     GPIOE: Peripheral {
-//!         register_block: Gpioe,
-//!         ceiling: C0,
-//!     },
-//!     RCC: Peripheral {
-//!         register_block: Rcc,
-//!         ceiling: C0,
-//!     },
-//!     TIM7: Peripheral {
-//!         register_block: Tim7,
-//!         ceiling: C1,
-//!     },
-//!     USART1: Peripheral {
-//!         register_block: Usart1,
-//!         ceiling: C1,
-//!     },
-//! });
+//!     let serial = Serial(p.USART2);
+//!     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
+//!     serial.listen(Event::Rxne);
 //! 
-//! static SHARED: Resource<State, C1> = Resource::new(State::new());
 //! 
-//! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let gpioa = GPIOA.access(priority, threshold);
-//!     let gpioe = GPIOE.access(priority, threshold);
-//!     let rcc = RCC.access(priority, threshold);
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
-//!     let usart1 = USART1.access(priority, threshold);
-//! 
-//!     led::init(&gpioe, &rcc);
-//!     timer.init(&rcc, FREQUENCY);
-//!     Serial(&usart1).init(&gpioa, &rcc, BAUD_RATE);
-//! 
-//!     timer.resume();
+//!     p.SYST.set_clock_source(SystClkSource::Core);
+//!     p.SYST.set_reload(16_000_000 / DIVISOR);
+//!     p.SYST.enable_interrupt();
+//!     p.SYST.enable_counter();
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
+//! fn idle() -> ! {
 //!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
@@ -133,102 +85,93 @@
 //! }
 //! 
 //! // TASKS
-//! tasks!(stm32f30x, {
-//!     roulette: Task {
-//!         interrupt: Tim7,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//!     receive: Task {
-//!         interrupt: Usart1Exti25,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//! });
-//! 
-//! fn receive(mut task: Usart1Exti25, ref priority: P1, ref threshold: T1) {
-//!     // 16 byte buffer
-//!     static BUFFER: Local<Vec<u8, [u8; 16]>, Usart1Exti25> = {
-//!         Local::new(Vec::new([0; 16]))
-//!     };
-//! 
-//!     let usart1 = USART1.access(priority, threshold);
-//!     let serial = Serial(&usart1);
+//! fn receive(_t: &mut Threshold, r: USART2::Resources) {
+//!     let serial = Serial(&**r.USART2);
 //! 
-//!     if let Ok(byte) = serial.read() {
-//!         if serial.write(byte).is_err() {
-//!             // As we are echoing the bytes as soon as they arrive, it should
-//!             // be impossible to have a TX buffer overrun
-//!             #[cfg(debug_assertions)]
-//!             unreachable!()
-//!         }
+//!     let byte = serial.read().unwrap();
 //! 
-//!         let buffer = BUFFER.borrow_mut(&mut task);
+//!     serial.write(byte).unwrap();
 //! 
-//!         if byte == b'r' {
-//!             // end of command
+//!     if byte == b'r' {
+//!         // end of command
 //! 
-//!             let shared = SHARED.access(priority, threshold);
-//!             match &**buffer {
-//!                 b"bounce" => shared.mode.set(Mode::Bounce),
-//!                 b"continuous" => shared.mode.set(Mode::Continuous),
-//!                 b"reverse" => {
-//!                     shared.direction.set(shared.direction.get().reverse());
-//!                 }
-//!                 _ => {}
+//!         match &***r.BUFFER {
+//!             b"bounce" => r.SHARED.mode = Mode::Bounce,
+//!             b"continuous" => r.SHARED.mode = Mode::Continuous,
+//!             b"reverse" => {
+//!                 r.SHARED.direction = r.SHARED.direction.reverse();
 //!             }
+//!             _ => {}
+//!         }
 //! 
-//!             // clear the buffer to prepare for the next command
-//!             buffer.clear();
-//!         } else {
-//!             // push the byte into the buffer
+//!         // clear the buffer to prepare for the next command
+//!         r.BUFFER.clear();
+//!     } else {
+//!         // push the byte into the buffer
 //! 
-//!             if buffer.push(byte).is_err() {
-//!                 // error: buffer full
-//!                 // KISS: we just clear the buffer when it gets full
-//!                 buffer.clear();
-//!             }
+//!         if r.BUFFER.push(byte).is_err() {
+//!             // error: buffer full
+//!             // KISS: we just clear the buffer when it gets full
+//!             r.BUFFER.clear();
 //!         }
-//!     } else {
-//!         // Only reachable through `rtfm::request(receive)`
-//!         #[cfg(debug_assertions)]
-//!         unreachable!()
 //!     }
 //! }
 //! 
-//! fn roulette(mut task: Tim7, ref priority: P1, ref threshold: T1) {
-//!     static STATE: Local<u8, Tim7> = Local::new(0);
+//! fn roulette(_t: &mut Threshold, r: SYS_TICK::Resources) {
+//!     let curr = **r.STATE;
 //! 
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
+//!     let mut direction = r.SHARED.direction;
+//!     if curr == 0 && r.SHARED.mode == Mode::Bounce {
+//!         direction = direction.reverse();
+//!         r.SHARED.direction = direction;
+//!     }
 //! 
-//!     if timer.clear_update_flag().is_ok() {
-//!         let state = STATE.borrow_mut(&mut task);
-//!         let curr = *state;
+//!     let n = u8(LEDS.len()).unwrap();
+//!     let next = match direction {
+//!         Direction::Clockwise => (curr + 1) % n,
+//!         Direction::Counterclockwise => curr.checked_sub(1).unwrap_or(n - 1),
+//!     };
 //! 
-//!         let shared = SHARED.access(priority, threshold);
-//!         let mut direction = shared.direction.get();
+//!     LEDS[usize(curr)].off();
+//!     LEDS[usize(next)].on();
 //! 
-//!         if curr == 0 && shared.mode.get() == Mode::Bounce {
-//!             direction = direction.reverse();
-//!             shared.direction.set(direction);
-//!         }
+//!     **r.STATE = next;
+//! }
 //! 
-//!         let n = u8(LEDS.len()).unwrap();
-//!         let next = match direction {
-//!             Direction::Clockwise => (curr + 1) % n,
-//!             Direction::Counterclockwise => curr.checked_sub(1).unwrap_or(n - 1),
-//!         };
+//! // SUPPORT CODE
+//! pub struct State {
+//!     direction: Direction,
+//!     mode: Mode,
+//! }
 //! 
-//!         LEDS[usize(curr)].off();
-//!         LEDS[usize(next)].on();
+//! impl State {
+//!     const fn new() -> Self {
+//!         State {
+//!             direction: Direction::Clockwise,
+//!             mode: Mode::Continuous,
+//!         }
+//!     }
+//! }
 //! 
-//!         *state = next;
-//!     } else {
-//!         // Only reachable through `rtfm::request(roulette)`
-//!         #[cfg(debug_assertion)]
-//!         unreachable!()
+//! #[derive(Clone, Copy)]
+//! enum Direction {
+//!     Clockwise,
+//!     Counterclockwise,
+//! }
+//! 
+//! impl Direction {
+//!     fn reverse(self) -> Self {
+//!         match self {
+//!             Direction::Clockwise => Direction::Counterclockwise,
+//!             Direction::Counterclockwise => Direction::Clockwise,
+//!         }
 //!     }
 //! }
+//! 
+//! #[derive(Clone, Copy, PartialEq)]
+//! enum Mode {
+//!     Bounce,
+//!     Continuous,
+//! }
 //! ```
 // Auto-generated. Do not modify.
diff --git a/src/examples/_8_preemption.rs b/src/examples/_8_preemption.rs
index aa58c5c9b1f388b34982f84a5022e677b0077f65..cdbc99dbdc136cd85db8d65ae111422a159455bb 100644
--- a/src/examples/_8_preemption.rs
+++ b/src/examples/_8_preemption.rs
@@ -8,122 +8,73 @@
 //! - `reset` - moves the roulette back to its start position (North)
 //!
 //! ```
-//! 
+//! #![deny(unsafe_code)]
+//! #![deny(warnings)]
 //! #![feature(const_fn)]
-//! #![feature(used)]
+//! #![feature(proc_macro)]
 //! #![no_std]
 //! 
-//! // version = "0.2.2", default-features = false
 //! extern crate cast;
-//! 
-//! // version = "0.2.0"
-//! extern crate cortex_m_rt;
-//! 
-//! // version = "0.1.0"
-//! #[macro_use]
+//! extern crate cortex_m;
 //! extern crate cortex_m_rtfm as rtfm;
-//! 
-//! extern crate f3;
-//! 
-//! // version = "0.1.0"
+//! extern crate f4;
 //! extern crate heapless;
 //! 
-//! use core::cell::Cell;
-//! 
-//! use cast::{u8, usize};
-//! use f3::led::{self, LEDS};
-//! use f3::serial::Serial;
-//! use f3::stm32f30x::interrupt::{Tim7, Usart1Exti25};
-//! use f3::stm32f30x;
-//! use f3::timer::Timer;
+//! use cast::{usize, u8};
+//! use cortex_m::peripheral::SystClkSource;
+//! use f4::Serial;
+//! use f4::led::{self, LEDS};
+//! use f4::prelude::*;
+//! use f4::serial::Event;
 //! use heapless::Vec;
-//! use rtfm::{C2, Local, P0, P1, P2, Resource, T0, T1, T2, TMax};
-//! 
-//! // SUPPORT CODE
-//! #[derive(Clone, Copy)]
-//! enum Direction {
-//!     Clockwise,
-//!     Counterclockwise,
-//! }
+//! use rtfm::{app, Resource, Threshold};
+//! use f4::time::Hertz;
 //! 
-//! impl Direction {
-//!     fn reverse(self) -> Self {
-//!         match self {
-//!             Direction::Clockwise => Direction::Counterclockwise,
-//!             Direction::Counterclockwise => Direction::Clockwise,
-//!         }
-//!     }
-//! }
+//! // CONFIGURATION
+//! const BAUD_RATE: Hertz = Hertz(115_200);
+//! const DIVISOR: u32 = 4;
 //! 
-//! #[derive(Clone, Copy, PartialEq)]
-//! enum Mode {
-//!     Bounce,
-//!     Continuous,
-//! }
+//! // TASK & RESOURCES
+//! app!{
+//!     device: f4::stm32f40x,
 //! 
-//! struct State {
-//!     direction: Cell<Direction>,
-//!     mode: Cell<Mode>,
-//! }
+//!     resources: {
+//!         static BUFFER: Vec<u8, [u8; 16]> = Vec::new([0; 16]);
+//!         static SHARED: State = State::new();
+//!         static STATE: u8 = 0;
+//!     },
 //! 
-//! impl State {
-//!     const fn new() -> Self {
-//!         State {
-//!             direction: Cell::new(Direction::Clockwise),
-//!             mode: Cell::new(Mode::Continuous),
-//!         }
-//!     }
+//!     tasks: {
+//!         USART2: {
+//!             path: receive,
+//!             priority: 1,
+//!             resources: [BUFFER, SHARED, USART2],
+//!         },
+//! 
+//!         SYS_TICK: {
+//!             path: roulette,
+//!             priority: 2,
+//!             resources: [SHARED, STATE],
+//!         },
+//!     },
 //! }
 //! 
-//! // CONFIGURATION
-//! pub const BAUD_RATE: u32 = 115_200; // bits per second
-//! const FREQUENCY: u32 = 4; // Hz
-//! 
-//! // RESOURCES
-//! peripherals!(stm32f30x, {
-//!     GPIOA: Peripheral {
-//!         register_block: Gpioa,
-//!         ceiling: C0,
-//!     },
-//!     GPIOE: Peripheral {
-//!         register_block: Gpioe,
-//!         ceiling: C0,
-//!     },
-//!     RCC: Peripheral {
-//!         register_block: Rcc,
-//!         ceiling: C0,
-//!     },
-//!     TIM7: Peripheral {
-//!         register_block: Tim7,
-//!         ceiling: C2, // was `C1`
-//!     },
-//!     USART1: Peripheral {
-//!         register_block: Usart1,
-//!         ceiling: C1,
-//!     },
-//! });
+//! // INITIALIZATION PHASE
+//! fn init(p: init::Peripherals, _r: init::Resources) {
+//!     led::init(&p.GPIOA, &p.RCC);
 //! 
-//! // the ceiling was `C1`
-//! static SHARED: Resource<State, C2> = Resource::new(State::new());
+//!     let serial = Serial(p.USART2);
+//!     serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC);
+//!     serial.listen(Event::Rxne);
 //! 
-//! // INITIALIZATION PHASE
-//! fn init(ref priority: P0, threshold: &TMax) {
-//!     let gpioa = GPIOA.access(priority, threshold);
-//!     let gpioe = GPIOE.access(priority, threshold);
-//!     let rcc = RCC.access(priority, threshold);
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
-//!     let usart1 = USART1.access(priority, threshold);
-//! 
-//!     led::init(&gpioe, &rcc);
-//!     timer.init(&rcc, FREQUENCY);
-//!     Serial(&usart1).init(&gpioa, &rcc, BAUD_RATE);
-//! 
-//!     timer.resume();
+//!     p.SYST.set_clock_source(SystClkSource::Core);
+//!     p.SYST.set_reload(8_000_000 / DIVISOR);
+//!     p.SYST.enable_interrupt();
+//!     p.SYST.enable_counter();
 //! }
 //! 
 //! // IDLE LOOP
-//! fn idle(_priority: P0, _threshold: T0) -> ! {
+//! fn idle() -> ! {
 //!     // Sleep
 //!     loop {
 //!         rtfm::wfi();
@@ -131,113 +82,104 @@
 //! }
 //! 
 //! // TASKS
-//! tasks!(stm32f30x, {
-//!     roulette: Task {
-//!         interrupt: Tim7,
-//!         priority: P2, // changed to `P2`
-//!         enabled: true,
-//!     },
-//!     receive: Task {
-//!         interrupt: Usart1Exti25,
-//!         priority: P1,
-//!         enabled: true,
-//!     },
-//! });
+//! fn receive(t: &mut Threshold, mut r: USART2::Resources) {
+//!     let serial = Serial(&**r.USART2);
 //! 
-//! fn receive(mut task: Usart1Exti25, ref priority: P1, ref threshold: T1) {
-//!     static BUFFER: Local<Vec<u8, [u8; 16]>, Usart1Exti25> = {
-//!         Local::new(Vec::new([0; 16]))
-//!     };
+//!     let byte = serial.read().unwrap();
+//!     if serial.write(byte).is_err() {
+//!         // As we are echoing the bytes as soon as they arrive, it should
+//!         // be impossible to have a TX buffer overrun
+//!         #[cfg(debug_assertions)]
+//!         unreachable!()
+//!     }
 //! 
-//!     let usart1 = USART1.access(priority, threshold);
-//!     let serial = Serial(&usart1);
+//!     if byte == b'r' {
+//!         // end of command
 //! 
-//!     if let Ok(byte) = serial.read() {
-//!         if serial.write(byte).is_err() {
-//!             // As we are echoing the bytes as soon as they arrive, it should
-//!             // be impossible to have a TX buffer overrun
-//!             #[cfg(debug_assertions)]
-//!             unreachable!()
-//!         }
-//! 
-//!         let buffer = BUFFER.borrow_mut(&mut task);
-//! 
-//!         if byte == b'r' {
-//!             // end of command
-//! 
-//!             match &**buffer {
-//!                 b"bounce" => {
-//!                     threshold.raise(
-//!                         &SHARED, |threshold| {
-//!                             let shared = SHARED.access(priority, threshold);
-//!                             shared.mode.set(Mode::Bounce)
-//!                         }
-//!                     );
-//!                 }
-//!                 b"continuous" => {
-//!                     threshold.raise(
-//!                         &SHARED, |threshold| {
-//!                             let shared = SHARED.access(priority, threshold);
-//!                             shared.mode.set(Mode::Continuous)
-//!                         }
-//!                     );
-//!                 }
-//!                 b"reverse" => {
-//!                     threshold.raise(&SHARED, |threshold| {
-//!                         let shared = SHARED.access(priority, threshold);
-//!                         shared.direction.set(shared.direction.get().reverse());
-//!                     });
-//!                 }
-//!                 _ => {}
+//!         match &***r.BUFFER {
+//!             b"bounce" => {
+//!                 r.SHARED
+//!                     .claim_mut(t, |shared, _| { shared.mode = Mode::Bounce; });
 //!             }
-//! 
-//!             buffer.clear();
-//!         } else {
-//!             if buffer.push(byte).is_err() {
-//!                 // error: buffer full
-//!                 // KISS: we just clear the buffer when it gets full
-//!                 buffer.clear();
+//!             b"continuous" => {
+//!                 r.SHARED.claim_mut(
+//!                     t,
+//!                     |shared, _| { shared.mode = Mode::Continuous; },
+//!                 );
+//!             }
+//!             b"reverse" => {
+//!                 r.SHARED.claim_mut(t, |shared, _| {
+//!                     shared.direction = shared.direction.reverse();
+//!                 });
 //!             }
+//!             _ => {}
 //!         }
+//! 
+//!         r.BUFFER.clear();
 //!     } else {
-//!         // Only reachable through `rtfm::request(receive)`
-//!         #[cfg(debug_assertions)]
-//!         unreachable!()
+//!         if r.BUFFER.push(byte).is_err() {
+//!             // error: buffer full
+//!             // KISS: we just clear the buffer when it gets full
+//!             r.BUFFER.clear();
+//!         }
 //!     }
 //! }
 //! 
-//! fn roulette(mut task: Tim7, ref priority: P2, ref threshold: T2) {
-//!     static STATE: Local<u8, Tim7> = Local::new(0);
+//! fn roulette(_t: &mut Threshold, r: SYS_TICK::Resources) {
+//!     let curr = **r.STATE;
+//! 
+//!     let mut direction = r.SHARED.direction;
 //! 
-//!     let tim7 = TIM7.access(priority, threshold);
-//!     let timer = Timer(&tim7);
+//!     if curr == 0 && r.SHARED.mode == Mode::Bounce {
+//!         direction = direction.reverse();
+//!         r.SHARED.direction = direction;
+//!     }
+//! 
+//!     let n = u8(LEDS.len()).unwrap();
+//!     let next = match direction {
+//!         Direction::Clockwise => (curr + 1) % n,
+//!         Direction::Counterclockwise => curr.checked_sub(1).unwrap_or(n - 1),
+//!     };
 //! 
-//!     if timer.clear_update_flag().is_ok() {
-//!         let state = STATE.borrow_mut(&mut task);
-//!         let curr = *state;
+//!     LEDS[usize(curr)].off();
+//!     LEDS[usize(next)].on();
 //! 
-//!         let shared = SHARED.access(priority, threshold);
-//!         let mut direction = shared.direction.get();
+//!     **r.STATE = next;
+//! }
+//! 
+//! // SUPPORT CODE
+//! #[derive(Clone, Copy)]
+//! enum Direction {
+//!     Clockwise,
+//!     Counterclockwise,
+//! }
 //! 
-//!         if curr == 0 && shared.mode.get() == Mode::Bounce {
-//!             direction = direction.reverse();
-//!             shared.direction.set(direction);
+//! impl Direction {
+//!     fn reverse(self) -> Self {
+//!         match self {
+//!             Direction::Clockwise => Direction::Counterclockwise,
+//!             Direction::Counterclockwise => Direction::Clockwise,
 //!         }
+//!     }
+//! }
 //! 
-//!         let n = u8(LEDS.len()).unwrap();
-//!         let next = match direction {
-//!             Direction::Clockwise => (curr + 1) % n,
-//!             Direction::Counterclockwise => curr.checked_sub(1).unwrap_or(n - 1),
-//!         };
+//! #[derive(Clone, Copy, PartialEq)]
+//! enum Mode {
+//!     Bounce,
+//!     Continuous,
+//! }
 //! 
-//!         LEDS[usize(curr)].off();
-//!         LEDS[usize(next)].on();
+//! pub struct State {
+//!     direction: Direction,
+//!     mode: Mode,
+//! }
 //! 
-//!         *state = next;
-//!     } else {
-//!         // Only reachable through `rtfm::request(roulette)`
-//!         #[cfg(debug_assertion)]
-//!         unreachable!()
+//! impl State {
+//!     const fn new() -> Self {
+//!         State {
+//!             direction: Direction::Clockwise,
+//!             mode: Mode::Continuous,
+//!         }
 //!     }
 //! }
 //! ```
diff --git a/src/frequency.rs b/src/frequency.rs
index ce5eb546e826c89aafce968d20b0a56649d7eb42..8fedc3a7bbb92fb22aeeab1face933f2771adffd 100644
--- a/src/frequency.rs
+++ b/src/frequency.rs
@@ -1,4 +1,4 @@
-//! Definition of bus frequency details for f3.
+//! Definition of bus frequency details for f4.
 
 macro_rules! frequency {
     ($FREQUENCY:expr) => {
@@ -72,15 +72,15 @@ macro_rules! frequency {
 
 /// Advance High-performance Bus (AHB)
 pub mod ahb {
-    frequency!(8_000_000);
+    frequency!(16_000_000);
 }
 
 /// Advance Peripheral Bus 1 (APB1)
 pub mod apb1 {
-    frequency!(8_000_000);
+    frequency!(16_000_000);
 }
 
 /// Advance Peripheral Bus 2 (APB2)
 pub mod apb2 {
-    frequency!(8_000_000);
+    frequency!(16_000_000);
 }
diff --git a/src/led.rs b/src/led.rs
index ccd3c6b09c764b786ac52aabd6d2ab5b5cc02881..98dc55147436c14bee6c61d15a03bf26e4bba268 100644
--- a/src/led.rs
+++ b/src/led.rs
@@ -1,17 +1,10 @@
 //! User LEDs
 
-use stm32f30x::{GPIOE, RCC};
+use stm32f40x::{GPIOA, RCC};
 
 /// All the user LEDs
-pub static LEDS: [Led; 8] = [
-    Led { i: 9 },
-    Led { i: 10 },
-    Led { i: 11 },
-    Led { i: 12 },
-    Led { i: 13 },
-    Led { i: 14 },
-    Led { i: 15 },
-    Led { i: 8 },
+pub static LEDS: [Led; 1] = [
+    Led { i: 5 },
 ];
 
 /// An LED
@@ -23,42 +16,28 @@ impl Led {
     /// Turns off the LED
     pub fn off(&self) {
         // NOTE(safe) atomic write
-        unsafe { (*GPIOE.get()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
+        unsafe { (*GPIOA.get()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
     }
 
     /// Turns on the LED
     pub fn on(&self) {
         // NOTE(safe) atomic write
-        unsafe { (*GPIOE.get()).bsrr.write(|w| w.bits(1 << self.i)) }
+        unsafe { (*GPIOA.get()).bsrr.write(|w| w.bits(1 << self.i)) }
     }
 }
 
 /// Initializes all the user LEDs
-pub fn init(gpioe: &GPIOE, rcc: &RCC) {
+pub fn init(gpioa: &GPIOA, rcc: &RCC) {
     // Power up peripherals
-    rcc.ahbenr.modify(|_, w| w.iopeen().enabled());
+    rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
 
     // Configure pins 8-15 as outputs
-    gpioe
+    gpioa
         .moder
         .modify(
             |_, w| {
-                w.moder8()
-                    .output()
-                    .moder9()
-                    .output()
-                    .moder10()
-                    .output()
-                    .moder11()
-                    .output()
-                    .moder12()
-                    .output()
-                    .moder13()
-                    .output()
-                    .moder14()
-                    .output()
-                    .moder15()
-                    .output()
+                w.moder5()
+                    .bits(1)
             },
         );
 }
diff --git a/src/lib.rs b/src/lib.rs
index 3eb80ab24a0fe2eabcedb7265643c4b81aa03a17..765f9642a562476bc63c22ab42c28c8eba7858b8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -30,7 +30,7 @@ extern crate embedded_hal as hal;
 extern crate nb;
 extern crate static_ref;
 
-pub extern crate stm32f30x;
+pub extern crate stm32f40x;
 
 // For documentation only
 pub mod examples;
diff --git a/src/serial.rs b/src/serial.rs
index 2f292af6b3306046303c22ad9711b4a07f887c9a..1039e0835f85df198801243db51dc7956d695982 100644
--- a/src/serial.rs
+++ b/src/serial.rs
@@ -2,11 +2,11 @@
 //!
 //! You can use the `Serial` interface with these USART instances
 //!
-//! # USART1
+//! # USART2
 //!
-//! - TX = PA9
-//! - RX = PA10
-//! - Interrupt = USART1
+//! - TX = PA2
+//! - RX = PA3
+//! - Interrupt = USART2
 
 use core::any::{Any, TypeId};
 use core::marker::Unsize;
@@ -17,23 +17,23 @@ use cast::u16;
 use hal;
 use nb;
 use static_ref::Static;
-use stm32f30x::{gpioa, DMA1, USART1, usart1, GPIOA,
+use stm32f40x::{gpioa, DMA1, USART2, usart6, GPIOA,
                   RCC};
 
-use dma::{self, Buffer, Dma1Channel4, Dma1Channel5};
+use dma::{self, Buffer, Dma1Channel6, Dma1Channel5};
 
 /// Specialized `Result` type
 pub type Result<T> = ::core::result::Result<T, nb::Error<Error>>;
 
 /// IMPLEMENTATION DETAIL
-pub unsafe trait Usart: Deref<Target = usart1::RegisterBlock> {
+pub unsafe trait Usart: Deref<Target = usart6::RegisterBlock> {
     /// IMPLEMENTATION DETAIL
     type GPIO: Deref<Target = gpioa::RegisterBlock>;
     /// IMPLEMENTATION DETAIL
     type Ticks: Into<u32>;
 }
 
-unsafe impl Usart for USART1 {
+unsafe impl Usart for USART2 {
     type GPIO = GPIOA;
     type Ticks = ::apb2::Ticks;
 }
@@ -117,31 +117,29 @@ where
 
         // power up peripherals
         if dma1.is_some() {
-            rcc.ahbenr.modify(|_, w| w.dmaen().enabled());
+            rcc.ahb1enr.modify(|_, w| w.dma1en().set_bit());
         }
-        if usart.get_type_id() == TypeId::of::<USART1>() {
-            rcc.apb2enr.modify(|_, w| {
-                w.usart1en().enabled()
+        if usart.get_type_id() == TypeId::of::<USART2>() {
+            rcc.apb1enr.modify(|_, w| {
+                w.usart2en().set_bit()
             });
         }
 
-        rcc.ahbenr.modify(|_, w| w.iopaen().set_bit());
+        rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
 
-        if usart.get_type_id() == TypeId::of::<USART1>() {
-            // PA9. = TX, PA10 = RX
-            gpio.afrh.modify(|_, w| {
-                unsafe {
-                    w.afrh9().bits(7).afrh10().bits(7)
-                }
+        if usart.get_type_id() == TypeId::of::<USART2>() {
+            // PA2. = TX, PA3 = RX
+            gpio.afrl.modify(|_, w| {
+                    w.afrl2().bits(7).afrl3().bits(7)
             });
             gpio.moder.modify(|_, w| {
-                w.moder9().alternate()
-                    .moder10().alternate()
+                w.moder2().bits(2)
+                    .moder3().bits(2)
             });
         }
 
         if let Some(dma1) = dma1 {
-            if usart.get_type_id() == TypeId::of::<USART1>() {
+            if usart.get_type_id() == TypeId::of::<USART2>() {
                 // TX DMA transfer
                 // mem2mem: Memory to memory mode disabled
                 // pl: Medium priority
@@ -153,10 +151,8 @@ where
                 // dir: Transfer from memory to peripheral
                 // tceie: Transfer complete interrupt enabled
                 // en: Disabled
-                dma1.ccr4.write(|w| unsafe {
-                    w.mem2mem()
-                        .clear_bit()
-                        .pl()
+                dma1.s6cr.write(|w| unsafe {
+                    w.pl()
                         .bits(0b01)
                         .msize()
                         .bits(0b00)
@@ -169,7 +165,7 @@ where
                         .pinc()
                         .clear_bit()
                         .dir()
-                        .set_bit()
+                        .bits(1)
                         .tcie()
                         .set_bit()
                         .en()
@@ -187,10 +183,8 @@ where
                 // dir: Transfer from peripheral to memory
                 // tceie: Transfer complete interrupt enabled
                 // en: Disabled
-                dma1.ccr5.write(|w| unsafe {
-                    w.mem2mem()
-                        .clear_bit()
-                        .pl()
+                dma1.s5cr.write(|w| unsafe {
+                    w.pl()
                         .bits(0b01)
                         .msize()
                         .bits(0b00)
@@ -203,7 +197,7 @@ where
                         .pinc()
                         .clear_bit()
                         .dir()
-                        .clear_bit()
+                        .bits(0)
                         .tcie()
                         .set_bit()
                         .en()
@@ -282,8 +276,8 @@ where
     type Error = Error;
 
     fn read(&self) -> Result<u8> {
-        let usart1 = self.0;
-        let sr = usart1.isr.read();
+        let usart2 = self.0;
+        let sr = usart2.sr.read();
 
         if sr.ore().bit_is_set() {
             Err(nb::Error::Other(Error::Overrun))
@@ -295,7 +289,7 @@ where
             // NOTE(read_volatile) the register is 9 bits big but we'll only
             // work with the first 8 bits
             Ok(unsafe {
-                ptr::read_volatile(&usart1.rdr as *const _ as *const u8)
+                ptr::read_volatile(&usart2.dr as *const _ as *const u8)
             })
         } else {
             Err(nb::Error::WouldBlock)
@@ -310,8 +304,8 @@ where
     type Error = Error;
 
     fn write(&self, byte: u8) -> Result<()> {
-        let usart1 = self.0;
-        let sr = usart1.isr.read();
+        let usart2 = self.0;
+        let sr = usart2.sr.read();
 
         if sr.ore().bit_is_set() {
             Err(nb::Error::Other(Error::Overrun))
@@ -322,7 +316,7 @@ where
         } else if sr.txe().bit_is_set() {
             // NOTE(write_volatile) see NOTE in the `read` method
             unsafe {
-                ptr::write_volatile(&usart1.tdr as *const _ as *mut u8, byte)
+                ptr::write_volatile(&usart2.dr as *const _ as *mut u8, byte)
             }
             Ok(())
         } else {
@@ -331,7 +325,7 @@ where
     }
 }
 
-impl<'a> Serial<'a, USART1> {
+impl<'a> Serial<'a, USART2> {
     /// Starts a DMA transfer to receive serial data into a `buffer`
     ///
     /// This will mutably lock the `buffer` preventing borrowing its contents
@@ -346,21 +340,21 @@ impl<'a> Serial<'a, USART1> {
     where
         B: Unsize<[u8]>,
     {
-        let usart1 = self.0;
+        let usart2 = self.0;
 
-        if dma1.ccr5.read().en().bit_is_set() {
+        if dma1.s5cr.read().en().bit_is_set() {
             return Err(dma::Error::InUse);
         }
 
         let buffer: &mut [u8] = buffer.lock_mut();
 
-        dma1.cndtr5
+        dma1.s5ndtr
             .write(|w| unsafe { w.ndt().bits(u16(buffer.len()).unwrap()) });
-        dma1.cpar5
-            .write(|w| unsafe { w.bits(&usart1.rdr as *const _ as u32) });
-        dma1.cmar5
+        dma1.s5par
+            .write(|w| unsafe { w.bits(&usart2.dr as *const _ as u32) });
+        dma1.s5m0ar
             .write(|w| unsafe { w.bits(buffer.as_ptr() as u32) });
-        dma1.ccr5.modify(|_, w| w.en().set_bit());
+        dma1.s5cr.modify(|_, w| w.en().set_bit());
 
         Ok(())
     }
@@ -372,26 +366,26 @@ impl<'a> Serial<'a, USART1> {
     pub fn write_all<B>(
         &self,
         dma1: &DMA1,
-        buffer: &Static<Buffer<B, Dma1Channel4>>,
+        buffer: &Static<Buffer<B, Dma1Channel6>>,
     ) -> ::core::result::Result<(), dma::Error>
     where
         B: Unsize<[u8]>,
     {
-        let usart1 = self.0;
+        let usart2 = self.0;
 
-        if dma1.ccr4.read().en().bit_is_set() {
+        if dma1.s6cr.read().en().bit_is_set() {
             return Err(dma::Error::InUse);
         }
 
         let buffer: &[u8] = buffer.lock();
 
-        dma1.cndtr4
+        dma1.s6ndtr
             .write(|w| unsafe { w.ndt().bits(u16(buffer.len()).unwrap()) });
-        dma1.cpar4
-            .write(|w| unsafe { w.bits(&usart1.tdr as *const _ as u32) });
-        dma1.cmar4
+        dma1.s6par
+            .write(|w| unsafe { w.bits(&usart2.dr as *const _ as u32) });
+        dma1.s6m0ar
             .write(|w| unsafe { w.bits(buffer.as_ptr() as u32) });
-        dma1.ccr4.modify(|_, w| w.en().set_bit());
+        dma1.s6cr.modify(|_, w| w.en().set_bit());
 
         Ok(())
     }
diff --git a/src/timer.rs b/src/timer.rs
index 41d41300e65266a2ba9ae33e85703cdc1bcdd5c1..8b0db4196d2c8902560d06d0918f7458087c00fc 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -3,7 +3,7 @@
 use core::u16;
 
 use cast::{u16, u32};
-use stm32f30x::{RCC, TIM7};
+use stm32f40x::{RCC, TIM11};
 
 /// Specialized `Result` type
 pub type Result<T> = ::core::result::Result<T, Error>;
@@ -17,50 +17,50 @@ pub struct Error {
 ///
 /// # Interrupts
 ///
-/// - `Tim7` - update event
-pub struct Timer<'a>(pub &'a TIM7);
+/// - `Tim11` - update event
+pub struct Timer<'a>(pub &'a TIM11);
 
 impl<'a> Timer<'a> {
     /// Initializes the timer with a periodic timeout of `frequency` Hz
     ///
     /// NOTE After initialization, the timer will be in the paused state.
     pub fn init(&self, rcc: &RCC, frequency: u32) {
-        let tim7 = self.0;
+        let tim11 = self.0;
 
         // Power up peripherals
-        rcc.apb1enr.modify(|_, w| w.tim7en().enabled());
+        rcc.apb2enr.modify(|_, w| w.tim11en().set_bit());
 
         let ratio = ::apb1::FREQUENCY / frequency;
         let psc = u16((ratio - 1) / u32(u16::MAX)).unwrap();
-        tim7.psc.write(|w| w.psc().bits(psc));
+        tim11.psc.write(|w| unsafe{w.psc().bits(psc)});
         let arr = u16(ratio / u32(psc + 1)).unwrap();
-        tim7.arr.write(|w| w.arr().bits(arr));
+        tim11.arr.write(|w| unsafe{ w.arr().bits(arr)});
 
-        tim7.dier.write(|w| w.uie().set_bit());
-        tim7.cr1.write(|w| w.opm().continuous());
+        tim11.dier.write(|w| w.uie().set_bit());
+        // tim7.cr1.write(|w| w.opm().continuous());
     }
 
     /// Clears the update event flag
     ///
     /// Returns `Err` if no update event has occurred
     pub fn clear_update_flag(&self) -> Result<()> {
-        let tim7 = self.0;
+        let tim11 = self.0;
 
-        if tim7.sr.read().uif().is_no_update() {
+        if tim11.sr.read().uif().bit_is_clear() {
             Err(Error { _0: () })
         } else {
-            self.0.sr.modify(|_, w| w.uif().clear());
+            self.0.sr.modify(|_, w| w.uif().clear_bit());
             Ok(())
         }
     }
 
     /// Resumes the timer count
     pub fn resume(&self) {
-        self.0.cr1.modify(|_, w| w.cen().enabled());
+        self.0.cr1.modify(|_, w| w.cen().set_bit());
     }
 
     /// Pauses the timer
     pub fn pause(&self) {
-        self.0.cr1.modify(|_, w| w.cen().disabled());
+        self.0.cr1.modify(|_, w| w.cen().clear_bit());
     }
 }