|
| 1 | +## Running in a QEMU ESP32 emulator on desktop |
| 2 | + |
| 3 | +For development and automated testing, it can be very useful to run MicroPythonOS on an emulated ESP32 device. |
| 4 | + |
| 5 | +Compared to running on desktop, the emulated ESP32 device offers more capabitlities: |
| 6 | + |
| 7 | +- emulated WiFi scanning (finds a hard-coded list of access points) |
| 8 | +- emulated WiFi connection (doesn't support encryption, so leave password blank) |
| 9 | +- emulated WiFi Access Point (AP) mode |
| 10 | +- emulated storage, which enables LittleFS2 filesystem and Over-The-Air update testing |
| 11 | +- emulated Ultra Low Processor and DeepSleep |
| 12 | +- emulated GPIO buttons |
| 13 | +- emulated capacitive touch buttons |
| 14 | +- emulated ST7789V display |
| 15 | + |
| 16 | +In the future, more features might land: |
| 17 | + |
| 18 | +- [emulated Bluetooth](https://github.com/Ebiroll/qemu_esp32) - currently only on ESP32 but maybe [someday on ESP32S3](https://github.com/Ebiroll/calib/issues/1). |
| 19 | + |
| 20 | +To this end, we're using the amazing a159x36 QEMU emulator, which can emulate the LilyGo T-Display (ESP32) and LilyGo T-Display-S3 (ESP32S3), with [a few improvements](https://github.com/a159x36/qemu/pulls?q=is%3Apr) waiting to be merged upstream. |
| 21 | + |
| 22 | +To get it running, follow these steps: |
| 23 | + |
| 24 | +1. Compile QEMU (or get a precompiled build) |
| 25 | +2. Pad a MicroPythonOS release image to 16MB (otherwise QEMU refuses it) |
| 26 | +3. Start QEMU with the padded MicroPython release image |
| 27 | + |
| 28 | +## 1. Compile QEMU |
| 29 | + |
| 30 | +Get the prerequisites: |
| 31 | + |
| 32 | +`sudo apt-get install -y -q --no-install-recommends build-essential libgcrypt-dev libglib2.0-dev libpixman-1-dev libsdl2-dev libslirp-dev ninja-build python3-pip libvte-2.91-dev wget zlib1g-dev` |
| 33 | + |
| 34 | +Clone it: |
| 35 | + |
| 36 | +``` |
| 37 | +git clone https://github.com/MicroPythonOS/qemu/ |
| 38 | +cd qemu |
| 39 | +``` |
| 40 | + |
| 41 | +Configure it: |
| 42 | + |
| 43 | +`./configure --target-list=xtensa-softmmu --enable-gcrypt --enable-slirp --enable-debug --enable-vte --enable-stack-protector` |
| 44 | + |
| 45 | +Compile it: |
| 46 | + |
| 47 | +`make -j4 # 4 is the number of cores` |
| 48 | + |
| 49 | +## 2. Pad a MicroPythonOS build |
| 50 | + |
| 51 | +Download the [latest release](https://github.com/MicroPythonOS/MicroPythonOS/releases) or use one you built yourself. |
| 52 | + |
| 53 | +A simple way to pad a file to 16MB on Linux is: |
| 54 | + |
| 55 | +`dd if=MicroPythonOS_esp32_0.8.0.bin of=MicroPythonOS_esp32_0.8.0.bin.padded bs=1M count=16 oflag=append conv=notrunc` |
| 56 | + |
| 57 | +## 3. Start QEMU |
| 58 | + |
| 59 | +``` |
| 60 | +./build/qemu-system-xtensa -machine esp32s3 -m 8M -drive file=MicroPythonOS_esp32_0.8.0.bin.padded,if=mtd,format=raw -nic user,model=esp32_wifi,hostfwd=tcp:127.0.0.1:10080-192.168.4.15:80,net=192.168.4.0/24,host=192.168.4.2,hostfwd=tcp:127.0.0.1:1081-192.168.4.1:80,hostfwd=tcp:127.0.0.1:7890-192.168.4.15:7890,hostfwd=tcp:127.0.0.1:7891-192.168.4.1:7890 -display default,show-cursor=on -parallel none -monitor none -serial stdio |
| 61 | +``` |
| 62 | + |
| 63 | +The hostfwd lines forward: |
| 64 | + |
| 65 | +- `127.0.0.1:7890 to 192.168.4.15:7890` for webrepl webserver on port 7890 of the device in Station (WiFi client) mode |
| 66 | +- `127.0.0.1:7891 to 192.168.4.1:7890` for webrepl webrepl on port 7890 of the ESP32 in Access Point (Hotspot) mode |
| 67 | + |
| 68 | +Also these are forwarded, although currently unused: |
| 69 | + |
| 70 | +- `127.0.0.1:10080 to 192.168.4.15:80` when the ESP32 is in Station (WiFi client) mode |
| 71 | +- `127.0.0.1:10081 to 192.168.4.1:80` when the ESP32 is in Access Point (Hotspot) mode |
| 72 | + |
| 73 | +**Note**: QEMU will only log to stdout if you start it from a normal shell, with stdin set. If you're starting it from a script or other tool, consider adding "unbuffer" as a prefix to make sure stdin is set, otherwise you won't see much logging. |
| 74 | + |
| 75 | +## Controls |
| 76 | + |
| 77 | +To navigate around in the emulated T-Display S3: |
| 78 | + |
| 79 | +- press "r" for the reset button |
| 80 | +- press "1" for the GPIO0 button - "previous" |
| 81 | +- press "2" for the GPIO14 button - "next" |
| 82 | +- press both for the "enter" action |
| 83 | +- long press "1" for the "back" action |
| 84 | + |
| 85 | +You can also click the buttons on the picture of the board if you like. |
| 86 | + |
| 87 | +Also, currently unused but: |
| 88 | +- 7, 8, 9 and 0 are bound to capacitive touch input pins 0, 1, 11 and 12 which correspond to GPIO01, GPIO02, GPIO12 and GPIO13 |
| 89 | + |
| 90 | +The code for these controls is in QEMU's `hw/xtensa/esp32s3.c` and `hw/display/st7789v.c`. |
| 91 | + |
| 92 | +## Building an image with a filesystem |
| 93 | + |
| 94 | +For quick development, rather than doing a full rebuild, you could also just rebuild the filesystem based on internal_filesystem/ and bundle that filesystem in an image. |
| 95 | + |
| 96 | +Run `scripts/make_image.sh` from the [MicroPythonOS repo](https://github.com/MicroPythonOS/MicroPythonOS) to do so. |
| 97 | + |
| 98 | +It will call `scripts/mklittlefs.sh` to build the filesystem and bundle it with all the other requisites, giving you a bootable image in one second. |
| 99 | + |
0 commit comments