-
Notifications
You must be signed in to change notification settings - Fork 80
Home
This repository contains a fork of QEMU with patches for Espressif chips support. We hope that these patches will eventually be mature enough to become part of upstream QEMU project.
At the moment, Espressif does not provide support for QEMU. We appreciate issue reports, but keep in mind that our response may be delayed. We will likely not be able to help with issues which require extensive troubleshooting or don't have a straightforward way to reproduce them. We will also likely not be able to help with particular use cases which aren't supported yet (e.g. due to missing emulation of some peripherals).
The main branch of this repository is esp-develop
. This branch will often be rebased on top of the upstream master
branch, and force-pushed. If you wish to submit a non-trivial PR, please open an issue first so that we can avoid making conflicting changes.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
The rest of this page provides some ESP-specific instructions for running QEMU. Refer to the official documentation for general QEMU usage questions: https://www.qemu.org/documentation/.
./configure --target-list=xtensa-softmmu \
--enable-debug --enable-sanitizers \
--disable-strip --disable-user \
--disable-capstone --disable-vnc \
--disable-sdl --disable-gtk
(feel free to add more --disable
options, to reduce the first compilation time)
make -j8
A program xtensa-softmmu/qemu-system-xtensa
should be built.
Build an ESP-IDF application, setting CONFIG_ESPTOOLPY_FLASHMODE_DOUT=y
in sdkconfig. The default mode, DIO, does not fully work yet (although it may work if you aren't using spi_flash operations).
Create a flash image, combining the bootloader, partition table, and the application. One option is to use this script (make-flash-img.sh
):
#!/usr/bin/env bash
set -e
arg_projname=$1
arg_flashimg=$2
if [ -z "$1" -o -z "$2" ]; then
echo "Usage: make-flash-img.sh app_name flash_img_file"
exit 1
fi
dd if=/dev/zero bs=1024 count=4096 of=${arg_flashimg}
dd if=build/bootloader/bootloader.bin bs=1 seek=0x1000 of=${arg_flashimg} conv=notrunc
dd if=build/partition_table/partition-table.bin bs=1 seek=0x8000 of=${arg_flashimg} conv=notrunc
dd if=build/${arg_projname}.bin bs=1 seek=0x10000 of=${arg_flashimg} conv=notrunc
Note: it is also possible to use esptool.py
to "flash" the application into Qemu, but Qemu needs to be started with correct strapping mode. See below.
xtensa-softmmu/qemu-system-xtensa -nographic \
-machine esp32 \
-kernel esp32_rom.elf \
-drive file=flash_image.bin,if=mtd,format=raw
xtensa-softmmu/qemu-system-xtensa -nographic -s -S \
-machine esp32 \
-kernel esp32_rom.elf \
-drive file=flash_image.bin,if=mtd,format=raw
To connect using GDB, use the following:
xtensa-esp32-elf-gdb build/app-name.elf \
-ex "target remote :1234" \
-ex "monitor system_reset" \
-ex "tb app_main" -ex "c"
(or put the same commands into a gdbinit script)
This needs an IDF branch with Opencores Ethernet MAC driver support.
- When running
protocols
examples, enableCONFIG_EXAMPLE_CONNECT_ETHERNET
andCONFIG_EXAMPLE_USE_OPENETH
. - When running a custom app, enable
CONFIG_ETH_USE_OPENETH
and initialize the Ethernet driver as it is done in examples/common_components/protocol_examples_common/connect.c (look foresp_eth_mac_new_openeth
).
When starting QEMU, use open_eth
network device.
For example, to start networking in user mode (TCP/UDP only, emulated device is behind NAT), add the following option to the QEMU command line:
-nic user,model=open_eth
TODO: add instructions for running QEMU network in tap
mode.
Add extra argument to the command line to specify the desired strapping mode:
-global driver=esp32.gpio,property=strap_mode,value=0x0f
This sets the value of GPIO_STRAP
register.
- Use 0x12 for flash boot mode (default)
- Use 0x0f for UART-only download mode (since the SDIO part is not implemented)
Add extra arguments to the command line:
-drive file=qemu_efuse.bin,if=none,format=raw,id=efuse
-global driver=nvram.esp32.efuse,property=drive,value=efuse
The first argument creates creates a block device backed by qemu_efuse.bin
file, with identifier efuse
. The second line configures nvram.esp32.efuse
device to use this block device for storage.
The file must be created prior to starting qemu:
dd if=/dev/zero bs=1 count=124 of=/tmp/qemu_efuse.bin
124 bytes is the total size of ESP32 eFuse blocks.
-
Start Qemu:
xtensa-softmmu/qemu-system-xtensa -nographic \ -machine esp32 \ -kernel esp32_rom.elf \ -drive file=flash_image.bin,if=mtd,format=raw \ -global driver=esp32.gpio,property=strap_mode,value=0x0f \ -drive file=qemu_efuse.bin,if=none,format=raw,id=efuse \ -global driver=nvram.esp32.efuse,property=drive,value=efuse \ -serial tcp::5555,server,nowait
The final line redirects the emulated UART to TCP port 5555 (Qemu acts as a server).
Type
q
and press Enter at any time to quit. -
Run esptool.py:
esptool.py -p socket://localhost:5555 flash_id
Flashing with
idf.py
also works:export ESPPORT=socket://localhost:5555 idf.py flash
-
Or, run espefuse.py:
espefuse.py --port socket://localhost:5555 --do-not-confirm burn_custom_mac 00:11:22:33:44:55
Note: esptool can not reset the emulated chip using the RTS signal, because the state of RTS is not transmitted over TCP to Qemu. To reset the emulated chip, run system_reset
command in Qemu console (started at step 1).