diff --git a/esp8266/Makefile b/esp8266/Makefile
index 156b8304a14856bdd8e920b05ad25d20296237fc..d6ab96974d21ea90d1f295ba0e2b7ffab28d2c75 100644
--- a/esp8266/Makefile
+++ b/esp8266/Makefile
@@ -66,6 +66,7 @@ SRC_C = \
 	modpybpwm.c \
 	modpybrtc.c \
 	modpybadc.c \
+	modpybuart.c \
 	modpybi2c.c \
 	modpybspi.c \
 	modesp.c \
diff --git a/esp8266/esp8266.ld b/esp8266/esp8266.ld
index a74e2d25d86fc093464daa8f9d628a60ef2fcb28..2c38e1c82df11722cf4e1031ef3414df8ea54d97 100644
--- a/esp8266/esp8266.ld
+++ b/esp8266/esp8266.ld
@@ -137,6 +137,7 @@ SECTIONS
         *modpybpwm.o(.literal*, .text*)
         *modpybrtc.o(.literal*, .text*)
         *modpybadc.o(.literal*, .text*)
+        *modpybuart.o(.literal*, .text*)
         *modpybi2c.o(.literal*, .text*)
         *modpybspi.o(.literal*, .text*)
         *modesp.o(.literal* .text*)
diff --git a/esp8266/modmachine.c b/esp8266/modmachine.c
index 0dab5104b0c3946ebb6817aeaba9a9dde9570814..96f9845dc10b19e5a36f3467c617c06bb826a38b 100644
--- a/esp8266/modmachine.c
+++ b/esp8266/modmachine.c
@@ -158,6 +158,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
     { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },
     { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) },
     { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
+    { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
     { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) },
     { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
 };
diff --git a/esp8266/modpyb.h b/esp8266/modpyb.h
index 51f5b0a672a77fd9ce72d5e4bcd2bdbd9f8611a9..3ac9f2f15f8a9dcf4cf922a82ffc08ec8892029e 100644
--- a/esp8266/modpyb.h
+++ b/esp8266/modpyb.h
@@ -2,6 +2,7 @@ extern const mp_obj_type_t pyb_pin_type;
 extern const mp_obj_type_t pyb_pwm_type;
 extern const mp_obj_type_t pyb_adc_type;
 extern const mp_obj_type_t pyb_rtc_type;
+extern const mp_obj_type_t pyb_uart_type;
 extern const mp_obj_type_t pyb_i2c_type;
 extern const mp_obj_type_t pyb_spi_type;
 
diff --git a/esp8266/modpybuart.c b/esp8266/modpybuart.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c06f8090786f6d3df4e573e6fafe9f173d5a37a
--- /dev/null
+++ b/esp8266/modpybuart.c
@@ -0,0 +1,157 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include "ets_sys.h"
+#include "uart.h"
+
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "modpyb.h"
+
+typedef struct _pyb_uart_obj_t {
+    mp_obj_base_t base;
+    uint8_t uart_id;
+} pyb_uart_obj_t;
+
+/******************************************************************************/
+// MicroPython bindings for UART
+
+STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+    pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_printf(print, "UART(%u)", self->uart_id);
+}
+
+STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+    /*
+    enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop };
+    static const mp_arg_t allowed_args[] = {
+        { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
+        { MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
+        { MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+        { MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
+        { MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+        { MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+    };
+    mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+    mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+    */
+    // not implemented
+}
+
+STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+    mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
+
+    // get uart id
+    mp_int_t uart_id = mp_obj_get_int(args[0]);
+    if (uart_id != 0 && uart_id != 1) {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", uart_id));
+    }
+
+    // create instance
+    pyb_uart_obj_t *self = m_new_obj(pyb_uart_obj_t);
+    self->base.type = &pyb_uart_type;
+    self->uart_id = uart_id;
+
+    if (n_args > 1 || n_kw > 0) {
+        // init the peripheral
+        mp_map_t kw_args;
+        mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+        pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
+    }
+
+    return MP_OBJ_FROM_PTR(self);
+}
+
+STATIC mp_obj_t pyb_uart_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+    pyb_uart_init_helper(args[0], n_args - 1, args + 1, kw_args);
+    return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
+
+STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
+    { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
+
+    { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+    { MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) },
+    { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
+    { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+    { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
+
+STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
+    mp_not_implemented("reading from UART");
+}
+
+STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
+    pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
+    const byte *buf = buf_in;
+
+    /* TODO implement non-blocking
+    // wait to be able to write the first character
+    if (!uart_tx_wait(self, timeout)) {
+        *errcode = EAGAIN;
+        return MP_STREAM_ERROR;
+    }
+    */
+
+    // write the data
+    for (size_t i = 0; i < size; ++i) {
+        uart_tx_one_char(self->uart_id, *buf++);
+    }
+
+    // return number of bytes written
+    return size;
+}
+
+STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
+    *errcode = EINVAL;
+    return MP_STREAM_ERROR;
+}
+
+STATIC const mp_stream_p_t uart_stream_p = {
+    .read = pyb_uart_read,
+    .write = pyb_uart_write,
+    .ioctl = pyb_uart_ioctl,
+    .is_text = false,
+};
+
+const mp_obj_type_t pyb_uart_type = {
+    { &mp_type_type },
+    .name = MP_QSTR_UART,
+    .print = pyb_uart_print,
+    .make_new = pyb_uart_make_new,
+    .getiter = mp_identity,
+    .iternext = mp_stream_unbuffered_iter,
+    .stream_p = &uart_stream_p,
+    .locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict,
+};
diff --git a/esp8266/qstrdefsport.h b/esp8266/qstrdefsport.h
index 12f72a3e208f0791180de8049438faa0a40bc66a..df9c2fb4fd515625e3988357f75aaf2f1def130d 100644
--- a/esp8266/qstrdefsport.h
+++ b/esp8266/qstrdefsport.h
@@ -150,6 +150,10 @@ Q(memory)
 Q(ADC)
 Q(read)
 
+// UART
+Q(UART)
+Q(init)
+
 // I2C
 Q(I2C)
 Q(init)