Studying MicroPython’s Serial REPL

The beauty of Unix philosophy: piping data from one simple program to another, to do great work 😉

Sniffing the serial port to know better MicroPython Serial REPL (https://docs.micropython.org/en/latest/reference/repl.html) protocol:

echo 123 > test.txt
strace -s9999 -o output.log -eread,write ampy -p /dev/ttyACM put test.txt

Result:
read(9, “123\n”, 4096) = 4
read(9, “”, 4096) = 0
write(3, “\r\3\3”, 3) = 3
write(3, “\r\1”, 2) = 2
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “r”, 1) = 1
read(3, “a”, 1) = 1
read(3, “w”, 1) = 1
read(3, ” “, 1) = 1
read(3, “R”, 1) = 1
read(3, “E”, 1) = 1
read(3, “P”, 1) = 1
read(3, “L”, 1) = 1
read(3, “;”, 1) = 1
read(3, ” “, 1) = 1
read(3, “C”, 1) = 1
read(3, “T”, 1) = 1
read(3, “R”, 1) = 1
read(3, “L”, 1) = 1
read(3, “-“, 1) = 1
read(3, “B”, 1) = 1
read(3, ” “, 1) = 1
read(3, “t”, 1) = 1
read(3, “o”, 1) = 1
read(3, ” “, 1) = 1
read(3, “e”, 1) = 1
read(3, “x”, 1) = 1
read(3, “i”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
write(3, “\4”, 1) = 1
read(3, “O”, 1) = 1
read(3, “K”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “M”, 1) = 1
read(3, “P”, 1) = 1
read(3, “Y”, 1) = 1
read(3, “:”, 1) = 1
read(3, ” “, 1) = 1
read(3, “s”, 1) = 1
read(3, “o”, 1) = 1
read(3, “f”, 1) = 1
read(3, “t”, 1) = 1
read(3, ” “, 1) = 1
read(3, “r”, 1) = 1
read(3, “e”, 1) = 1
read(3, “b”, 1) = 1
read(3, “o”, 1) = 1
read(3, “o”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
write(3, “\3”, 1) = 1
write(3, “\3”, 1) = 1
read(3, “r”, 1) = 1
read(3, “a”, 1) = 1
read(3, “w”, 1) = 1
read(3, ” “, 1) = 1
read(3, “R”, 1) = 1
read(3, “E”, 1) = 1
read(3, “P”, 1) = 1
read(3, “L”, 1) = 1
read(3, “;”, 1) = 1
read(3, ” “, 1) = 1
read(3, “C”, 1) = 1
read(3, “T”, 1) = 1
read(3, “R”, 1) = 1
read(3, “L”, 1) = 1
read(3, “-“, 1) = 1
read(3, “B”, 1) = 1
read(3, ” “, 1) = 1
read(3, “t”, 1) = 1
read(3, “o”, 1) = 1
read(3, ” “, 1) = 1
read(3, “e”, 1) = 1
read(3, “x”, 1) = 1
read(3, “i”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
write(3, “f = open(‘test.txt’, ‘wb’)”, 26) = 26
write(3, “\4”, 1) = 1
read(3, “OK”, 2) = 2
read(3, “\4”, 1) = 1
read(3, “\4”, 1) = 1
read(3, “>”, 1) = 1
write(3, “f.write(b’123\\n’)”, 17) = 17
write(3, “\4”, 1) = 1
read(3, “OK”, 2) = 2
read(3, “\4”, 1) = 1
read(3, “\4”, 1) = 1
read(3, “>”, 1) = 1
write(3, “f.close()”, 9) = 9
write(3, “\4”, 1) = 1
read(3, “OK”, 2) = 2
read(3, “\4”, 1) = 1
read(3, “\4”, 1) = 1
write(3, “\r\2”, 2) = 2
+++ exited with 0 +++

strace -s9999 -o output.log -eread,write ampy -p /dev/ttyACM1 ls

Result:
write(3, “\r\3\3”, 3) = 3
write(3, “\r\1”, 2) = 2
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “r”, 1) = 1
read(3, “a”, 1) = 1
read(3, “w”, 1) = 1
read(3, ” “, 1) = 1
read(3, “R”, 1) = 1
read(3, “E”, 1) = 1
read(3, “P”, 1) = 1
read(3, “L”, 1) = 1
read(3, “;”, 1) = 1
read(3, ” “, 1) = 1
read(3, “C”, 1) = 1
read(3, “T”, 1) = 1
read(3, “R”, 1) = 1
read(3, “L”, 1) = 1
read(3, “-“, 1) = 1
read(3, “B”, 1) = 1
read(3, ” “, 1) = 1
read(3, “t”, 1) = 1
read(3, “o”, 1) = 1
read(3, ” “, 1) = 1
read(3, “e”, 1) = 1
read(3, “x”, 1) = 1
read(3, “i”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
write(3, “\4”, 1) = 1
read(3, “O”, 1) = 1
read(3, “K”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “M”, 1) = 1
read(3, “P”, 1) = 1
read(3, “Y”, 1) = 1
read(3, “:”, 1) = 1
read(3, ” “, 1) = 1
read(3, “s”, 1) = 1
read(3, “o”, 1) = 1
read(3, “f”, 1) = 1
read(3, “t”, 1) = 1
read(3, ” “, 1) = 1
read(3, “r”, 1) = 1
read(3, “e”, 1) = 1
read(3, “b”, 1) = 1
read(3, “o”, 1) = 1
read(3, “o”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
write(3, “\3”, 1) = 1
write(3, “\3”, 1) = 1
read(3, “r”, 1) = 1
read(3, “a”, 1) = 1
read(3, “w”, 1) = 1
read(3, ” “, 1) = 1
read(3, “R”, 1) = 1
read(3, “E”, 1) = 1
read(3, “P”, 1) = 1
read(3, “L”, 1) = 1
read(3, “;”, 1) = 1
read(3, ” “, 1) = 1
read(3, “C”, 1) = 1
read(3, “T”, 1) = 1
read(3, “R”, 1) = 1
read(3, “L”, 1) = 1
read(3, “-“, 1) = 1
read(3, “B”, 1) = 1
read(3, ” “, 1) = 1
read(3, “t”, 1) = 1
read(3, “o”, 1) = 1
read(3, ” “, 1) = 1
read(3, “e”, 1) = 1
read(3, “x”, 1) = 1
read(3, “i”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
write(3, “try: \n import os\nexcept ImportError:\n import uos as os\ndef listdir(directory):\n if directory == ‘/’: \n return sorted([directory + f for f in os.listdir(directory)])\n else:\n return sorted([directory + ‘/’ + f “, 256) = 256
write(3, “for f in os.listdir(directory)])\n\nprint(listdir(‘/’))\n”, 54) = 54
write(3, “\4”, 1) = 1
read(3, “OK”, 2) = 2
read(3, “[“, 1)                         = 1
read(3, “‘”, 1)                         = 1
read(3, “/”, 1)                         = 1
read(3, “f”, 1)                         = 1
read(3, “i”, 1)                         = 1
read(3, “l”, 1)                         = 1
read(3, “e”, 1)                         = 1
read(3, “.”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “x”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “‘”, 1)                         = 1
read(3, “,”, 1)                         = 1
read(3, ” “, 1)                         = 1
read(3, “‘”, 1)                         = 1
read(3, “/”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “e”, 1)                         = 1
read(3, “s”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “.”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “x”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “‘”, 1)                         = 1
read(3, “,”, 1)                         = 1
read(3, ” “, 1)                         = 1
read(3, “‘”, 1)                         = 1
read(3, “/”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “e”, 1)                         = 1
read(3, “s”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “1”, 1)                         = 1
read(3, “.”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “x”, 1)                         = 1
read(3, “t”, 1)                         = 1
read(3, “‘”, 1)                         = 1
read(3, “]”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “\4”, 1) = 1
read(3, “\4”, 1) = 1
write(3, “\r\2”, 2) = 2
write(1, “/file.txt\n”, 10) = 10
write(1, “/test.txt\n”, 10) = 10
write(1, “/test1.txt\n”, 11) = 11
+++ exited with 0 +++

strace -s9999 -o output.log -eread,write ampy -p /dev/ttyACM1 get test.txt

Result:
write(3, “\r\3\3”, 3) = 3
write(3, “\r\1”, 2) = 2
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, “>”, 1) = 1
read(3, ” “, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “r”, 1) = 1
read(3, “a”, 1) = 1
read(3, “w”, 1) = 1
read(3, ” “, 1) = 1
read(3, “R”, 1) = 1
read(3, “E”, 1) = 1
read(3, “P”, 1) = 1
read(3, “L”, 1) = 1
read(3, “;”, 1) = 1
read(3, ” “, 1) = 1
read(3, “C”, 1) = 1
read(3, “T”, 1) = 1
read(3, “R”, 1) = 1
read(3, “L”, 1) = 1
read(3, “-“, 1) = 1
read(3, “B”, 1) = 1
read(3, ” “, 1) = 1
read(3, “t”, 1) = 1
read(3, “o”, 1) = 1
read(3, ” “, 1) = 1
read(3, “e”, 1) = 1
read(3, “x”, 1) = 1
read(3, “i”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
write(3, “\4”, 1) = 1
read(3, “O”, 1) = 1
read(3, “K”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “M”, 1) = 1
read(3, “P”, 1) = 1
read(3, “Y”, 1) = 1
read(3, “:”, 1) = 1
read(3, ” “, 1) = 1
read(3, “s”, 1) = 1
read(3, “o”, 1) = 1
read(3, “f”, 1) = 1
read(3, “t”, 1) = 1
read(3, ” “, 1) = 1
read(3, “r”, 1) = 1
read(3, “e”, 1) = 1
read(3, “b”, 1) = 1
read(3, “o”, 1) = 1
read(3, “o”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
write(3, “\3”, 1) = 1
write(3, “\3”, 1) = 1
read(3, “r”, 1) = 1
read(3, “a”, 1) = 1
read(3, “w”, 1) = 1
read(3, ” “, 1) = 1
read(3, “R”, 1) = 1
read(3, “E”, 1) = 1
read(3, “P”, 1) = 1
read(3, “L”, 1) = 1
read(3, “;”, 1) = 1
read(3, ” “, 1) = 1
read(3, “C”, 1) = 1
read(3, “T”, 1) = 1
read(3, “R”, 1) = 1
read(3, “L”, 1) = 1
read(3, “-“, 1) = 1
read(3, “B”, 1) = 1
read(3, ” “, 1) = 1
read(3, “t”, 1) = 1
read(3, “o”, 1) = 1
read(3, ” “, 1) = 1
read(3, “e”, 1) = 1
read(3, “x”, 1) = 1
read(3, “i”, 1) = 1
read(3, “t”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “>”, 1) = 1
write(3, “\nimport sys\nwith open(‘test.txt’, ‘rb’) as infile:\n while True:\n result = infile.read(32)\n if result == b”:\n break\n len = sys.stdout.write(result)\n”, 183) = 183
write(3, “\4”, 1) = 1
read(3, “OK”, 2) = 2
read(3, “1”, 1) = 1
read(3, “2”, 1) = 1
read(3, “3”, 1) = 1
read(3, “\r”, 1) = 1
read(3, “\n”, 1) = 1
read(3, “\4”, 1) = 1
read(3, “\4”, 1) = 1
write(3, “\r\2”, 2) = 2
write(1, “123\r\n”, 5) = 5
write(1, “\n”, 1) = 1
+++ exited with 0 +++

Optional:
-eread,write,ioctl

First, useful codes:
(http://www.physics.udel.edu/~watson/scen103/ascii.html)
Decimal | Ctrl char
1 | Ctrl+A
2 | Ctrl+B
3 | Ctrl+C
4 | Ctrl+D
5 | Ctrl+E

Some common conclusions (for the 3 tested cases):
1. Send Ctrl+C (3) twice
2. Send Ctrl+A (1) once
3. Wait for the message “raw REPL; CTRL-B to exit”
4. Send Ctrl+D (4)
5. Wait for “MPY: soft reboot”
6. Send Ctrl+C (3) twice again
7. Wait for the message “raw REPL; CTRL-B to exit”

8. Send the command / file, followed by Ctrl+D (4)
9. Repeat 8 as needed
10. To finish, send \r followed by Ctrl+B (2)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s