14.1.1.3. 模拟器#
有两个 TARGET 取值会将固件构建为在你主机上的 模拟器 中运行,无需连接任何硬件。它们的存在使得固件可以在任何地方运行和测试。
| 内核 | NPU | 模拟器 |
|---|---|---|---|
| Cortex-M7 | 无 | QEMU |
| Cortex-M55 | Ethos-U55 (256 MACs) | Arm FVP -- Corstone SSE-300 |
MPS2_AN500 是不带 NPU 的基础 Cortex-M7 目标。它在 QEMU 下运行,启动很快,是练习与平台无关的代码和测试套件的轻量方式。
MPS3_AN547 是带 Ethos-U55 NPU 的 Cortex-M55,运行在 Arm 的 Fast Models 上——即 FVP,它对 Corstone SSE-300 参考子系统进行建模。这是在模拟中练习 NPU 和 ML 模型路径的目标。
两者都提供 ROM 文件系统和充裕的 RAM(M55 上还有 NPU),因此视觉和 ML 脚本无需修改即可运行。
没有真实的传感器,但 csi 模块仍可针对一个虚拟传感器工作——csi.CSI.snapshot() 返回一个合成的、带动画的测试图案(灰度下是滚动的棋盘格,RGB565 下是渐变),而不是实时场景。要处理真实的图像内容,请改为从文件加载:从 ROM 文件系统中的固定文件加载一个 image.Image,或为录制的帧加载一个 image.ImageIO 流。
14.1.1.3.1. 构建与运行#
每个模拟器都是一个由你自行安装的主机工具。你像构建任何其他目标一样构建一个目标(参见 构建固件),然后在对应的模拟器下 run 它——run 会构建 ROMFS 镜像、引导固件,并让它保持运行,同时提供一个你可以连接的串口连接。
14.1.1.3.1.1. MPS2_AN500 (QEMU)#
QEMU 在大多数包管理器中作为 Arm 系统模拟器提供:
Linux(Debian / Ubuntu)——用
apt安装它:sudo apt install qemu-system-armmacOS——用 Homebrew 安装它:
brew install qemu
然后构建并运行目标:
make -j$(nproc) TARGET=MPS2_AN500
make TARGET=MPS2_AN500 run
14.1.1.3.1.2. MPS3_AN547 (Arm FVP)#
FVP 是 Arm 面向 Corstone SSE-300 的固定虚拟平台(Fixed Virtual Platform),作为 Arm Virtual Hardware 的一部分提供。它仅适用于 Linux——在 Mac 上,请改用上面的 QEMU 目标。
下载该捆绑包,解压它,并将其 bin/ 目录加入你的 PATH:
wget https://artifacts.tools.arm.com/avh/11.31.28/avh-linux-x86_11.31_28_Linux64.tar.gz
mkdir -p ~/fvp
tar --strip-components=1 -xzf avh-linux-x86_11.31_28_Linux64.tar.gz -C ~/fvp
export PATH="$HOME/fvp/bin:$PATH"
FVP 在运行时还需要 SDK 的 Python 库位于 LD_LIBRARY_PATH 上。请在仓库根目录下每个 shell 导出一次——读取 SDK_VERSION 可在仓库更新固定的 SDK 时保持其正确:
export LD_LIBRARY_PATH="$HOME/openmv-sdk-$(cat SDK_VERSION)/python/lib:$LD_LIBRARY_PATH"
然后构建并运行目标:
make -j$(nproc) TARGET=MPS3_AN547
make TARGET=MPS3_AN547 run
14.1.1.3.2. 运行测试套件#
单元测试位于 scripts/unittest/tests/ 中,其固定图像和数据位于 scripts/unittest/data/ 中。它们使用 mpremote 运行,后者会将 scripts/unittest/ 挂载到正在运行的模拟器上并执行其 run.py。
模拟器链接在原版 mpremote 下很慢,因此请使用仓库中捆绑的、已应用串口补丁的副本(应用一次即可):
patch -N -p1 -d lib/micropython < tools/mpremote-qemu-serial.patch
对于 QEMU 下的 MPS2_AN500,启动该目标——它会打印其串口所在的伪终端(例如 /dev/pts/5):
make TARGET=MPS2_AN500 run
然后,从另一个 shell,将打过补丁的 mpremote 指向该设备:
python3 lib/micropython/tools/mpremote/mpremote.py connect /dev/pts/5 \
mount scripts/unittest/ run scripts/unittest/run.py
对于 FVP 下的 MPS3_AN547,串口改为端口 5555 上的一个 telnet 套接字:
make TARGET=MPS3_AN547 run
python3 lib/micropython/tools/mpremote/mpremote.py connect socket://localhost:5555 \
mount scripts/unittest/ run scripts/unittest/run.py
run.py 会发现并执行每一个测试,为每个测试打印一行带计时的 PASSED / FAILED,并在末尾给出汇总。
14.1.1.3.3. 添加测试#
测试会被自动发现。要添加一个,请在 scripts/unittest/tests/ 中放入一个文件,其中定义一个 unittest(data_path, temp_path) 函数,测试通过时返回 True,失败时返回 False:
# scripts/unittest/tests/circles.py
def unittest(data_path, temp_path):
import image
img = image.Image(data_path + "/shapes.ppm", copy_to_fb=True)
circles = img.find_circles(threshold=5000, x_margin=30, y_margin=30, r_margin=30)
return len(circles) == 1 and circles[0][0:] == (118, 56, 22, 5856)
data_path 和 temp_path 参数指向套件运行时模拟器所看到的两个文件系统:
路径 | 由……支持 |
|---|---|
| 主机的 |
| 开发板的只读 ROM 文件系统,从 |
因此一个新的 测试 无需重新构建,但一个新的 固定文件 则需要:ROM 镜像以 romfs_config.json 而非各个数据文件为依据,所以请通过 touch 开发板的 romfs_config.json(或 make TARGET=<TARGET> clean)强制重新构建并再次运行。
预期值在测试中以内联方式断言,因此没有单独的预期输出文件需要维护。要在运行时跳过某个测试——例如当它需要模拟器未建模的硬件时——请抛出一个消息中包含 "SKIPPED" 的异常。