diff --git a/lib/usart.c b/lib/usart.c
new file mode 100644
index 0000000..f1fb42d
--- /dev/null
+++ b/lib/usart.c
@@ -0,0 +1,139 @@
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+/* Copyright (c) 2016 King Kévin */
+/* this library handles the USART
+ * it uses the TX and RX pins (depending on which USART is used)
+ */
+
+/* standard libraries */
+#include // standard integer types
+#include // standard I/O facilities
+#include // general utilities
+
+/* STM32 (including CM3) libraries */
+#include // real-time control clock library
+#include // general purpose input output library
+#include // universal synchronous asynchronous receiver transmitter library
+#include // interrupt handler
+
+#include "usart.h" // USART header and definitions
+
+/* input and output ring buffer, indexes, and available memory */
+uint8_t rx_buffer[USART_BUFFER] = {0};
+volatile uint8_t rx_i = 0;
+volatile uint8_t rx_used = 0;
+uint8_t tx_buffer[USART_BUFFER] = {0};
+volatile uint8_t tx_i = 0;
+volatile uint8_t tx_used = 0;
+/* show the user how much data received over USART is ready */
+volatile uint8_t usart_received = 0; // same as rx_used, but since the user can write this variable we don't rely on it
+
+/* setup USART port */
+void usart_setup(void)
+{
+ rcc_periph_clock_enable(USART_RCC); // enable USART1 clock
+ gpio_set_mode(USART_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USART_PIN_TX); // setup GPIO pin USART transmit
+ gpio_set_mode(USART_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, USART_PIN_RX); // setup GPIO pin USART receive
+
+ /* setup UART parameters */
+ usart_set_baudrate(USART, 115200);
+ usart_set_databits(USART, 8);
+ usart_set_stopbits(USART, USART_STOPBITS_1);
+ usart_set_mode(USART, USART_MODE_TX_RX);
+ usart_set_parity(USART, USART_PARITY_NONE);
+ usart_set_flow_control(USART, USART_FLOWCONTROL_NONE);
+
+ nvic_enable_irq(USART_IRQ); // enable the USART2 interrupt
+ usart_enable(USART); // enable USART
+
+ /* reset buffer states */
+ tx_i = 0;
+ tx_used = 0;
+ rx_i = 0;
+ rx_used = 0;
+ usart_received = 0;
+}
+
+/* put character on USART (blocking) */
+void usart_putchar_blocking(char c)
+{
+ if (c == '\n') { // add carrier return before line feed. this is recommended for most UART terminals
+ usart_putchar_blocking('\r'); // a second carrier return doesn't influence the terminal
+ }
+ usart_flush(); // empty buffer first
+ usart_send_blocking(USART, c); // send character
+}
+
+/* ensure all data has been transmitted (blocking) */
+void usart_flush(void)
+{
+ while (tx_used) { // idle until buffer is empty
+ __asm__("wfi"); // sleep until interrupt
+ }
+ usart_wait_send_ready(USART); // wait until transmit register is empty (transmission might not be complete)
+}
+
+/* get character from USART (blocking) */
+char usart_getchar(void)
+{
+ while (!rx_used) { // idle until data is available
+ __asm__("wfi"); // sleep until interrupt;
+ }
+ char to_return = rx_buffer[rx_i]; // get the next available character
+ rx_i = (rx_i+1)%sizeof(rx_buffer); // update used buffer
+ rx_used--; // update used buffer
+ usart_received = rx_used; // update available data
+ return to_return;
+}
+
+/* put character on USART stream (non-blocking using a buffer) */
+void usart_putchar_nonblocking(char c)
+{
+ while (tx_used>=sizeof(tx_buffer)) { // idle until buffer has some space
+ __asm__("wfi");
+ }
+ tx_buffer[(tx_i+tx_used)%sizeof(tx_buffer)] = c; // put character in buffer
+ tx_used++; // update used buffer
+ usart_enable_tx_interrupt(USART); // enable transmit interrupt
+}
+
+#if (USART==USART1)
+void usart1_isr(void)
+#elif (USART==USART2)
+void usart2_isr(void)
+#elif (USART==USART3)
+void usart3_isr(void)
+#endif
+{ // USART interrupt
+ if (usart_get_interrupt_source(USART, USART_SR_TXE)) { // data has been transmitted
+ if (!tx_used) { // no data in the buffer to transmit
+ usart_disable_tx_interrupt(USART); // disable transmit interrupt
+ } else {
+ usart_send(USART,tx_buffer[tx_i]); // put data in transmit register
+ tx_i = (tx_i+1)%sizeof(rx_buffer); // update location on buffer
+ tx_used--; // update used size
+ }
+ }
+ if (usart_get_interrupt_source(USART, USART_SR_RXNE)) { // data has been received
+ // only save data if there is space in the buffer
+ if (rx_used>=sizeof(rx_buffer)) {
+ usart_recv(USART); // read to clear interrupt
+ } else {
+ rx_buffer[(rx_i+rx_used)%sizeof(rx_buffer)] = usart_recv(USART); // put character in buffer
+ rx_used++; // update used buffer
+ usart_received = rx_used; // update available data
+ }
+ }
+}
diff --git a/lib/usart.h b/lib/usart.h
new file mode 100644
index 0000000..22933a4
--- /dev/null
+++ b/lib/usart.h
@@ -0,0 +1,42 @@
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+/* Copyright (c) 2016 King Kévin */
+/* This library handles the USART */
+
+/* which USART to use */
+#define USART USART1
+#define USART_RCC RCC_USART1
+#define USART_IRQ NVIC_USART1_IRQ
+#define USART_PORT GPIOA
+#define USART_PIN_TX GPIO_USART1_TX
+#define USART_PIN_RX GPIO_USART1_RX
+
+/* serial baudrate, in bits per second (with 8N1 8 bits, no parity bit, 1 stop bit settings) */
+#define BAUD 115200
+/* USART RX and TX buffer sizes */
+#define USART_BUFFER 64
+/* show the user how much received is available */
+extern volatile uint8_t usart_received;
+
+/* setup USART port */
+void usart_setup(void);
+/* put character on USART (blocking) */
+void usart_putchar_blocking(char c);
+/* ensure all data has been transmitted (blocking) */
+void usart_flush(void);
+/* get character from USART (blocking) */
+char usart_getchar(void);
+/* put character on USART (non-blocking until buffer is full) */
+void usart_putchar_nonblocking(char c);
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..45da4fe
--- /dev/null
+++ b/main.c
@@ -0,0 +1,85 @@
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+/* Copyright (c) 2016 King Kévin */
+
+/* standard libraries */
+#include // standard integer types
+#include // standard I/O facilities
+#include // standard utilities
+#include // standard streams
+#include // error number utilities
+
+/* STM32 (including CM3) libraries */
+#include // real-time control clock library
+#include // general purpose input output library
+#include // vector table definition
+
+/* own libraries */
+#include "main.h" // board definitions
+#include "usart.h" // USART utilities
+
+/* default output (i.e. for printf) */
+int _write(int file, char *ptr, int len)
+{
+ int i;
+
+ if (file == STDOUT_FILENO || file == STDERR_FILENO) {
+ for (i = 0; i < len; i++) {
+ if (ptr[i] == '\n') { // add carrier return before line feed. this is recommended for most UART terminals
+ usart_putchar_nonblocking('\r'); // a second line feed doesn't break the display
+ }
+ usart_putchar_nonblocking(ptr[i]); // send byte over USART
+ }
+ return i;
+ }
+ errno = EIO;
+ return -1;
+}
+
+static void clock_setup(void)
+{
+ rcc_clock_setup_in_hse_8mhz_out_72mhz(); // use 8 MHz high speed external clock to generate 72 MHz internal clock
+ rcc_periph_clock_enable(LED_RCC); //enable clock for LED
+}
+
+static void gpio_setup(void)
+{
+ /* set LED pin to 'output push-pull' */
+ gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, LED_PIN);
+}
+
+int main(void)
+{
+ int i, c = 0;
+
+ SCB_VTOR = (uint32_t) 0x08002000; // relocate vector table because of the bootloader
+
+ clock_setup();
+ gpio_setup();
+ usart_setup();
+ setbuf(stdout, NULL); // set standard out buffer to NULL to immediately print
+ setbuf(stderr, NULL); // set standard error buffer to NULL to immediately print
+
+ /* blink the LED with every transmitted character */
+ while (1) {
+ gpio_toggle(LED_PORT, LED_PIN); /* LED on/off */
+ printf("%c",c+'0');
+ c = (c == 9) ? 0 : c + 1; /* increment c */
+ for (i = 0; i < 8000000; i++) /* wait a bit */
+ __asm__("nop");
+ }
+
+ return 0;
+}
diff --git a/main.h b/main.h
new file mode 100644
index 0000000..2c19906
--- /dev/null
+++ b/main.h
@@ -0,0 +1,23 @@
+/* This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+/* Copyright (c) 2016 King Kévin */
+
+/* LED is on pin 11/PA1 */
+#define LED_PORT GPIOA
+#define LED_PIN GPIO1
+#define LED_RCC RCC_GPIOA
+
+/* default output (i.e. for printf) */
+int _write(int file, char *ptr, int len);