diff --git a/py/objarray.c b/py/objarray.c
index f96d6f4237dfa525a597ccece645bb8f6b885b8d..cb8e03e451d69eff6e5498871ba8155d41258f5c 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -126,7 +126,25 @@ STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
 
 #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
 STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
-    uint len;
+    // bytearrays can be raw-initialised from anything with the buffer protocol
+    // other arrays can only be raw-initialised from bytes and bytearray objects
+    mp_buffer_info_t bufinfo;
+    if (((MICROPY_PY_BUILTINS_BYTEARRAY
+            && typecode == BYTEARRAY_TYPECODE)
+        || (MICROPY_PY_ARRAY
+            && (MP_OBJ_IS_TYPE(initializer, &mp_type_bytes)
+                || MP_OBJ_IS_TYPE(initializer, &mp_type_bytearray))))
+        && mp_get_buffer(initializer, &bufinfo, MP_BUFFER_READ)) {
+        // construct array from raw bytes
+        // we round-down the len to make it a multiple of sz (CPython raises error)
+        int sz = mp_binary_get_size('@', typecode, NULL);
+        mp_uint_t len = bufinfo.len / sz;
+        mp_obj_array_t *o = array_new(typecode, len);
+        memcpy(o->items, bufinfo.buf, len * sz);
+        return o;
+    }
+
+    mp_uint_t len;
     // Try to create array of exact len if initializer len is known
     mp_obj_t len_in = mp_obj_len_maybe(initializer);
     if (len_in == MP_OBJ_NULL) {
@@ -164,7 +182,7 @@ STATIC mp_obj_t array_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
         // 1 arg: make an empty array
         return array_new(*typecode, 0);
     } else {
-        // 2 args: construct the array from the given iterator
+        // 2 args: construct the array from the given object
         return array_construct(*typecode, args[1]);
     }
 }
@@ -179,12 +197,12 @@ STATIC mp_obj_t bytearray_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
         return array_new(BYTEARRAY_TYPECODE, 0);
     } else if (MP_OBJ_IS_SMALL_INT(args[0])) {
         // 1 arg, an integer: construct a blank bytearray of that length
-        uint len = MP_OBJ_SMALL_INT_VALUE(args[0]);
+        mp_uint_t len = MP_OBJ_SMALL_INT_VALUE(args[0]);
         mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len);
         memset(o->items, 0, len);
         return o;
     } else {
-        // 1 arg, an iterator: construct the bytearray from that
+        // 1 arg: construct the bytearray from that
         return array_construct(BYTEARRAY_TYPECODE, args[0]);
     }
 }
diff --git a/py/objstr.c b/py/objstr.c
index a8e27602535dd7c25668017ab1dabb5d80254edd..cfe0ef115ccd48d80a1668a1cd40daaaaf884ab4 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -212,6 +212,12 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
         return mp_obj_str_builder_end(o);
     }
 
+    // check if argument has the buffer protocol
+    mp_buffer_info_t bufinfo;
+    if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_READ)) {
+        return mp_obj_new_str_of_type(&mp_type_bytes, bufinfo.buf, bufinfo.len);
+    }
+
     mp_int_t len;
     byte *data;
     vstr_t *vstr = NULL;
diff --git a/tests/basics/array_construct.py b/tests/basics/array_construct.py
new file mode 100644
index 0000000000000000000000000000000000000000..e050f3003b34180bb5e17d58040fe158f5b52211
--- /dev/null
+++ b/tests/basics/array_construct.py
@@ -0,0 +1,18 @@
+# test construction of array.array from different objects
+
+from array import array
+
+# tuple, list
+print(array('b', (1, 2)))
+print(array('h', [1, 2]))
+
+# raw copy from bytes, bytearray
+print(array('h', b'12'))
+print(array('h', bytearray(2)))
+print(array('i', bytearray(4)))
+
+# convert from other arrays
+print(array('H', array('b', [1, 2])))
+print(array('f', array('h', [1, 2])))
+print(array('b', array('I', [1, 2])))
+print(array('d', array('f', [1, 2])))
diff --git a/tests/basics/bytearray_construct.py b/tests/basics/bytearray_construct.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a7097d55aefdeef50e4e2d5a01fe127def4f6c9
--- /dev/null
+++ b/tests/basics/bytearray_construct.py
@@ -0,0 +1,14 @@
+# test construction of bytearray from different objects
+
+from array import array
+
+# bytes, tuple, list
+print(bytearray(b'123'))
+print(bytearray((1, 2)))
+print(bytearray([1, 2]))
+
+# arrays
+print(bytearray(array('b', [1, 2])))
+print(bytearray(array('h', [1, 2])))
+print(bytearray(array('I', [1, 2])))
+print(bytearray(array('f', [1, 2.3])))
diff --git a/tests/basics/bytes_construct.py b/tests/basics/bytes_construct.py
new file mode 100644
index 0000000000000000000000000000000000000000..1eb6d3e485c43f685163d0e1ee092433071464e6
--- /dev/null
+++ b/tests/basics/bytes_construct.py
@@ -0,0 +1,14 @@
+# test construction of bytes from different objects
+
+from array import array
+
+# tuple, list, bytearray
+print(bytes((1, 2)))
+print(bytes([1, 2]))
+print(bytes(bytearray(4)))
+
+# arrays
+print(bytes(array('b', [1, 2])))
+print(bytes(array('h', [1, 2])))
+print(bytes(array('I', [1, 2])))
+print(bytes(array('f', [1, 2.3])))