diff --git a/miosix/CMakeLists.txt b/miosix/CMakeLists.txt
index df1d0d4dce1e5f9b08553efdc17cc4d336f8c976..8c1c3865617f6622785c15e3675ca5c34c3dc458 100644
--- a/miosix/CMakeLists.txt
+++ b/miosix/CMakeLists.txt
@@ -91,6 +91,8 @@ foreach(OPT_BOARD ${BOARDS})
         util/version.cpp
         util/crc16.cpp
         util/lcd44780.cpp
+        util/angel/angel_serial.cpp
+        util/angel/angel.cpp
         ${ARCH_SRC}
     )
     add_library(Miosix::Miosix::${OPT_BOARD} ALIAS ${MIOSIX_LIBRARY})
diff --git a/miosix/util/angel/angel.cpp b/miosix/util/angel/angel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..915f38991fc8c314f9d1db3900a7faa2035b326d
--- /dev/null
+++ b/miosix/util/angel/angel.cpp
@@ -0,0 +1,168 @@
+/* Copyright (c) 2023 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * 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 "angel.h"
+
+#include <cstring>
+
+using namespace miosix::angel;
+
+__attribute__((target("thumb")))
+int miosix::angel::angelswi(int num2, int param2) {
+    register int num asm("r0") = num2;
+    register int param asm("r1") = param2;
+    register int ret asm("r0");
+    
+    asm(
+        "bkpt 0xAB"
+        : "=r" (ret)
+        : "r" (num), "r" (param)
+        : "memory"
+    );
+
+    return ret;
+}
+
+int miosix::angel::sys_clock() {
+    return angelswi(0x10, 0);
+}
+
+int miosix::angel::sys_close(int handle) {
+    struct {
+        int handle;
+    } params;
+
+    params.handle = handle;
+    return angelswi(0x02, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_errno() {
+    return angelswi(0x13, 0);
+}
+
+int miosix::angel::sys_flen(int handle) {
+    struct {
+        int handle;
+    } params;
+
+    params.handle = handle;
+    return angelswi(0x0c, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_istty(int handle) {
+    struct {
+        int handle;
+    } params;
+
+    params.handle = handle;
+    return angelswi(0x09, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_open(const char *filename, Mode mode) {
+    struct {
+        const char *filename;
+        int mode;
+        int filename_len;
+    } params;
+
+    params.filename = filename;
+    params.mode = mode;
+    params.filename_len = strlen(filename);
+
+    return angelswi(0x01, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_read(int handle, void *buf, int len) {
+    struct {
+        int handle;
+        void *buf;
+        int len;
+    } params;
+
+    params.handle = handle;
+    params.buf = buf;
+    params.len = len;
+
+    return angelswi(0x06, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_write(int handle, const void *buf, int len) {
+    struct {
+        int handle;
+        const void *buf;
+        int len;
+    } params;
+
+    params.handle = handle;
+    params.buf = buf;
+    params.len = len;
+
+    return angelswi(0x05, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_seek(int handle, int pos) {
+    struct {
+        int handle;
+        int pos;
+    } params;
+
+    params.handle = handle;
+    params.pos = pos;
+
+    return angelswi(0x0a, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_remove(const char *filename) {
+    struct {
+        const char *filename;
+        int filename_len;
+    } params;
+
+    params.filename = filename;
+    params.filename_len = strlen(filename);
+
+    return angelswi(0x0e, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_rename(const char *old_filename, const char *new_filename) {
+    struct {
+        const char *old_filename;
+        int old_filename_len;
+        const char *new_filename;
+        int new_filename_len;
+    } params;
+
+    params.old_filename = old_filename;
+    params.old_filename_len = strlen(old_filename);
+    params.new_filename = new_filename;
+    params.new_filename_len = strlen(new_filename);
+
+    return angelswi(0x0f, reinterpret_cast<int>(&params));
+}
+
+int miosix::angel::sys_open_stdout() {
+    return sys_open(":tt", MODE_W);
+}
+
+int miosix::angel::sys_open_stderr() {
+    return sys_open(":tt", MODE_A);
+}
\ No newline at end of file
diff --git a/miosix/util/angel/angel.h b/miosix/util/angel/angel.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e0988aae4a9053251985cb9a83ed296d7a18748
--- /dev/null
+++ b/miosix/util/angel/angel.h
@@ -0,0 +1,59 @@
+/* Copyright (c) 2023 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * 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.
+ */
+
+#pragma once
+
+namespace miosix {
+    namespace angel {
+        enum Mode {
+            MODE_R = 0,
+            MODE_RB = 1,
+            MODE_RP = 2,
+            MODE_RPB = 3,
+            MODE_W = 4,
+            MODE_WB = 5,
+            MODE_WP = 6,
+            MODE_WPB = 7,
+            MODE_A = 8,
+            MODE_AB = 9,
+            MODE_AP = 10,
+            MODE_APB = 11
+        };
+
+        int angelswi(int num2, int param2);
+
+        int sys_clock();
+        int sys_close(int handle);
+        int sys_errno();
+        int sys_flen(int handle);
+        int sys_istty(int handle);
+        int sys_open(const char *filename, Mode mode);
+        int sys_read(int handle, void *buf, int len);
+        int sys_write(int handle, const void *buf, int len);
+        int sys_seek(int handle, int pos);
+        int sys_remove(const char *filename);
+        int sys_rename(const char *old_filename, const char *new_filename);
+    
+        int sys_open_stdout();
+        int sys_open_stderr();
+    }
+}
\ No newline at end of file
diff --git a/miosix/util/angel/angel_serial.cpp b/miosix/util/angel/angel_serial.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dcdcce77e90e25c16330aa8b86555a5485a78d10
--- /dev/null
+++ b/miosix/util/angel/angel_serial.cpp
@@ -0,0 +1,67 @@
+/* Copyright (c) 2023 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * 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 "angel_serial.h"
+
+#include <termios.h>
+
+#include "angel.h"
+#include "filesystem/ioctl.h"
+
+using namespace miosix;
+
+miosix::AngelSerial::AngelSerial() : Device(DeviceType::TTY), handle(angel::sys_open_stdout()) {}
+
+ssize_t miosix::AngelSerial::readBlock(void *buffer, size_t size, off_t where) {
+    return size - angel::sys_read(handle, buffer, size);
+}
+
+ssize_t miosix::AngelSerial::writeBlock(const void *buffer, size_t size, off_t where) {
+    return size - angel::sys_write(handle, buffer, size);
+}
+
+int miosix::AngelSerial::ioctl(int cmd, void *arg) {
+    if(reinterpret_cast<unsigned>(arg) & 0b11) 
+        return -EFAULT; // Unaligned
+    
+    termios *t = reinterpret_cast<termios*>(arg);
+
+    switch(cmd)
+    {
+        case IOCTL_SYNC:
+            return 0;
+        case IOCTL_TCGETATTR:
+            t->c_iflag = IGNBRK | IGNPAR;
+            t->c_oflag = 0;
+            t->c_cflag = CS8;
+            t->c_lflag = 0;
+            return 0;
+        case IOCTL_TCSETATTR_NOW:
+        case IOCTL_TCSETATTR_DRAIN:
+        case IOCTL_TCSETATTR_FLUSH:
+            // Changing things at runtime unsupported, so do nothing, but don't
+            // return error as console_device.h implements some attribute changes
+            return 0;
+        default:
+            return -ENOTTY; // Means the operation does not apply to this descriptor
+    }
+}
diff --git a/miosix/util/angel/angel_serial.h b/miosix/util/angel/angel_serial.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f2cfa90a3d272e8a109b6c6d558e35dfeccbfc9
--- /dev/null
+++ b/miosix/util/angel/angel_serial.h
@@ -0,0 +1,39 @@
+/* Copyright (c) 2023 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <filesystem/devfs/devfs.h>
+
+namespace miosix {
+    class AngelSerial : public miosix::Device {
+    public:
+        AngelSerial();
+
+        ssize_t readBlock(void *buffer, size_t size, off_t where) override;
+        ssize_t writeBlock(const void *buffer, size_t size, off_t where) override;
+        int ioctl(int cmd, void *arg) override;
+
+    private:
+        int handle;
+    };
+}
\ No newline at end of file