diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9d29e4797eae871d413c35b088b1a40c0a142219..6bd3c7c628a2d668952a4ceb29f115871f8dd191 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -86,25 +86,37 @@
             "type": "cortex-debug",
             "request": "launch",
             "servertype": "openocd",
-            "name": "Debug Microcontroller",
+            "name": "c serial-dma-tx",
             "executable": "./target/thumbv7em-none-eabihf/debug/examples/serial-dma-tx",
             "configFiles": [
                 "interface/stlink.cfg",
                 "target/stm32f4x.cfg"
             ],
-            "swoConfig": [
-                "enabled": "true",
-                "swoFrequency": "0",
-                "cpuFrequency": "0",
-                "ports": [
-                    [
-                        "number": "0",
-                        "label": "0",
-                        "format": "console",
-                    ]
-                ]
-            ],
-            "cwd": "${workspaceRoot}"
-        }
-    ]
+            // "swoConfig": [
+            // "enabled": "true",
+            // "swoFrequency": "0",
+            // "cpuFrequency": "0",
+            // "ports": [
+            //     [
+            //         "number": "0",
+            //         "label": "0",
+            //         "format": "console",
+            //     ]
+            // ]
+        ],
+        "cwd": "${workspaceRoot}"
+    },
+    {
+        "type": "cortex-debug",
+        "request": "launch",
+        "servertype": "openocd",
+        "name": "c rtfm-serial-dma-tx",
+        "executable": "./target/thumbv7em-none-eabihf/debug/examples/rtfm-serial-dma-tx",
+        "configFiles": [
+            "interface/stlink.cfg",
+            "target/stm32f4x.cfg"
+        ],
+        "cwd": "${workspaceRoot}"
+    }
+]
 }
\ No newline at end of file
diff --git a/examples/rtfm-serial-dma-tx.rs b/examples/rtfm-serial-dma-tx.rs
new file mode 100644
index 0000000000000000000000000000000000000000..be8f03b06b35e6995a8d2d7d7c48c98318f8b2cd
--- /dev/null
+++ b/examples/rtfm-serial-dma-tx.rs
@@ -0,0 +1,120 @@
+//! Serial interface echo server (reactive version)
+//!
+//! This is a reactive version of the `serial-echo` example. Here the processor sleeps most of the
+//! time and only wakes up to sent back received bytes.
+//!
+//! This example uses the [Real Time For the Masses framework](https://docs.rs/cortex-m-rtfm/~0.3)
+#![deny(unsafe_code)]
+//#![deny(warnings)]
+#![feature(proc_macro)]
+#![no_std]
+
+extern crate cortex_m;
+extern crate cortex_m_rtfm as rtfm;
+extern crate stm32f4x_hal as hal;
+
+use hal::prelude::*;
+use hal::serial::{Rx, Serial, Tx};
+use hal::dma::Event;
+use hal::stm32f4x;
+use rtfm::{app, Threshold};
+use cortex_m::asm;
+
+app! {
+    device: stm32f4x,
+
+    resources: {
+        //static TX: Tx<stm32f4x::USART2>;
+        static RX: Rx<stm32f4x::USART2>;
+    },
+
+    tasks: {
+        DMA1_STREAM6: {
+            path: tx,
+            resources: [RX],
+        }
+    },
+}
+
+fn init(p: init::Peripherals) -> init::LateResources {
+    let mut flash = p.device.FLASH.constrain();
+    let mut rcc = p.device.RCC.constrain();
+    let mut gpioa = p.device.GPIOA.split(&mut rcc.ahb1);
+    let streams = p.device.DMA1.split(&mut rcc.ahb1);
+    let mut tx_stream = streams.1.into_channel4(); // S6<C4>
+
+    let clocks = rcc.cfgr.freeze(&mut flash.acr);
+
+    let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
+    let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
+
+    let mut serial = Serial::usart2(
+        p.device.USART2,
+        (tx, rx),
+        115_200.bps(),
+        clocks,
+        &mut rcc.apb1,
+    );
+
+    let (tx, rx) = serial.split();
+    tx_stream.listen(Event::TransferComplete);
+
+    let _ = tx.write_all(tx_stream, b"The quick brown fox");
+
+    init::LateResources { RX: rx }
+}
+
+fn idle() -> ! {
+    // sleep
+    loop {
+        // rtfm::wfi();
+    }
+}
+
+fn tx(_: &mut Threshold, mut r: DMA1_STREAM6::Resources) {
+    asm::bkpt();
+}
+
+// //! Serial interface echo server
+// //!
+// //! In this example every received byte will be sent back to the sender. You can test this example
+// //! with serial terminal emulator like `minicom`.
+// #![deny(unsafe_code)]
+// //#![deny(warnings)]
+// #![no_std]
+
+// extern crate stm32f4x_hal as f4;
+
+// use f4::prelude::*;
+// use f4::serial::Serial;
+// use f4::stm32f4x;
+
+// fn main() {
+//     let p = stm32f4x::Peripherals::take().unwrap();
+
+//     let mut flash = p.FLASH.constrain();
+//     let mut rcc = p.RCC.constrain();
+//     let mut gpioa = p.GPIOA.split(&mut rcc.ahb1);
+//     let streams = p.DMA1.split(&mut rcc.ahb1);
+//     let tx_stream = streams.1.into_channel4(); // S6<C4>
+
+//     let clocks = rcc.cfgr.freeze(&mut flash.acr);
+
+//     let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
+//     let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
+
+//     let serial = Serial::usart2(p.USART2, (tx, rx), 115_200.bps(), clocks, &mut rcc.apb1);
+//     let (mut tx, mut rx) = serial.split();
+
+//     let (_, c, tx) = tx.write_all(tx_stream, b"The quick brown fox").wait();
+
+//     // asm::bkpt();
+
+//     let (_, c, tx) = tx.write_all(c, b" jumps").wait();
+
+//     // asm::bkpt();
+
+//     tx.write_all(c, b" over the lazy dog.").wait();
+
+//     // asm::bkpt();
+// }
diff --git a/src/dma.rs b/src/dma.rs
index 62d67d77fa0d059ed362e4322fdebb0c09ab2ef7..f176508fefcf06a42c0b55e284d39f6a96a66dba 100644
--- a/src/dma.rs
+++ b/src/dma.rs
@@ -206,11 +206,20 @@ pub mod dma1 {
 
     impl<CHANNEL> S5<CHANNEL> {
         pub fn listen(&mut self, event: Event) {
+            let dma = unsafe { &*DMA1::ptr() };
+            match event {
+                Event::HalfTransfer => dma.s5cr.modify(|_, w| w.htie().set_bit()),
+                Event::TransferComplete => dma.s5cr.modify(|_, w| w.tcie().set_bit()),
+            }
+        }
+    }
+
+    impl<CHANNEL> S6<CHANNEL> {
+        pub fn listen(&mut self, event: Event) {
+            let dma = unsafe { &*DMA1::ptr() };
             match event {
-                Event::HalfTransfer => (), // self.ccr().modify(|_, w| w.htie().set_bit()),
-                Event::TransferComplete => {
-                    //           self.ccr().modify(|_, w| w.tcie().set_bit())
-                }
+                Event::HalfTransfer => dma.s6cr.modify(|_, w| w.htie().set_bit()),
+                Event::TransferComplete => dma.s6cr.modify(|_, w| w.tcie().set_bit()),
             }
         }
     }
@@ -235,9 +244,9 @@ pub mod dma1 {
         // pinc: Peripheral increment mode disabled
         // circ: Circular mode disabled
         // dir: Transfer from memory to peripheral
-        // tcie: Transfer complete interrupt enabled
+
         // en: Disabled
-        dma.s6cr.write(|w| unsafe {
+        dma.s6cr.modify(|_, w| unsafe {
             w.chsel()
                 .bits(4) // channel 4
                 .pl()
@@ -254,12 +263,10 @@ pub mod dma1 {
                 .clear_bit() // no peripheral increment
                 .dir()
                 .bits(1) // memory -> peripheral
-                .tcie()
-                .clear_bit() // no interrupt
                 .en()
-                .clear_bit() // setup
+                .set_bit() // setup
         });
-        dma.s6cr.modify(|_, w| w.en().set_bit());
+        //        dma.s6cr.modify(|_, w| w.en().set_bit());
     }
 
     impl DmaExt for DMA1 {
diff --git a/src/serial.rs b/src/serial.rs
index c37a132d8d43088fd6ac06c531bbd76557a117f1..5a16c3d69cd1f09b8860706e9d0af2bbcc19e293 100644
--- a/src/serial.rs
+++ b/src/serial.rs
@@ -276,45 +276,11 @@ macro_rules! hal {
                             buf.as_ptr() as u32
                         );
 
-
-                    //let buffer: &[u8] = buffer.borrow();
-                    // chan.cmar().write(|w| unsafe {
-                    //     w.ma().bits(buffer.as_ptr() as usize as u32)
-                    // });
-                    // chan.cndtr().write(|w| unsafe{
-                    //     w.ndt().bits(u16(buffer.len()).unwrap())
-                    // });
-                    // chan.cpar().write(|w| unsafe {
-                    //     w.pa().bits(&(*$USARTX::ptr()).dr as *const _ as usize as u32)
-                    // });
-
-                    // TODO can we weaken this compiler barrier?
-                    // NOTE(compiler_fence) operations on `buffer` should not be reordered after
-                    // the next statement, which starts the DMA transfer
-                    // atomic::compiler_fence(Ordering::SeqCst);
-
-                    //     chan.ccr().modify(|_, w| {
-                    //         w.mem2mem()
-                    //             .clear_bit()
-                    //             .pl()
-                    //             .medium()
-                    //             .msize()
-                    //             .bit8()
-                    //             .psize()
-                    //             .bit8()
-                    //             .minc()
-                    //             .set_bit()
-                    //             .pinc()chan
-                    //             .clear_bit()
-                    //             .circ()
-                    //             .clear_bit()
-                    //             .dir()
-                    //             .set_bit()
-                    //             .en()
-                    //             .set_bit()
-                    //     });
+                        // TODO can we weaken this compiler barrier?
+                        // NOTE(compiler_fence) operations on `buffer` should not be reordered after
+                        // the next statement, which starts the DMA transfer
+                         atomic::compiler_fence(Ordering::SeqCst);
                     }
-
                     Transfer::r(buffer, tx_stream, self)
                 }
             }