【物联网设备端开发】ESP开发工具:QEMU的使用方法
概要
本文提供了一些运行QEMU的ESP特定说明。有关QEMU的一般使用问题,请参阅官方文档:https://www.qemu.org/documentation/.
编译 QEMU
准备工作
libgcrypt-devellibgcryptlibgcrypt
配置
ninja
./configure --target-list=xtensa-softmmu \
--enable-gcrypt \
--enable-slirp \
--enable-debug --enable-sanitizers \
--enable-sdl \
--disable-strip --disable-user \
--disable-capstone --disable-vnc \
--disable-gtk
--disable./configure --help
--enable-sdl--enable-gtk--enable-sdl--enable-gtk
编译
ninja
ninja -C build
build/qemu-system-xtensa
编译ESP-IDF程序进行仿真
esptool.py merge_binesptool.py
cd build
esptool.py --chip esp32 merge_bin --fill-flash-size 4MB -o flash_image.bin @flash_args
flash_argsmerge_bin--fill-flash-size 4MB
QEMU中的ESP32目标支持大小为2、4、8和16MB的闪存,创建任何其他大小的镜像都会导致错误。
注意
flash_argsflash_argsbootloader.bin
0x1000 bootloader/bootloader.bin
esptool.py
运行 QEMU
不加载GDB
如果你不需要调试客户应用程序,你可以在不加载GDB的情况下执行QEMU:
build/qemu-system-xtensa -nographic \
-machine esp32 \
-drive file=flash_image.bin,if=mtd,format=raw
flash_image.bin
使用GDB服务器,等待连接
-s -S
build/qemu-system-xtensa -nographic -s -S \
-machine esp32 \
-drive file=flash_image.bin,if=mtd,format=raw
flash_image.bin
然后,要连接GDB客户端,请使用以下命令:
xtensa-esp32-elf-gdb build/app-name.elf \
-ex "target remote :1234" \
-ex "monitor system_reset" \
-ex "tb app_main" -ex "c"
app_mainc
硬件加密支持
从IDF 4.1开始,默认启用以下硬件加密功能:AES、SHA、RSA。 所有这些都在QEMU中实现了ESP32目标。但是,请注意,SHA模拟目前不支持不同SHA类型的并发操作。
以太网口支持
ESP-IDF中添加了对Opencores以太网MAC的支持。
CONFIG_EXAMPLE_CONNECT_ETHERNETCONFIG_EXAMPLE_USE_OPENETHCONFIG_ETH_USE_OPENETHesp_eth_mac_new_openeth
open_eth
用户模式网络
例如,要在用户模式下启动网络(仅TCP/UDP,模拟设备位于NAT之后),请在QEMU命令行中添加以下选项:
-nic user,model=open_eth
一些ESP项目(特别是运行TCP侦听器)可能需要设置端口转发,
-nic user,model=open_eth,id=lo0,hostfwd=tcp:127.0.0.1:PORT_HOST-:PORT_GUEST
hostfwd=tcp:127.0.0.1:22222-:2222nc localhost 2222
指定引导模式
要指定所需的 strapping 模式, 在运行QEMU时需要添加以下参数:
-global driver=esp32.gpio,property=strap_mode,value=0x0f
GPIO_STRAP
0x120x0f
Specifying eFuse storage
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
qemu_efuse.binefusenvram.esp32.efuse
The file must be created before 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.
Note
Specifying eFuse storage is mandatory to test out any platform security features like “Secure Boot” or “Flash Encryption”.
Emulating ESP32 ECO3
For the application to detect the emulated chip as ESP32 ECO3, the following virtual efuses must be set:
- CHIP_VER_REV1
- CHIP_VER_REV2
xxd -p
000000000000000000000000008000000000000000001000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000
00000000
efuse.hexxxd -r -p efuse.hex qemu_efuse.bin
Alternatively, these bits can be set using espefuse:
espefuse.py --port=socket://localhost:5555 burn_efuse CHIP_VER_REV1
espefuse.py --port=socket://localhost:5555 burn_efuse CHIP_VER_REV2
Disabling the watchdogs
By default, Timer Group watchdog timers are emulated, and TG0 WDT is enabled at reset. It is sometimes useful to disable these watchdog timers. This can be done by adding the following to the command line:
-global driver=timer.esp32.timg,property=wdt_disable,value=true
This disables the emulation of TG watchdog timers. Even if the application configures them, they will not fire.
The RTC watchdog timer is not emulated yet, so it doesn’t need to be disabled.
Using esptool.py and espefuse.py to interact with QEMU
Start QEMU:
build/qemu-system-xtensa -nographic \
-machine esp32 \
-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
idf.py
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
esptoolsystem_reset
Specifying ROM ELF file
-kernel-bios-bios
Using flash encryption
Self-encryption workflow
CONFIG_SECURE_FLASH_ENC_ENABLEDmenuconfig
Build the flash image as per the instructions from the Compiling the ESP-IDF program to emulate section.
qemu_efuse.bin
qemu-system-xtensa
build/qemu-system-xtensa -nographic -machine esp32 \
-drive file=/path/to/qemu_efuse.bin,if=none,format=raw,id=efuse \
-global driver=nvram.esp32.efuse,property=drive,value=efuse \
-drive file=/path/to/flash_image.bin,if=mtd,format=raw \
-global driver=timer.esp32.timg,property=wdt_disable,value=true
Adding PSRAM
-m 2M-m 4M
himem
Using SD cards
QEMU emulates SD/MMC host controller used in ESP32. To add an SD card to the system, create an image and pass it to QEMU.
Create a raw image file, for example, 64 MB:
$ dd if=/dev/zero bs=$((1024*1024)) count=64 of=sd_image.bin
Add the following argument when running QEMU:
-drive file=sd_image.bin,if=sd,format=raw
cqow2qemu-img
Only one SD card is supported at a time. You can use either slot 0 or slot 1 of the SD/MMC controller in the application code.
Enabling graphical user interface (GUI)
The ESP32 QEMU implementation implements a virtual RGB panel, absent on the real hardware, that can be used to show graphical interface. It is associated to a virtual frame buffer that can be used to populate the pixels to show. It is also possible to use the target internal RAM as a frame buffer.
To enable the graphical interface, while keeping the serial output in the console, use the following command line:
build/qemu-system-xtensa \
-machine esp32 \
-drive file=flash_image.bin,if=mtd,format=raw
-display sdl \
-serial stdio
gtk-display sdl-display gtk
上一篇: 鸿蒙开发工程师需要学什么