diff --git a/examples/blinky-blocking.rs b/examples/blinky-blocking.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9a09898504625a53a9901723f72c67a30caba5d1
--- /dev/null
+++ b/examples/blinky-blocking.rs
@@ -0,0 +1,56 @@
+//! Blocking version of blinky
+
+#![allow(unreachable_code)] // for the `block!` macro
+#![deny(unsafe_code)]
+#![deny(warnings)]
+#![feature(proc_macro)]
+#![no_std]
+
+extern crate f4;
+
+extern crate cortex_m_rtfm as rtfm;
+
+#[macro_use(block)]
+extern crate nb;
+
+use f4::Timer;
+use f4::led::{self, LED};
+use f4::prelude::*;
+use f4::time::Hertz;
+use rtfm::{app, Threshold};
+
+const FREQUENCY: Hertz = Hertz(1);
+
+app! {
+    device: f4::stm32f40x,
+
+    idle: {
+        resources: [TIM11],
+    }
+}
+
+fn init(p: init::Peripherals) {
+    led::init(p.GPIOA, p.RCC);
+
+    let timer = Timer(&*p.TIM11);
+
+    timer.init(FREQUENCY.invert(), p.RCC);
+}
+
+fn idle(_t: &mut Threshold, r: idle::Resources) -> ! {
+    let timer = Timer(&*r.TIM11);
+
+    timer.resume();
+    let mut state = false;
+    loop {
+        block!(timer.wait()).unwrap(); // NOTE(unwrap) E = !
+
+        state = !state;
+
+        if state {
+            LED.on();
+        } else {
+            LED.off();
+        }
+    }
+}
diff --git a/examples/blinky.rs b/examples/blinky.rs
index f048a4e867d74dec04d19d9a88058d5d056f4476..63b927ea1854767a0e651c860555b0fa2c99ea6c 100644
--- a/examples/blinky.rs
+++ b/examples/blinky.rs
@@ -13,7 +13,7 @@ use f4::led::{self, LEDS};
 use rtfm::{app, Threshold};
 
 // CONFIGURATION
-const FREQUENCY: u32 = 4; // Hz
+const FREQUENCY: u32 = 1; // Hz
 
 // TASKS & RESOURCES
 app! {
diff --git a/src/led.rs b/src/led.rs
index e8582ae2db472e378e888baf3bc783f5ad191500..eb3e7119614d9ce93d52f87b70ca344953204929 100644
--- a/src/led.rs
+++ b/src/led.rs
@@ -1,57 +1,37 @@
 //! User LEDs
+//!
+//! - PA5
 
-use stm32f40x::{GPIOB, RCC};
-
-/// All the user LEDs
-pub static LEDS: [Led; 8] = [
-    Led { i: 2 },
-    Led { i: 1 },
-    Led { i: 15 },
-    Led { i: 14 },
-    Led { i: 13 },
-    Led { i: 5 },
-    Led { i: 4 },
-    Led { i: 10 },
-];
-
-/// An LED
-pub struct Led {
-    i: u8,
-}
+use stm32f40x::{GPIOA, RCC};
 
-impl Led {
-    /// Turns off the LED
-    pub fn off(&self) {
-        // NOTE(safe) atomic write
-        unsafe { (*GPIOB.get()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
-    }
+/// LED connected to pin PC13
+pub const LED: PA5 = PA5;
+
+/// Pin PA5. There's an LED connected to this pin
+pub struct PA5;
+
+/// Initializes the user LED
+pub fn init(gpioa: &GPIOA, rcc: &RCC) {
+    // power on GPIOC
+    rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+
+    // configure PC13 as output
+    gpioa.moder.write(|w| w.moder5().bits(1));
 
-    /// Turns on the LED
+}
+
+impl PA5 {
+    /// Turns the LED on
     pub fn on(&self) {
-        // NOTE(safe) atomic write
-        unsafe { (*GPIOB.get()).bsrr.write(|w| w.bits(1 << self.i)) }
+        unsafe {
+            (*GPIOA.get()).odr.write(|w| w.odr5().bit(false));
+        }
     }
-}
 
-/// Initializes all the user LEDs
-pub fn init(gpioa: &GPIOB, rcc: &RCC) {
-    // Power up peripherals
-    rcc.ahb1enr.modify(|_, w| w.gpioben().set_bit());
-
-    // Configure pins 8-15 as outputs
-    gpioa
-        .moder
-        .modify(
-            |_, w| {unsafe {
-                w.moder2().bits(1)
-                .moder1().bits(1)
-                .moder15().bits(1)
-                .moder14().bits(1)
-                .moder13().bits(1)
-                .moder5().bits(1)
-                .moder4().bits(1)
-                .moder10().bits(1)
-                }
-            },
-        );
-}
+    /// Turns the LED off
+    pub fn off(&self) {
+        unsafe {
+            (*GPIOA.get()).odr.write(|w| w.odr5().bit(true));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 765f9642a562476bc63c22ab42c28c8eba7858b8..34744a15a1776828e6c1d87a3d27d40bc1159420 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -46,4 +46,5 @@ use frequency::*;
 
 pub use hal::prelude;
 pub use serial::Serial;
+pub use timer::{Channel, Timer};
 
diff --git a/src/timer.rs b/src/timer.rs
index 8b0db4196d2c8902560d06d0918f7458087c00fc..9dab206d5c2115cf57b608f7277c2ddfce63efb3 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -1,66 +1,145 @@
-//! Periodic timer
+//! Timer
 
-use core::u16;
+use core::any::{Any, TypeId};
 
 use cast::{u16, u32};
-use stm32f40x::{RCC, TIM11};
+use hal;
+use nb::{self, Error};
+use stm32f40x::{TIM1, TIM2, TIM3, TIM4, TIM5, TIM9, TIM10, TIM11, RCC};
 
-/// Specialized `Result` type
-pub type Result<T> = ::core::result::Result<T, Error>;
-
-/// An error
-pub struct Error {
-    _0: (),
+/// Channel associated to a timer
+#[derive(Clone, Copy, Debug)]
+pub enum Channel {
+    /// TxC1
+    _1,
+    /// TxC2
+    _2,
+    /// TxC3
+    _3,
+    /// TxC4
+    _4,
 }
 
-/// Periodic timer
-///
-/// # Interrupts
-///
-/// - `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 tim11 = self.0;
-
-        // Power up peripherals
-        rcc.apb2enr.modify(|_, w| w.tim11en().set_bit());
-
-        let ratio = ::apb1::FREQUENCY / frequency;
-        let psc = u16((ratio - 1) / u32(u16::MAX)).unwrap();
-        tim11.psc.write(|w| unsafe{w.psc().bits(psc)});
-        let arr = u16(ratio / u32(psc + 1)).unwrap();
-        tim11.arr.write(|w| unsafe{ w.arr().bits(arr)});
-
-        tim11.dier.write(|w| w.uie().set_bit());
-        // tim7.cr1.write(|w| w.opm().continuous());
+
+/// `hal::Timer` implementation
+pub struct Timer<'a, T>(pub &'a T)
+where
+    T: 'a;
+
+impl<'a, T> Clone for Timer<'a, T> {
+    fn clone(&self) -> Self {
+        *self
     }
+}
+
+impl<'a, T> Copy for Timer<'a, T> {}
+
+macro_rules! impl_Timer {
+    ($TIM:ident, $APB:ident) => {
+        impl<'a> Timer<'a, $TIM>
+        {
+            /// Initializes the timer with a periodic timeout of `frequency` Hz
+            ///
+            /// NOTE After initialization, the timer will be in the paused state.
+            pub fn init<P>(&self, period: P, rcc: &RCC)
+            where
+                P: Into<::$APB::Ticks>,
+            {
+                self.init_(period.into(), rcc)
+            }
+
+            fn init_(&self, timeout: ::$APB::Ticks, rcc: &RCC) {
+                let tim = self.0;
+
+                // Enable TIMx
+                // Reference manual does not mention TIM6-8, TIM 12-14 
+                // although they are implemented in device crate...
+                if tim.get_type_id() == TypeId::of::<TIM1>() {
+                    rcc.apb2enr.modify(|_, w| w.tim1en().set_bit());
+                } else if tim.get_type_id() == TypeId::of::<TIM2>() {
+                    rcc.apb1enr.modify(|_, w| w.tim2en().set_bit());
+                } else if tim.get_type_id() == TypeId::of::<TIM3>() {
+                    rcc.apb1enr.modify(|_, w| w.tim3en().set_bit());
+                } else if tim.get_type_id() == TypeId::of::<TIM4>() {
+                    rcc.apb1enr.modify(|_, w| w.tim4en().set_bit());
+                } else if tim.get_type_id() == TypeId::of::<TIM5>() {
+                    rcc.apb1enr.modify(|_, w| w.tim5en().set_bit());
+                } else if tim.get_type_id() == TypeId::of::<TIM9>() {
+                    rcc.apb2enr.modify(|_, w| w.tim9en().set_bit());
+                } else if tim.get_type_id() == TypeId::of::<TIM10>() {
+                    rcc.apb2enr.modify(|_, w| w.tim10en().set_bit());
+                } else if tim.get_type_id() == TypeId::of::<TIM11>() {
+                    rcc.apb2enr.modify(|_, w| w.tim11en().set_bit());
+                }
+
+                // Configure periodic update event
+                self._set_timeout(timeout);
+
+                // Continuous mode
+                // tim2.cr1.write(|w| w.opm().continuous());
+
+                // Enable the update event interrupt
+                tim.dier.modify(|_, w| w.uie().set_bit());
+            }
 
-    /// Clears the update event flag
-    ///
-    /// Returns `Err` if no update event has occurred
-    pub fn clear_update_flag(&self) -> Result<()> {
-        let tim11 = self.0;
-
-        if tim11.sr.read().uif().bit_is_clear() {
-            Err(Error { _0: () })
-        } else {
-            self.0.sr.modify(|_, w| w.uif().clear_bit());
-            Ok(())
+            fn _set_timeout(&self, timeout: ::$APB::Ticks) {
+                let period = timeout.0;
+
+                let psc = u16((period - 1) / (1 << 16)).unwrap();
+                self.0.psc.write(|w| unsafe{w.psc().bits(psc)});
+
+                let arr = u32(period / u32(psc + 1));
+                self.0.arr.write(|w| unsafe{w.bits(arr)});
+            }
         }
-    }
 
-    /// Resumes the timer count
-    pub fn resume(&self) {
-        self.0.cr1.modify(|_, w| w.cen().set_bit());
-    }
+        impl<'a> hal::Timer for Timer<'a, $TIM>
+            {
+            type Time = ::$APB::Ticks;
+
+            fn get_timeout(&self) -> ::$APB::Ticks {
+                    ::$APB::Ticks(
+                        u32(self.0.psc.read().psc().bits() + 1) *
+                            u32(self.0.arr.read().bits()),
+                    )
+                }
 
-    /// Pauses the timer
-    pub fn pause(&self) {
-        self.0.cr1.modify(|_, w| w.cen().clear_bit());
+                fn pause(&self) {
+                    self.0.cr1.modify(|_, w| w.cen().clear_bit());
+                }
+
+                fn restart(&self) {
+                    self.0.cnt.write(|w| unsafe{w.bits(0)});
+                }
+
+                fn resume(&self) {
+                    self.0.cr1.modify(|_, w| w.cen().set_bit());
+                }
+
+                fn set_timeout<TO>(&self, timeout: TO)
+                where
+                    TO: Into<::$APB::Ticks>,
+                {
+                    self._set_timeout(timeout.into())
+                }
+
+                fn wait(&self) -> nb::Result<(), !> {
+                    if self.0.sr.read().uif().bit_is_clear() {
+                        Err(Error::WouldBlock)
+                    } else {
+                        self.0.sr.modify(|_, w| w.uif().clear_bit());
+                        Ok(())
+                    }
+                }
+            }
     }
 }
+
+impl_Timer!(TIM1, apb2);
+impl_Timer!(TIM2, apb1);
+impl_Timer!(TIM3, apb1);
+impl_Timer!(TIM4, apb1);
+impl_Timer!(TIM5, apb1);
+impl_Timer!(TIM9, apb2);
+impl_Timer!(TIM10, apb2);
+impl_Timer!(TIM11, apb2);