diff --git a/.vscode/launch.json b/.vscode/launch.json
index 130ad1f0c000ab9d02cc1deeb69508ef50d8cc66..dd5712aaa74f417d8f1129ab96732ac4423bdb3a 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -66,6 +66,21 @@
             ],
             "cwd": "${workspaceRoot}"
         },
+        {
+            "type": "gdb",
+            "request": "attach",
+            "name": "Debug usart_clk",
+            "gdbpath": "/usr/bin/arm-none-eabi-gdb",
+            "target": ":3333",
+            "remote": true,
+            "autorun": [
+                "monitor reset init",
+                "monitor arm semihosting enable",
+                "file ./target/thumbv7em-none-eabihf/debug/examples/usart_clk",
+                "load"
+            ],
+            "cwd": "${workspaceRoot}"
+        },
         {
             "type": "gdb",
             "request": "attach",
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 5b92a69c579dceef58622eaa08c90cc7b0fadb73..3291c4dd235f68026e468efbb1cb141f8b6d1e5a 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -35,6 +35,18 @@
                 "$rustc"
             ]
         },
+        {
+            "taskName": "xargo build --example usart_clk",
+            "type": "shell",
+            "command": "xargo build --example usart_clk",
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            },
+            "problemMatcher": [
+                "$rustc"
+            ]
+        },
         {
             "taskName": "xargo build --example itm",
             "type": "shell",
@@ -50,10 +62,6 @@
             "problemMatcher": [
                 "$rustc"
             ],
-            "group": {
-                "kind": "build",
-                "isDefault": true
-            }
         },
         {
             "type": "shell",
diff --git a/examples/usart_clk.rs b/examples/usart_clk.rs
new file mode 100644
index 0000000000000000000000000000000000000000..a0c1efce54e266e282e59e5bd42dd611bb84a8c1
--- /dev/null
+++ b/examples/usart_clk.rs
@@ -0,0 +1,220 @@
+//! Test the USART1 instance
+//!
+//! Connect the TX and RX pins to run this test
+//!
+//! PA2 (TX), PA3(RX) on the MCU is connected to the pin header CN3
+//#![deny(unsafe_code)]
+#![deny(warnings)]
+#![allow(warnings)]
+#![feature(proc_macro)]
+#![no_std]
+
+extern crate cortex_m_rtfm as rtfm;
+extern crate cortex_m_semihosting as semihosting;
+extern crate hal;
+#[macro_use]
+extern crate nb;
+#[macro_use]
+extern crate nucleo_64;
+extern crate stm32f40x;
+use hal::usart::USART;
+
+use nucleo_64::time::Hertz;
+
+use rtfm::app;
+use core::ptr;
+use nucleo_64::apb1;
+
+const BAUD_RATE: Hertz = Hertz(115_200);
+
+app! {
+    device: nucleo_64::stm32f40x,
+}
+
+use stm32f40x::USART2;
+
+fn serial_init(p: &init::Peripherals) {
+    // RM0368 6.3.9
+    // enable clock to GPIOA, USART2
+    p.RCC.ahb1enr.modify(|_, w| w.gpioaen().enable());
+
+    // enable clock to
+    p.RCC.apb1enr.modify(|_, w| w.usart2en().bit(true));
+
+    // PA2 = TX, PA3 = RX
+    // p.AFIO.mapr.modify(|_, w| w.usart2_remap().clear_bit());
+
+
+    // RM0368 8.4.1
+    // set output mode for GPIOA
+    // PA2 = TX (output mode), PA3 = RX (input mode)
+    p.GPIOA.moder.modify(|_, w| {
+        w.moder2()
+            .variant(stm32f40x::gpioa::moder::MODER15W::ALTERNATEMODE)
+            .moder3()
+            .variant(stm32f40x::gpioa::moder::MODER15W::ALTERNATEMODE)
+    });
+
+    // we don't care about the speed register atm
+    // DM00102166
+    // AF7, Table 9
+    // PA2 and PA3 is connected to USART2 TX and RX respectively
+    p.GPIOA.afrl.modify(|_, w| w.afrl2().af7().afrl3().af7());
+
+    // 8N1, stop bit
+    p.USART2.cr2.write(|w| unsafe { w.stop().bits(0b00) });
+
+    // baud rate
+    //    let brr :<U::Ticks>= BAUD_RATE.into();
+    let brr: apb1::Ticks = BAUD_RATE.invert().into();
+    let brr = brr.0;
+    assert!(brr >= 16, "impossible baud rate");
+
+    p.USART2.brr.write(|w| unsafe { w.bits(brr) });
+
+    // disable hardware flow control
+    // enable DMA TX and RX transfers
+    p.USART2.cr3.write(|w| {
+        w.rtse() /* Ready To Send disable */
+            .clear_bit()
+            .ctse() /* Clear To Send disable */
+            .clear_bit()
+            .dmat() /* Enable DMA Transmit */
+            .set_bit()
+            .dmar()  /* Enable DMA Receive */
+            .set_bit()
+    });
+
+    // enable TX, RX; disable parity checking
+    p.USART2.cr1.write(|w| {
+        w.ue() /* Usart Enable */
+            .set_bit()
+            .re() /* Receiver Enable */
+            .set_bit()
+            .te() /* Transmitter Enable */
+            .set_bit()
+            .m() /* Word Length, 8 */
+            .clear_bit()
+            .pce() /* Parity Control Enable */
+            .clear_bit()
+            .rxneie() /* Reception Interrupt Enable */
+            .clear_bit()
+    });
+}
+
+fn clk_init(p: &init::Peripherals) {
+    // setting up the flash memory latency
+    // RM0368 8.4.1 (register), 3.4 Table 6
+    // we assume 3.3 volt operation, thus 2 cycles for 84mHz
+    p.FLASH.acr.modify(|_, w| unsafe { w.latency().bits(2) });
+
+    p.FLASH.acr.modify(|_, w| unsafe { w.latency().bits(2) });
+    println!("Init! {:x}", p.FLASH.acr.read().latency().bits());
+
+
+    p.RCC
+        .cfgr
+        .modify(|_, w| w.sw0().clear_bit().sw1().clear_bit()); //Switch to HSI
+    p.RCC.cfgr.modify(|_, w| unsafe { w.ppre1().bits(4) }); //Configure apb1 prescaler = 2
+    p.RCC.apb1enr.modify(|_, w| w.pwren().set_bit());
+    p.RCC.cr.write(|w| w.pllon().clear_bit());
+
+    //Enable PLL
+    //					   PP	  PLLN	    PLLM
+    // 0b0000 0000 0000 00 01 0 101010000 010000
+    // RM0368 6.3.2
+    p.RCC
+        .pllcfgr
+        .write(|w| unsafe { w.bits(0b00000000000000010101010000010000) }); //Configure PLL
+
+    p.RCC.cr.modify(|_, w| w.pllon().set_bit()); //Enable PLL
+
+    while p.RCC.cr.read().pllrdy().bit_is_clear() {}
+
+    p.RCC.cfgr.modify(|_, w| w.sw0().clear_bit()); //Switch to PLL
+    p.RCC.cfgr.modify(|_, w| w.sw1().set_bit()); //Switch to PLL
+    p.RCC.apb2enr.modify(|_, w| w.syscfgen().set_bit());
+
+    p.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit()); //Enable GPIOA clock
+    p.RCC.ahb1enr.modify(|_, w| w.gpioben().set_bit()); //Enable GPIOB clock
+
+    //USART::send(p.USART2, "\n\n\nUSART initialized\n\r");
+}
+
+#[inline(never)]
+fn init(p: init::Peripherals) {
+    println!("Init!");
+    clk_init(&p);
+    //serial_init(&p);
+    USART::initialize(p.GPIOA, p.RCC, p.USART2);
+
+    USART::send(p.USART2, "\n\n\nUSART \n\r");
+
+    loop {
+        let b = block!(read(p.USART2)).unwrap();
+        write(p.USART2, b).unwrap();
+    }
+}
+
+// Specialized `Result` type
+pub type Result<T> = ::core::result::Result<T, nb::Error<Error>>;
+
+/// An error
+#[derive(Debug)]
+pub enum Error {
+    /// De-synchronization, excessive noise or a break character detected
+    Framing,
+    /// Noise detected in the received frame
+    Noise,
+    /// RX buffer overrun
+    Overrun,
+    #[doc(hidden)] _Extensible,
+}
+
+fn write(usart2: &USART2, byte: u8) -> Result<()> {
+    let sr = usart2.sr.read();
+
+    if sr.ore().bit_is_set() {
+        Err(nb::Error::Other(Error::Overrun))
+    } else if sr.nf().bit_is_set() {
+        Err(nb::Error::Other(Error::Noise))
+    } else if sr.fe().bit_is_set() {
+        Err(nb::Error::Other(Error::Framing))
+    } else if sr.txe().bit_is_set() {
+        // NOTE(write_volatile) see NOTE in the `read` method
+        unsafe { ptr::write_volatile(&usart2.dr as *const _ as *mut u8, byte) }
+        Ok(())
+    } else {
+        Err(nb::Error::WouldBlock)
+    }
+}
+
+fn read(usart2: &USART2) -> Result<u8> {
+    let sr = usart2.sr.read();
+
+    if sr.ore().bit_is_set() {
+        Err(nb::Error::Other(Error::Overrun))
+    } else if sr.nf().bit_is_set() {
+        Err(nb::Error::Other(Error::Noise))
+    } else if sr.fe().bit_is_set() {
+        Err(nb::Error::Other(Error::Framing))
+    } else if sr.rxne().bit_is_set() {
+        // NOTE(read_volatile) the register is 9 bits big but we'll only
+        // work with the first 8 bits
+        Ok(unsafe {
+            ptr::read_volatile(&usart2.dr as *const _ as *const u8)
+        })
+    } else {
+        Err(nb::Error::WouldBlock)
+    }
+}
+
+fn idle() -> ! {
+    // Will never be hit, as
+    rtfm::bkpt();
+
+    // Sleep
+    loop {
+        rtfm::wfi();
+    }
+}