micro:bit emulation support is available from QEMU 4.0 onwards and can be used for low-level software testing and development. Unlike existing micro:bit simulators, QEMU performs full-system emulation and actually runs the same ARM code as the real hardware. This blog post explains what full-system emulation means and why QEMU is now a useful tool for developing micro:bit software.
The micro:bit is a tiny ARM board designed for teaching. It is increasingly being used around the world to expose children to computers, programming, and electronics in a low-cost way with an active online community that shares project ideas, lesson plans, and programming tips.
Simulators and emulators
Simulators are used for many tasks from mobile app development to performance analysis of computer hardware. It is possible to develop code using a simulator without having access to real hardware. Oftentimes using a simulator is more convenient than flashing and debugging programs on real hardware.
Emulators allow programs written for one computer system to run on a different computer system. They use techniques like machine code interpreters and just-in-time compilers to execute guest programs that do not run natively on the host computer. Each CPU instruction must be correctly implemented by the emulator so it can run guest software.
How existing micro:bit simulators work
In the screenshot above the micro:bit program calls
world!") and this becomes a call into the MakeCode simulator code to
render images of LEDs in the web browser. On real hardware the code path is
different and eventually leads to an LED matrix driver that lights
up the LEDs by driving output pins on the micro:bit board.
What are the advantages of full-system emulation?
- Programs written in any language can run (MicroPython, mbed C/C++, etc)
- Boot, device driver, and language run-time code can be tested
- Bugs in lower layers of the software stack can be reproduced
- CPU architecture-specific bugs can be reproduced (stack and memory corruption bugs)
- A debugger can be connected to inspect the entire software stack
The main disadvantage of full-system emulation is that the performance overhead is higher since simulation happens at the CPU instruction level. Programs consist of many CPU instructions so the task of emulation is performance-sensitive. Luckily the micro:bit’s CPU is much less powerful than CPUs available in our laptops and desktops, so programs execute at a reasonable speed.
Running micro:bit programs on QEMU
QEMU emulates the core devices on the micro:bit, including the serial port (UART) and timers. This is enough for developing and testing low-level software but does not offer the LEDs, radio, and other devices that most micro:bit programs rely on. These devices might be emulated by QEMU in the future, but for now the main use of QEMU is for developing and testing low-level micro:bit code.
$ qemu-system-arm -M microbit -device loader,file=test.hex -serial stdio
Any output written to the serial port is printed to the terminal by QEMU.
Debugging micro:bit programs with QEMU and GDB
QEMU has GDB guest debugging support. This means GDB can connect to QEMU in order to debug the guest software. This is similar to debugging a real system over JTAG, except no hardware is necessary!
Connect with GDB to debug the guest:
$ qemu-system-arm -M microbit -device loader,file=test.hex -s $ gdb (gdb) target remote tcp:127.0.0.1:1234 (gdb) x/10i $pc => 0x161c4: ldr r3, [r4, #0] 0x161c6: cmp r3, #0 0x161c8: beq.n 0x161d2 0x161ca: ldr r3, [pc, #48] ; (0x161fc) 0x161cc: ldr r3, [r3, #0] 0x161ce: cmp r3, #0 0x161d0: bne.n 0x161d8 0x161d2: movs r0, #6 0x161d4: bl 0x16160 0x161d8: ldr r0, [r4, #0]
Having a debugger is very powerful. QEMU can also load ELF files in addition to the popular .hex files used for micro:bit programs. ELF files can contain debugging information that enables source-level debugging so GDB can display function and variable names as well as listing the source code instead of showing assembly instructions.
QEMU now offers a platform for developing and testing micro:bit programs. It is open to future extension, hopefully to emulate more devices and offer a graphical user interface.
micro:bit emulation was contributed by Julia Suvorova and Steffen Görtz as part of their Outreachy and Google Summer of Code internships with QEMU. Jim Mussared, Joel Stanley, and Stefan Hajnoczi acted as mentors and contributed patches as well.