diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index b42b897f5c237d0e63701c1105c63b6cd954be4e..c64ce34f449c07c4ae8344ad2f956b9cff813bb3 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -2,12 +2,12 @@
 	"name": "Machine PM - Embedded Development",
 	"dockerFile": "./Dockerfile",
 	"settings": {
-		"terminal.integrated.shell.linux": "/bin/zsh"
+		"terminal.integrated.defaultProfile.linux": "zsh",
 	},
 	"extensions": [
 		"asabil.meson",
-		"marus25.cortex-debug",
-		"ms-vscode.cpptools",
+		"marus25.cortex-debug@0.4.4",
+		"ms-vscode.cpptools@1.5.1",
 		"xaver.clang-format",
 		"visualstudioexptteam.vscodeintellicode",
 		"mhutchie.git-graph",
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 919f29b474e41f6286a0984b3ac13c0eaba6b8bc..2ae10e03536d6eaf911a7b394345994c360735a1 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -45,6 +45,10 @@
 				{
 					"label": "Extended Interrupt Sample",
 					"value": "extended-interrupt"
+				},
+				{
+					"label": "Dma Uart",
+					"value": "dma-uart"
 				}
 			]
 		}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1a0d5689147877133796158dee48ffce1b24bfc1..6b208bfd8090650e81ab4d8fbb5a513074f6cfa8 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,7 +1,6 @@
 {
 	"editor.formatOnSave": true,
 	"task.problemMatchers.neverPrompt": true,
-	"task.autoDetect": "off",
 	"files.autoSave": "onFocusChange",
 	"mesonbuild.buildFolder": "build",
 	"search.exclude": {
@@ -9,5 +8,5 @@
 	},
 	"[cpp]": {
 		"editor.defaultFormatter": "xaver.clang-format"
-	},
+	}
 }
diff --git a/library/stm32f072xb/dma/abstract-dma/abstract-dma-init.hpp b/library/stm32f072xb/dma/abstract-dma/abstract-dma-init.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..22a65d0a4024a1511eade2b220d170697d515e2e
--- /dev/null
+++ b/library/stm32f072xb/dma/abstract-dma/abstract-dma-init.hpp
@@ -0,0 +1,24 @@
+#ifndef ABSTRACT_DMA_INIT_H
+#define ABSTRACT_DMA_INIT_H
+
+#include <variant>
+
+#include "dma-register.hpp"
+
+namespace stm32f072xb {
+
+struct AbstractDmaInit {
+	const DmaPeripheral peripheral;
+	const DmaDirection direction;
+	const DmaCircularMode circularMode;
+	const DmaMemoryIncrement memoryIncrement;
+	const DmaMemorySize memorySize;
+	const DmaPeripheralIncrement peripheralIncrement;
+	const DmaPeripheralSize peripheralSize;
+	const uint8_t* buffer;
+	const uint16_t bufferSize;
+};
+
+}  // namespace stm32f072xb
+
+#endif
diff --git a/library/stm32f072xb/dma/abstract-dma/abstract-dma.cpp b/library/stm32f072xb/dma/abstract-dma/abstract-dma.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ad0f160f04b1e6723d7d49bcdfb20be785513e01
--- /dev/null
+++ b/library/stm32f072xb/dma/abstract-dma/abstract-dma.cpp
@@ -0,0 +1,131 @@
+#include "abstract-dma.hpp"
+
+using namespace stm32f072xb;
+
+AbstractDma::AbstractDma(DMA_Channel_TypeDef* dmaChannel, AbstractDmaInit& dmaInit)
+    : _dmaChannel(dmaChannel), _dmaInit(dmaInit) {
+	if (!READ_BIT(RCC->AHBENR, RCC_AHBENR_DMAEN)) {
+		SET_BIT(RCC->AHBENR, RCC_AHBENR_DMAEN);
+	}
+	setupRegister();
+}
+
+AbstractDma::~AbstractDma() {
+	stop();
+}
+
+void AbstractDma::start() {
+	if (READ_BIT(_dmaChannel->CCR, DMA_CCR_EN)) {
+		stop();
+		setNumberOfDataTransfer(_dmaInit.bufferSize);
+	}
+	SET_BIT(_dmaChannel->CCR, DMA_CCR_EN);
+}
+
+void AbstractDma::stop() {
+	CLEAR_BIT(_dmaChannel->CCR, DMA_CCR_EN);
+}
+
+void AbstractDma::setupRegister() {
+	WRITE_REG(_dmaChannel->CCR, 0);
+	setPeripheral(_dmaInit.peripheral);
+	setMemory(_dmaInit.buffer);
+	setNumberOfDataTransfer(_dmaInit.bufferSize);
+	setDirection(_dmaInit.direction);
+	setCircularMode(_dmaInit.circularMode);
+	setMemoryIncrement(_dmaInit.memoryIncrement);
+	setMemorySize(_dmaInit.memorySize);
+	setPeripheralIncrement(_dmaInit.peripheralIncrement);
+	setPeripheralSize(_dmaInit.peripheralSize);
+}
+
+void AbstractDma::setPeripheral(DmaPeripheral peripheral) {
+	switch (peripheral) {
+		case DmaPeripheral::USART2_RX:
+			WRITE_REG(_dmaChannel->CPAR, (uint32_t)&USART2->RDR);
+			break;
+		case DmaPeripheral::USART2_TX:
+			WRITE_REG(_dmaChannel->CPAR, (uint32_t)&USART2->TDR);
+			break;
+	}
+}
+
+void AbstractDma::setMemory(const uint8_t* buffer) {
+	WRITE_REG(_dmaChannel->CMAR, (uint32_t)(buffer));
+}
+
+void AbstractDma::setNumberOfDataTransfer(uint16_t numberOfDataTransfer) {
+	WRITE_REG(_dmaChannel->CNDTR, numberOfDataTransfer);
+}
+
+void AbstractDma::setDirection(DmaDirection direction) {
+	switch (direction) {
+		case DmaDirection::MEMORY_TO_PERIPHERAL:
+			SET_BIT(_dmaChannel->CCR, DMA_CCR_DIR);
+			break;
+		case DmaDirection::PERIPHERAL_TO_MEMORY:
+			CLEAR_BIT(_dmaChannel->CCR, DMA_CCR_DIR);
+			break;
+	}
+}
+
+void AbstractDma::setCircularMode(DmaCircularMode circularMode) {
+	switch (circularMode) {
+		case DmaCircularMode::ENABLE:
+			SET_BIT(_dmaChannel->CCR, DMA_CCR_CIRC);
+			break;
+		case DmaCircularMode::DISABLE:
+			CLEAR_BIT(_dmaChannel->CCR, DMA_CCR_CIRC);
+			break;
+	}
+}
+
+void AbstractDma::setMemoryIncrement(DmaMemoryIncrement memoryIncrement) {
+	switch (memoryIncrement) {
+		case DmaMemoryIncrement::ENABLE:
+			SET_BIT(_dmaChannel->CCR, DMA_CCR_MINC);
+			break;
+		case DmaMemoryIncrement::DISABLE:
+			CLEAR_BIT(_dmaChannel->CCR, DMA_CCR_MINC);
+			break;
+	}
+}
+
+void AbstractDma::setMemorySize(DmaMemorySize memorySize) {
+	switch (memorySize) {
+		case DmaMemorySize::BYTE:
+			CLEAR_BIT(_dmaChannel->CCR, DMA_CCR_MSIZE);
+			break;
+		case DmaMemorySize::HALF_WORD:
+			MODIFY_REG(_dmaChannel->CCR, DMA_CCR_PSIZE, DMA_CCR_MSIZE_0);
+			break;
+		case DmaMemorySize::WORD:
+			MODIFY_REG(_dmaChannel->CCR, DMA_CCR_PSIZE, DMA_CCR_MSIZE_1);
+			break;
+	}
+}
+
+void AbstractDma::setPeripheralIncrement(DmaPeripheralIncrement peripheralIncrement) {
+	switch (peripheralIncrement) {
+		case DmaPeripheralIncrement::ENABLE:
+			SET_BIT(_dmaChannel->CCR, DMA_CCR_PINC);
+			break;
+		case DmaPeripheralIncrement::DISABLE:
+			CLEAR_BIT(_dmaChannel->CCR, DMA_CCR_PINC);
+			break;
+	}
+}
+
+void AbstractDma::setPeripheralSize(DmaPeripheralSize peripheralSize) {
+	switch (peripheralSize) {
+		case DmaPeripheralSize::BYTE:
+			CLEAR_BIT(_dmaChannel->CCR, DMA_CCR_PSIZE);
+			break;
+		case DmaPeripheralSize::HALF_WORD:
+			MODIFY_REG(_dmaChannel->CCR, DMA_CCR_PSIZE, DMA_CCR_PSIZE_0);
+			break;
+		case DmaPeripheralSize::WORD:
+			MODIFY_REG(_dmaChannel->CCR, DMA_CCR_PSIZE, DMA_CCR_PSIZE_1);
+			break;
+	}
+}
diff --git a/library/stm32f072xb/dma/abstract-dma/abstract-dma.hpp b/library/stm32f072xb/dma/abstract-dma/abstract-dma.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1a60dd5248f1334280ff991842c4396b515cb501
--- /dev/null
+++ b/library/stm32f072xb/dma/abstract-dma/abstract-dma.hpp
@@ -0,0 +1,36 @@
+#ifndef ABSTRACT_DMA_H
+#define ABSTRACT_DMA_H
+
+#include <stm32f0xx.h>
+#include "abstract-dma-init.hpp"
+
+namespace stm32f072xb {
+
+class AbstractDma {
+   public:
+	AbstractDma(DMA_Channel_TypeDef* dmaChannel, AbstractDmaInit& dmaInit);
+	~AbstractDma();
+	void start();
+	void stop();
+
+   protected:
+	void setupRegister();
+
+   private:
+	void setPeripheral(DmaPeripheral peripheral);
+	void setMemory(const uint8_t* buffer);
+	void setNumberOfDataTransfer(uint16_t numberOfDataTransfer);
+	void setDirection(DmaDirection direction);
+	void setCircularMode(DmaCircularMode circularMode);
+	void setMemoryIncrement(DmaMemoryIncrement memoryIncrement);
+	void setMemorySize(DmaMemorySize memorySize);
+	void setPeripheralIncrement(DmaPeripheralIncrement peripheralIncrement);
+	void setPeripheralSize(DmaPeripheralSize peripheralSize);
+
+	DMA_Channel_TypeDef* _dmaChannel;
+	AbstractDmaInit& _dmaInit;
+};
+
+}  // namespace stm32f072xb
+
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-channel.hpp b/library/stm32f072xb/dma/dma-register/dma-channel.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ff56fae873f866db7f518a040149a6f261bed9b
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-channel.hpp
@@ -0,0 +1,7 @@
+#ifndef DMA_CHANNEL_H
+#define DMA_CHANNEL_H
+
+namespace stm32f072xb {
+enum class DmaChannel { CHANNEL1, CHANNEL2, CHANNEL3, CHANNEL4, CHANNEL5, CHANNEL6, CHANNEL7 };
+}
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-circular-mode.hpp b/library/stm32f072xb/dma/dma-register/dma-circular-mode.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..dcbd3a75fe6f477207d4f4394009ba6bc87a87d7
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-circular-mode.hpp
@@ -0,0 +1,7 @@
+#ifndef DMA_CIRCULAR_MODE_H
+#define DMA_CIRCULAR_MODE_H
+
+namespace stm32f072xb {
+enum class DmaCircularMode { DISABLE, ENABLE };
+}
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-direction.hpp b/library/stm32f072xb/dma/dma-register/dma-direction.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..aa64be887f467907599bfbf0476f0309e7ec2957
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-direction.hpp
@@ -0,0 +1,9 @@
+#ifndef DMA_DIRECTION_H
+#define DMA_DIRECTION_H
+
+namespace stm32f072xb {
+enum class DmaDirection { MEMORY_TO_PERIPHERAL, PERIPHERAL_TO_MEMORY };
+
+}
+
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-memory-increment.hpp b/library/stm32f072xb/dma/dma-register/dma-memory-increment.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fee7f1c715fb42cc8138981f4115db7961418600
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-memory-increment.hpp
@@ -0,0 +1,10 @@
+#ifndef DMA_MEMORY_INCREMENT_H
+#define DMA_MEMORY_INCREMENT_H
+
+namespace stm32f072xb {
+enum class DmaMemoryIncrement {
+	DISABLE,
+	ENABLE,
+};
+}
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-memory-size.hpp b/library/stm32f072xb/dma/dma-register/dma-memory-size.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ed07e28ccaf3ade8c1c662d523f732cd821fa5f
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-memory-size.hpp
@@ -0,0 +1,7 @@
+#ifndef DMA_MEMORY_SIZE_H
+#define DMA_MEMORY_SIZE_H
+
+namespace stm32f072xb {
+enum class DmaMemorySize { BYTE, HALF_WORD, WORD };
+}
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-peripheral-increment.hpp b/library/stm32f072xb/dma/dma-register/dma-peripheral-increment.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..66c04013152982b30b6680cb64774d3d14370bd9
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-peripheral-increment.hpp
@@ -0,0 +1,9 @@
+#ifndef DMA_PERIPHERAL_INCREMENT_H
+#define DMA_PERIPHERAL_INCREMENT_H
+namespace stm32f072xb {
+enum class DmaPeripheralIncrement {
+	DISABLE,
+	ENABLE,
+};
+}
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-peripheral-size.hpp b/library/stm32f072xb/dma/dma-register/dma-peripheral-size.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..00539a577faa58443c9495ecb7019076e870c812
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-peripheral-size.hpp
@@ -0,0 +1,11 @@
+#ifndef DMA_PERIPHERAL_SIZE_H
+#define DMA_PERIPHERAL_SIZE_H
+
+namespace stm32f072xb {
+enum class DmaPeripheralSize {
+	BYTE,
+	HALF_WORD,
+	WORD,
+};
+}
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-peripheral.hpp b/library/stm32f072xb/dma/dma-register/dma-peripheral.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..059067de285866b79d4cdf7055fddb6773b4bb60
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-peripheral.hpp
@@ -0,0 +1,7 @@
+#ifndef DMA_PERIPHERAL_H
+#define DMA_PERIPHERAL_H
+
+namespace stm32f072xb {
+enum class DmaPeripheral { USART2_RX, USART2_TX };
+}
+#endif
diff --git a/library/stm32f072xb/dma/dma-register/dma-register.hpp b/library/stm32f072xb/dma/dma-register/dma-register.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..c33279484aebc2af6bdf0790393afc1ef463c7aa
--- /dev/null
+++ b/library/stm32f072xb/dma/dma-register/dma-register.hpp
@@ -0,0 +1,8 @@
+#include "dma-channel.hpp"
+#include "dma-circular-mode.hpp"
+#include "dma-direction.hpp"
+#include "dma-memory-increment.hpp"
+#include "dma-memory-size.hpp"
+#include "dma-peripheral-increment.hpp"
+#include "dma-peripheral-size.hpp"
+#include "dma-peripheral.hpp"
diff --git a/library/stm32f072xb/dma/dma.cpp b/library/stm32f072xb/dma/dma.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8c8b5ede33d4725f6ea6dfb6a664f4ebda99a1b5
--- /dev/null
+++ b/library/stm32f072xb/dma/dma.cpp
@@ -0,0 +1,15 @@
+#include "dma.hpp"
+
+using namespace stm32f072xb;
+
+Dma<DmaChannel::CHANNEL4, DmaPeripheral::USART2_TX>::Dma(AbstractDmaInit& dmaInit,
+                                                         Uart<UartRegister::UART2, Port::A>& uart)
+    : AbstractDma(DMA1_Channel4, dmaInit) {
+	uart.enableDmaTransmission();
+}
+
+Dma<DmaChannel::CHANNEL5, DmaPeripheral::USART2_RX>::Dma(AbstractDmaInit& dmaInit,
+                                                         Uart<UartRegister::UART2, Port::A>& uart)
+    : AbstractDma(DMA1_Channel5, dmaInit) {
+	uart.enableDmaReception();
+}
diff --git a/library/stm32f072xb/dma/dma.hpp b/library/stm32f072xb/dma/dma.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..42ab955155c16dd4b0668d0ba1bcb4bc2b2b2792
--- /dev/null
+++ b/library/stm32f072xb/dma/dma.hpp
@@ -0,0 +1,28 @@
+
+#ifndef DMA_H
+#define DMA_H
+
+#include "abstract-dma.hpp"
+#include "dma-register.hpp"
+#include "stm32f072xb.h"
+#include "uart.hpp"
+
+namespace stm32f072xb {
+
+template <DmaChannel T, DmaPeripheral P>
+class Dma {};
+
+template <>
+class Dma<DmaChannel::CHANNEL4, DmaPeripheral::USART2_TX> : public AbstractDma {
+   public:
+	Dma(AbstractDmaInit& dmaInit, Uart<UartRegister::UART2, Port::A>& uart);
+};
+
+template <>
+class Dma<DmaChannel::CHANNEL5, DmaPeripheral::USART2_RX> : public AbstractDma {
+   public:
+	Dma(AbstractDmaInit& dmaInit, Uart<UartRegister::UART2, Port::A>& uart);
+};
+
+}  // namespace stm32f072xb
+#endif
diff --git a/library/stm32f072xb/gpio/abstract-gpio/abstract-gpio-init.hpp b/library/stm32f072xb/gpio/abstract-gpio/abstract-gpio-init.hpp
index 01e45c2e04cb29ec4afdc8539545798e1b7556f6..9df7217bdd4a521b55ff667c4854923a5ddf3e89 100644
--- a/library/stm32f072xb/gpio/abstract-gpio/abstract-gpio-init.hpp
+++ b/library/stm32f072xb/gpio/abstract-gpio/abstract-gpio-init.hpp
@@ -1,8 +1,8 @@
-#include "gpio-register.hpp"
-
 #ifndef ABSTRACT_GPIO_INIT_H
 #define ABSTRACT_GPIO_INIT_H
 
+#include "gpio-register.hpp"
+
 namespace stm32f072xb {
 
 struct AbstractGpioInit {
diff --git a/library/stm32f072xb/meson.build b/library/stm32f072xb/meson.build
index 783422d90e28d66864688e7e25f17c9e0ba4eb31..860bfb02485ec79dac1763ffe1ba662391c9995f 100644
--- a/library/stm32f072xb/meson.build
+++ b/library/stm32f072xb/meson.build
@@ -4,18 +4,22 @@ stm32f072xb_modules		= []
 stm32f072xb_includes	= []
 stm32f072xb_sources 	= []
 
-stm32f072xb_modules += ['gpio/abstract-gpio']
 stm32f072xb_modules += ['gpio']
+stm32f072xb_modules += ['gpio/abstract-gpio']
 stm32f072xb_modules += ['gpio/gpio-register']
 stm32f072xb_modules += ['gpio/output-gpio']
 stm32f072xb_modules += ['gpio/input-gpio']
 stm32f072xb_modules += ['gpio/alternate-gpio']
 stm32f072xb_modules += ['gpio/uart-gpio']
 
-stm32f072xb_modules += ['uart/abstract-uart']
 stm32f072xb_modules += ['uart']
+stm32f072xb_modules += ['uart/abstract-uart']
 stm32f072xb_modules += ['uart/uart-register']
 
+stm32f072xb_modules += ['dma']
+stm32f072xb_modules += ['dma/abstract-dma']
+stm32f072xb_modules += ['dma/dma-register']
+
 stm32f072xb_modules += ['basic-timer']
 
 fs = import('fs')
diff --git a/library/stm32f072xb/uart/abstract-uart/abstract-uart.cpp b/library/stm32f072xb/uart/abstract-uart/abstract-uart.cpp
index bfa38aa3011de404e76b3f8305ebe92dc98e3780..5c65adb9715d0e679779355a6d72d9175a62f1c0 100644
--- a/library/stm32f072xb/uart/abstract-uart/abstract-uart.cpp
+++ b/library/stm32f072xb/uart/abstract-uart/abstract-uart.cpp
@@ -89,3 +89,11 @@ void AbstractUart::enableTransmitter() {
 void AbstractUart::enableReception() {
 	SET_BIT(_uart->CR1, USART_CR1_RE);  // enable Reception (p.734)
 }
+
+void AbstractUart::enableDmaReception() {
+	SET_BIT(USART2->CR3, USART_CR3_DMAR);
+}
+
+void AbstractUart::enableDmaTransmission() {
+	SET_BIT(USART2->CR3, USART_CR3_DMAT);
+}
diff --git a/library/stm32f072xb/uart/abstract-uart/abstract-uart.hpp b/library/stm32f072xb/uart/abstract-uart/abstract-uart.hpp
index bc50990ecb16cad36cf4d579495328161c80d0ba..4ea79ca63a2fdcf4ae2050e1b638259071196c92 100644
--- a/library/stm32f072xb/uart/abstract-uart/abstract-uart.hpp
+++ b/library/stm32f072xb/uart/abstract-uart/abstract-uart.hpp
@@ -8,12 +8,14 @@ namespace stm32f072xb {
 class AbstractUart {
    public:
 	AbstractUart(USART_TypeDef* uart, AbstractUartInit uartInit);
+	~AbstractUart();
 	USART_TypeDef* getUart() { return _uart; };
 
 	char readWord();
 	void writeWord(uint16_t word);
 
-	~AbstractUart();
+	void enableDmaReception();
+	void enableDmaTransmission();
 
    protected:
 	void setupRegister();
diff --git a/samples/meson.build b/samples/meson.build
index 1ef686b5e36c27cc42e02544f78aca23b5c765bf..dc471f667b763acc70d6c6427c561b0a19989022 100644
--- a/samples/meson.build
+++ b/samples/meson.build
@@ -7,6 +7,7 @@ samples += ['gpio']
 samples += ['interruption']
 samples += ['pwm']
 samples += ['extended-interrupt']
+samples += ['dma-uart']
 # samples += ['timeout']
 samples += ['uart']
 
diff --git a/samples/stm32f072xb/dma-uart/main.cpp b/samples/stm32f072xb/dma-uart/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..88978e119c8689867105ee0956abe711a13323a8
--- /dev/null
+++ b/samples/stm32f072xb/dma-uart/main.cpp
@@ -0,0 +1,65 @@
+#include <stm32f072xb.h>
+#include <dma.hpp>
+#include <gpio.hpp>
+#include <uart-gpio.hpp>
+#include <uart.hpp>
+
+using namespace stm32f072xb;
+
+AbstractUartInit uartInit = {WordLength::HEIGHT_BITS, StopBits::ONE_BIT, 115200};
+UartGpio<UartRegister::UART2, UartGpioType::RX, Port::A> rxGpio;
+UartGpio<UartRegister::UART2, UartGpioType::TX, Port::A> txGpio;
+
+Uart<UartRegister::UART2, Port::A> uartTxRx(uartInit, txGpio, rxGpio);
+
+constexpr uint8_t bufferSize = 5;
+uint8_t buffer[bufferSize] = {0};
+
+AbstractDmaInit dmaUartRxInit = {DmaPeripheral::USART2_RX,
+                                 DmaDirection::PERIPHERAL_TO_MEMORY,
+                                 DmaCircularMode::ENABLE,
+                                 DmaMemoryIncrement::ENABLE,
+                                 DmaMemorySize::BYTE,
+                                 DmaPeripheralIncrement::DISABLE,
+                                 DmaPeripheralSize::BYTE,
+                                 buffer,
+                                 bufferSize};
+Dma<DmaChannel::CHANNEL5, DmaPeripheral::USART2_RX> dmaUartRx(dmaUartRxInit, uartTxRx);
+AbstractDmaInit dmaUartTxInit = {DmaPeripheral::USART2_TX,
+                                 DmaDirection::MEMORY_TO_PERIPHERAL,
+                                 DmaCircularMode::DISABLE,
+                                 DmaMemoryIncrement::ENABLE,
+                                 DmaMemorySize::BYTE,
+                                 DmaPeripheralIncrement::DISABLE,
+                                 DmaPeripheralSize::BYTE,
+                                 buffer,
+                                 bufferSize};
+
+Dma<DmaChannel::CHANNEL4, DmaPeripheral::USART2_TX> dmaUartTx(dmaUartTxInit, uartTxRx);
+
+extern "C" void DMA1_Channel4_5_6_7_IRQHandler() {
+	if (READ_BIT(DMA1->ISR, DMA_ISR_TEIF6)) {  // DMA Error occured
+		SET_BIT(DMA1->IFCR, DMA_IFCR_CTEIF6);  // Clear interrupt register
+	}
+
+	if (READ_BIT(DMA1->ISR, DMA_ISR_TCIF5)) {
+		SET_BIT(DMA1->IFCR, DMA_IFCR_CTCIF5);
+		dmaUartTx.start();
+	}
+}
+
+void enableDmaChannel4_5_6_7Irq();
+
+int main() {
+	SET_BIT(DMA1_Channel5->CCR, DMA_CCR_TCIE);
+	enableDmaChannel4_5_6_7Irq();
+	dmaUartRx.start();
+
+	while (true) {
+	}
+}
+
+void enableDmaChannel4_5_6_7Irq() {
+	NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);
+	NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 0);
+}