diff --git a/src/lib.rs b/src/lib.rs
index 28148346fa72a1d25655f67407d4814ad0745573..aa7242ff359adc862746440e08e5f86fdf2e07d8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -37,6 +37,6 @@ pub mod rcc;
 pub mod serial;
 // pub mod spi;
 pub mod time;
-// pub mod timer;
+pub mod timer;
 
 pub mod led;
diff --git a/src/timer.rs b/src/timer.rs
index b1aff91fc39f3b75e677bd4319f3b8017af11d8c..4e644aa2b7957adf28064b11aeac3134407c039c 100644
--- a/src/timer.rs
+++ b/src/timer.rs
@@ -1,9 +1,11 @@
 //! Timers
+use cortex_m::peripheral::SYST;
+use cortex_m::peripheral::syst::SystClkSource;
 
 use cast::{u16, u32};
 use hal::timer::{CountDown, Periodic};
 use nb;
-use stm32f30x::{TIM2, TIM3, TIM4, TIM6, TIM7};
+use stm32f4x::{TIM2, TIM3, TIM4, TIM6, TIM7};
 
 use rcc::{APB1, Clocks};
 use time::Hertz;
@@ -21,6 +23,64 @@ pub enum Event {
     TimeOut,
 }
 
+impl Timer<SYST> {
+    /// start systic timer
+    pub fn syst<T>(mut syst: SYST, timeout: T, clocks: Clocks) -> Self
+    where
+        T: Into<Hertz>,
+    {
+        syst.set_clock_source(SystClkSource::Core);
+        let mut timer = Timer {
+            tim: syst,
+            clocks: clocks,
+            timeout: Hertz(0),
+        };
+        timer.start(timeout);
+        timer
+    }
+
+    /// Starts listening for an `event`
+    pub fn listen(&mut self, event: Event) {
+        match event {
+            Event::TimeOut => self.tim.enable_interrupt(),
+        }
+    }
+
+    /// Stops listening for an `event`
+    pub fn unlisten(&mut self, event: Event) {
+        match event {
+            Event::TimeOut => self.tim.disable_interrupt(),
+        }
+    }
+}
+
+impl CountDown for Timer<SYST> {
+    type Time = Hertz;
+
+    fn start<T>(&mut self, timeout: T)
+    where
+        T: Into<Hertz>,
+    {
+        let rvr = self.clocks.sysclk().0 / timeout.into().0 - 1;
+
+        assert!(rvr < (1 << 24));
+
+        self.tim.set_reload(rvr);
+        self.tim.clear_current();
+        self.tim.enable_counter();
+    }
+
+    fn wait(&mut self) -> nb::Result<(), !> {
+        if self.tim.has_wrapped() {
+            Ok(())
+        } else {
+            Err(nb::Error::WouldBlock)
+        }
+    }
+}
+
+impl Periodic for Timer<SYST> {}
+
 macro_rules! hal {
     ($($TIM:ident: ($tim:ident, $timXen:ident, $timXrst:ident),)+) => {
         $(