QEMU embedded simulation
Contract
| Field | Bound contract |
|---|---|
| Trigger | Bare-metal or RTOS firmware needs running without a board: Cortex-M on a QEMU STM32 machine, RISC-V on virt, a GDB stub session, or semihosting output. |
| Authority | Read-only. Emits analysis and commands for the operator to run; no file writes, no rollback needed. No remote mutation. |
| Side effect | QEMU command lines and a verdict in chat. Nothing is written. |
| Done | The firmware boots under the chosen machine, or the blocking limitation (unmodeled peripheral, wrong machine) is named. |
Inputs
- Firmware image (required): an ELF or binary linked for the target machine's memory map.
- Target machine (required): the MCU or
virtmachine the firmware was built for. - Toolchain (required):
qemu-system-arm,qemu-system-aarch64, orqemu-system-riscv32/64, plus a matching*-gdbfor debug sessions.
Procedure
Pick a Cortex-M machine. QEMU models a subset of STM32 boards, per the QEMU STM32 documentation:
Machine MCU Core stm32vldiscoverySTM32F100RBT6 Cortex-M3 netduino2STM32F205RFT6 Cortex-M3 netduinoplus2STM32F405RGT6 Cortex-M4F olimex-stm32-h405STM32F405RGT6 Cortex-M4F arm-none-eabi-gcc -mcpu=cortex-m3 -T linker.ld -o firmware.elf main.c startup.s qemu-system-arm -machine stm32vldiscovery -kernel firmware.elf \ -nographic -serial mon:stdio-kernelaccepts an ELF or a raw binary. List machines withqemu-system-arm -machine help. Match-mcpuand the linker map to the machine's MCU;stm32vldiscoveryis an F100, not an F407. Done when: the firmware reachesmainunder the right machine.Use generic
virtfor Cortex-A code.qemu-system-aarch64 -machine virt -cpu cortex-a53 -m 128M \ -kernel firmware.elf -nographicDone when: the image boots on
virt.Run RISC-V bare metal.
qemu-system-riscv32 -machine virt -nographic \ -bios none -kernel firmware.elf-bios nonestarts at the reset vector with no OpenSBI. Done when: the image runs from its reset entry.Debug through the GDB stub.
qemu-system-arm -machine stm32vldiscovery -kernel firmware.elf \ -S -gdb tcp::3333 -nographicarm-none-eabi-gdb firmware.elf (gdb) target remote :3333 (gdb) monitor system_reset # QEMU monitor command over the stub (gdb) load # write ELF sections into target memory-Shalts the CPU at reset so GDB connects before any instruction runs. Done when: GDB controls the emulated target.Enable semihosting when the toolchain supports it.
qemu-system-arm ... -semihosting-config enable=on,target=nativeSemihosting routes
printfand friends to the host through a syscall trap; the C library must be built with semihosting support. Done when: firmware output reaches the console without a UART model.Respect the limitations. Per QEMU's STM32 machine documentation:
Gotcha Reality No GPIO The GPIO controller is not modeled; LED-blink tests need hardware or another machine No DMA or I2C Not implemented on the STM32 machines Partial RCC Reset and enable only; no full clock tree Wrong MCU assumed stm32vldiscoveryis an F100 Cortex-M3; match CPU flags and linker memoryTiming Not cycle-accurate against silicon Validate on hardware before sign-off. Done when: the test plan accounts for every unmodeled peripheral the firmware touches.
Failure and recovery
| Symptom | Cause | Fix |
|---|---|---|
| QEMU exits immediately | main returned |
End with a loop or WFI |
| Wrong entry address | ELF not linked for the machine | Check readelf -h entry against the memory map |
| No serial output | Wrong UART model address | Use the machine's UART map or semihosting |
| GDB cannot connect | Missing -S or -gdb |
Add -S -gdb tcp::3333 |
| HardFault in QEMU | Invalid stack or vector table | Fix startup; see baremetal-startup |
Output
A working QEMU command line for the firmware and machine, the GDB stub session when debugging, and the named list of unmodeled peripherals that force hardware validation.