news 2026/9/24 14:58:04

TVM MicroTVM 与 Arduino 集成测试指南:从 `pytest --board` 到真机串口验证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TVM MicroTVM 与 Arduino 集成测试指南:从 `pytest --board` 到真机串口验证
  • 编译器
  • 深度学习
  • 模型优化

【免费下载链接】tvm

Open deep learning compiler stack for cpu, gpu and specialized accelerators

项目地址:https://gitcode.com/gh_mirrors/tvm7/tvm
点击查看免费下载

本指南围绕 Apache TVM 仓库中 tests/micro/arduino/README.md 所定义的 Arduino 集成测试套件展开,系统讲解 MicroTVM 在 Arduino 平台上的测试运行方式、pytest 命令行参数、受支持的开发板清单,以及底层测试用例是如何完成"模型生成 → 项目编译 → 板卡烧录 → 串口推理验证"全流程的。读完本文,你将能够独立运行 Arduino 相关的 MicroTVM 测试、选择构建专用模式与真机模式、理解各测试文件的职责划分,并能结合源码定位测试背后实际调用的项目生成与运行接口。

一、这套测试是什么:MicroTVM × Arduino 的端到端验证

MicroTVM 是 TVM 面向裸机与嵌入式微控制器(MCU)场景的编译栈,它把 Relay / TIR 编译产物与一个极小的 C 运行时(CRT)打包成可由平台工具链编译、烧录的固件项目。tests/micro/arduino/目录正是用来验证 MicroTVM 与 Arduino 平台集成正确性的测试集合:它既要验证"项目生成与编译"这条离线链路,也要在有真实硬件时验证"烧录、串口通信、板上推理"这条在线链路。

README 开门见山给出了测试的定位与运行方式:需要在一个安装了完整 TVM 依赖的 Python 环境中执行,并通过pytest驱动,例如:

$ cd tvm/tests/micro/arduino $ pytest --board=spresense

其中--board指定目标开发板(上例为索尼 Spresense)。README 同时强调了两点运行约束:

  • 大多数测试需要连接一块受支持的 Arduino 开发板,只有真机上才能完成烧录与推理验证;
  • 如果只是想验证项目生成和编译链路,可以通过--test-build-only跳过所有依赖硬件的用例。

这就是整套测试的两级结构:无硬件可跑的"构建级"测试必须有板子的"硬件级"测试

二、运行环境与前置条件

2.1 Python 环境与 TVM 依赖

README 明确要求"running in a Python environment with all of the appropriate TVM dependencies installed"。也就是说,测试直接 import 已安装的tvmPython 包(见 test_utils.py 中的import tvm.microfrom tvm import relay),因此运行前需要完成 TVM 的构建与 Python 包装入(参考 docs/install/from_source.rst)。此外,测试还依赖requestsnumpyonnxPillow等第三方库(由 test_utils.py 与 test_arduino_rpc_server.py 的导入可见)。

2.2 Arduino 平台支持

测试所需的 Arduino 项目模板由 MicroTVM 提供。test_utils.py中通过tvm.micro.get_microtvm_template_projects("arduino")定位模板目录,板卡描述文件则位于 apps/microtvm/arduino/template_project/boards.json。这意味着目标板的 Arduino 核心(Core)、工具链以及对应的板卡包需要预先通过 Arduino 生态安装好,boards.json中的package/architecture/board字段正是供 Arduino CLI 定位板卡包使用的。

三、pytest 命令行参数全解析

README 给出的参数只是冰山一角。实际的参数定义位于 MicroTVM 官方 pytest 插件 python/tvm/micro/testing/pytest_plugin.py,通过 conftest.py 中的pytest_plugins = ["tvm.micro.testing.pytest_plugin"]自动挂载到本套测试。完整参数如下:

参数类型默认值作用
--platformchoicesmicroTVM 测试平台,本目录场景为arduino(另有zephyr等)
--boardchoices目标开发板,取值来自各平台boards.json的键
--test-build-onlystore_trueFalse只运行不依赖物理硬件的用例(项目生成 + 编译)
--microtvm-debugstore_trueFalse保留项目目录用于调试,并在项目生成时开启 debug 级日志
--serial-numberstrNone板卡串口号,用于在同一型号有多块板卡时精确指定目标设备

其中 README 重点说明的两点是:

  1. 查看支持的--board取值
$ pytest --help

插件会在--help中列出--board的合法 choices——它们由get_supported_boards("zephyr")get_supported_boards("arduino")的键合并而成。

  1. 多块相同板卡时指定串口号
$ pytest --board=due --serial-number="4873ce"

--serial-number会透传给项目生成参数(见 test_utils.py 中generate_project的 options 字典),最终由 Arduino 上传工具用于在多个相同 VID/PID 的设备中锁定目标板。

3.1 硬件测试是如何被跳过的

--test-build-only的实现同样在 python/tvm/micro/testing/pytest_plugin.py:当该选项被置位时,插件会给所有带requires_hardware标记的用例统一打上pytest.mark.skip;该标记则由 conftest.py 的pytest_configure注册。换句话说,"构建级"与"硬件级"的区分不是散落在各测试函数里的 if 判断,而是由插件统一管理的一条标记机制。

四、受支持的 Arduino 板卡清单

README 提到可用pytest --help查看板卡列表,而列表的实际来源是 apps/microtvm/arduino/template_project/boards.json。当前仓库中登记的板卡共 11 款:

板卡键(--board取值)芯片型号(model)包 / 架构备注(note)
duesam3x8earduino / sam
feathers2esp32esp32 / esp32因 Feather S2 引导加载器机制,可正常编译但无法自动上传
metrom4atsamd51adafruit / samd
spresensecxd5602ggSPRESENSE / spresense仅从 v2.3.0 SDK 起可用
nano33blenrf52840arduino / mbed_nano
portentah7stm32h7xxarduino / mbed_portenta
pybadgeatsamd51adafruit / samd
rpipicorp2040rp2040 / rp2040
teensy40imxrt10xxteensy / avr
teensy41imxrt10xxteensy / avr
wioterminalatsamd51Seeeduino / samd

注意:boards.json中的board字段是 Arduino 生态内部的板卡名(如arduino_due_x_dbg),与 pytest 的--board短键不同;vid_hex/pid_hex则用于设备识别(部分板卡留空,说明其上传流程不依赖 VID/PID 匹配)。这些字段共同决定了项目生成时的目标配置。

五、测试套件结构:四个测试文件各司其职

目录下除 README 外共有 4 个测试文件与 1 个测试数据目录:

  • conftest.py:加载 MicroTVM 官方 pytest 插件并注册requires_hardware标记;
  • test_utils.py:公共工具——板卡加载、工作区创建、KWS 关键词识别项目生成;
  • test_arduino_workflow.py:模拟用户完整工作流;
  • test_arduino_rpc_server.py:模拟 RPC(host-driven)调优工作流;
  • test_arduino_error_detection.py:验证编译错误能被正确上报;
  • testdata/project.ino:用户自定义的 Arduino 主程序样例。

六、工作流测试:模拟真实用户从生成到串口验证

test_arduino_workflow.py 的模块 docstring 完整描述了它所模拟的用户流程:

  1. 使用一个简单的音频模型生成基础 Arduino sketch;
  2. 像真实用户那样修改.ino文件;
  3. 为目标板编译 sketch;
  4. 若存在物理硬件,则烧录到已连接板卡;
  5. 打开串口连接;
  6. 通过串口输出确认模型行为正确。

6.1 测试中的项目结构断言

test_project_folder_structure断言生成项目顶层应包含microtvm_api_server.pyproject.inosrcsrc下应为modelstandalone_crtplatform.cplatform.h。这印证了 MicroTVM 项目生成的核心产物:C 源码模型、独立 CRT 运行时、平台适配层

test_project_model_integrity进一步检查src/model下应有default_lib0.cdefault_lib1.cdefault_lib2.cmodel.tar——即模型被切分为多个 C 文件并由model.tar统一打包。

test_model_platform_templating验证platform.c中的TVM_WORKSPACE_SIZE_BYTES宏被正确模板化,且其取值被约束在 9000 ~ 30000 字节之间——这是 CRT 工作区大小的配置点。

test_import_rerouting则确认 CRT 源文件(src/standalone_crt/src/runtime/crt/common/crt_backend_api.c)中的#include已被重路由到项目内嵌的 CRT 头文件(include/tvm/runtime/crt/platform.h),保证固件构建不依赖主机 TVM 安装目录。

6.2 用户如何"改"项目:替换 .ino 与注入数据

modified_projectfixture 把testdata/project.ino复制为项目顶层project.ino,并把yes.cno.csilence.cunknown.c四个关键词音频样本拷贝进src/data/。查看 testdata/project.ino 可以理解板上程序的行为:setup()中调用TVMPlatformInitialize()并开启 115200 波特率串口;loop()中依次对四个样本执行performInference,用micros()计时,并将category,runtime,yes,no,silence,unknown的 CSV 行通过串口打印出来,其中TVMExecute即模型执行入口。

6.3 编译与烧录

compiled_projectfixture 调用project.build(),随后test_compile_yes_no_project断言build/目录存在且非空。只有构建成功,才轮到硬件阶段:uploaded_projectfixture 调用project.flash()完成烧录。

6.4 硬件级:串口读取与推理正确性

serial_outputfixture 通过project.transport()打开串口传输通道,读取 2048 字节并解析出 4 行推理结果。随后的两个@pytest.mark.requires_hardware用例是硬件级验证的核心:

  • test_project_inference_correctness:把板上输出与TENSORFLOW_EVALUATIONS中的参考值对比,允许的最大偏差为 2。测试注释说明"由于舍入差异,板上结果与 TensorFlow 原始输出不会逐位相同,但非常接近"——这正是嵌入式 int8 推理的典型现象;
  • test_project_inference_runtime:断言单次推理不超过 200 ms,且多次推理耗时的波动小于 1000 µs。测试注释给出一个关键参照:在 156 MHz 的索尼 Spresense 上,单次推理约 60 ms;同时提醒连接扩展板等外设可能导致耗时波动检查失败。

七、RPC Server 测试:面向调优的 host_driven 项目

test_arduino_rpc_server.py 模拟的是另一条工作流:实例化 Arduino RPC Server 项目 → 编译 → 烧录,之后在主机侧通过 RPC 会话驱动板上执行。它与工作流测试的关键差异在project_type_make_session使用"host_driven"(而 KWS 工作流使用"example_project"),并配合Runtime("crt", {"system-lib": True})把算子注册进板上系统库,从而支持按名调用。

该文件覆盖的能力包括:

  • 基础算子执行test_compile_runtime):构造int8A + BTE 计算图,经tvm.build后通过sess.get_system_lib().get_function("add")在板上执行并校验[6, 7]结果;
  • 性能计时test_platform_timer):用time_evaluator("add", sess.device, number=20, repeat=3, min_repeat_ms=40)在板上做计时测量,验证微基准能力;
  • Relay 图执行test_relay):构建x*x + 1的 Relay 图,用tvm.micro.create_local_graph_executor加载并在板上运行;
  • ONNX 前端链路test_onnx):加载mnist-8.onnx,经relay.frontend.from_onnx转 Relay 后编译,在板上对 digit-2 / digit-9 图片做分类并断言argmax正确;
  • BYOC 能力test_byoc_microtvm):把计算图的一部分用 C 编译器算子分区(byoc.CcompilerAnnotator+PartitionGraph),验证"外来代码 + TVM"混合执行;
  • 大数组 RPC 传输test_rpc_large_array):参数化 1 KiB / 4 KiB / 16 KiB 的int8数组往返传输校验,覆盖 RPC 缓冲边界。

八、错误检测测试:编译失败要被"接住"

test_arduino_error_detection.py 验证了 MicroTVM 项目 API 的错误上报机制:

  • test_blank_project_compiles:未修改的生成项目应当能成功编译;
  • test_bugged_project_compile_fails:向project.ino追加一个多余的花括号}制造语法错误,然后断言project.build()抛出tvm.micro.project_api.server.ServerError

它证明项目构建是"可失败且可检测"的:MicroTVM 通过 Project API Server 与板卡工具链交互,编译错误会被包装为结构化异常而非静默失败,这正是自动化测试与 CI 能够依赖该链路的前提。

九、源码视角:一个测试项目是如何被造出来的

test_utils.make_kws_project(见 test_utils.py)是整套测试的核心工厂,它完整复现了 MicroTVM 的离线编译流程:

  1. boards.json--board查得目标芯片模型(ARDUINO_BOARDS[board]);
  2. 通过fetch_model_from_url下载 TensorFlow 官方 micro_speech 的 TFLite 模型(固定 URL 与 SHA-256 校验,保证可复现);
  3. tvm.target.target.micro(model)构造裸机 target,Runtime("crt")选择 CRT 运行时,Executor("aot", {"unpacked-api": True})选择 AOT 执行器;
  4. opt_level=3且关闭向量化的 PassContext 下执行relay.build
  5. 调用tvm.micro.generate_project(template_dir, mod, output_dir, options)生成 Arduino 工程,options 中包含boardproject_typeverboseserial_number

这套调用链也正是 MicroTVM 用户在自己项目中落地 Arduino 部署的标准姿势:下载/转换模型 → Relay 编译到 CRT + AOT → generate_project 产出可编译的 Arduino 工程

十、无硬件时怎么跑:构建专用模式小结

如果手头没有开发板,又希望快速验证链路,推荐做法是:

$ cd tvm/tests/micro/arduino $ pytest --board=spresense --test-build-only

该命令会执行全部项目生成、结构完整性、模板化与编译类用例(对应test_arduino_workflow.pycompiled_project之前的阶段、test_arduino_error_detection.py的全部用例等),而所有带requires_hardware标记的串口与推理用例将被插件自动跳过。如需保留生成的项目目录以人工检查产物,可叠加--microtvm-debug

有了真机后,再移除--test-build-only并(可选)指定--serial-number即可切换到完整端到端验证。这套"构建可离线、推理需真机"的两级设计,让 Arduino 集成测试既能进入纯软件 CI,也能服务于真实的硬件回归。

  • 编译器
  • 深度学习
  • 模型优化

【免费下载链接】tvm

Open deep learning compiler stack for cpu, gpu and specialized accelerators

项目地址:https://gitcode.com/gh_mirrors/tvm7/tvm
点击查看免费下载
上一篇:LinkSwift 免费网盘直链获取完整指南:5 分钟安装,八大网盘直链下载
下一篇:Google Indexing Script与AI:智能预测索引效果的尝试

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 14:53:24

PyCaret 平台运维指南:备份、升级、可观测性与弹性扩展实战

【免费下载链接】pycaret Open-source, low-code AutoML platform for Python. PyCaret 4.0: sklearn-native engine React control plane. 项目地址: https://gitcode.com/gh_mirrors/py/pycaret 点击查看 免费下载 PyCaret 4.0 的 sklearn 原生引擎之上构建了完…

作者头像 李华
网站建设 2026/9/24 14:52:35

2026年软著申请全流程详解(附材料清单)

## 一、申请条件软件著作权申请的门槛并不高,个人和企业都可以申请。只要你有独立开发完成的软件作品,就可以申请软著登记。具体来说,软件必须是开发者独立开发完成的,要有固定的表达形式,也就是要有可运行的代码和相应…

作者头像 李华