如何用 Renode 仿真运行未修改的 ArduPilot STM32 固件并查看启动心跳?
2026/9/15 19:22:33 网站建设 项目流程

如何用 Renode 仿真运行未修改的 ArduPilot STM32 固件并查看启动心跳?

【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot

这个任务的目标是:不改动任何 ArduPilot 固件代码,直接在 Renode 硬件仿真器里跑一块 STM32 飞控板上的固件,等它完成启动流程后,用 MAVProxy 连上仿真出的串口,确认收到固件发出的 MAVLink 心跳(HEARTBEAT)。仓库自带的 Tools/renode 工具链覆盖了从生成板级描述、加载固件到暴露 MAVLink 串口的全过程,支持 STM32 F1、F3、F4、F7、G4、H7、L4 家族——支持范围不是板子白名单,而是由 hwdef 中的 MCU 家族驱动,用Tools/renode/run.py --list可以列出当前接受的 hwdef 目标。

以下以文档中反复使用、且有完整启动结果记录的 KakuteF4 + ArduCopter 为主路径。

确认前提条件

开始之前核对这几项:

  • 你有一份可以构建的 ArduPilot 源码检出,Renode 工具位于仓库内的 Tools/renode 目录;
  • 官方固件下载辅助脚本 tests/fetch_renode.sh 只发布 Linux 包(x86_64 与 aarch64),非 Linux 主机上该脚本会直接报错退出;
  • 新建 SD 镜像时run.py需要 Python 包 pyfatfs 1.1.0;
  • Renode 本身:基础仿真在原版 Renode 1.16.1 上即可工作。仓库建议改用fetch_renode.sh下载的打包版本,它附带性能补丁栈(文档实测约 4 倍提速)和 USB/IP 支持。

run.py--renode参数、$RENODE环境变量、PATH 这个顺序查找 renode 可执行文件,所以下面显式传入下载目录。

准备固件与 Renode 可执行文件

第一步是像平时一样构建目标板固件:

./waf configure --board KakuteF4 && ./waf copter

产物是build/KakuteF4/bin/arducopter,这也是run.py的默认固件位置(--elf/--firmware可覆盖,接受 APJ、raw BIN、Intel HEX 或 ELF)。

第二步下载 Renode 运行时(副作用:从firmware.ardupilot.org下载并解压到build/renode/,脚本会先校验包的latest.json清单、文件尺寸和 SHA-256 再解压):

Tools/renode/tests/fetch_renode.sh

注意该脚本在build/renode已存在时会报错退出,不会覆盖已有目录;确认成功后它会打印 Renode 源码 revision 与可执行文件路径,并运行--version

启动仿真并观察启动过程

从仓库根目录运行:

Tools/renode/run.py KakuteF4 --renode build/renode/renode

这一条命令会做几件事:调用 ArduPilot 生产环境的 ChibiOS hwdef 编译器展开KakuteF4hwdef.dat/hwdef-bl.dat,在build/KakuteF4/renode/generated/下生成板级 REPL/RESC(文档说明该过程不到一秒);把固件和参数存储加载进仿真;然后进入交互式 Renode monitor,此时固件已经在运行,SERIAL_ORDER中的第一个硬件 UART 暴露在tcp:localhost:5762上。

几个影响后续操作的行为需要提前知道:

  • 板卡状态默认持久化在仓库根目录renode/<board>/下:sdcard.img(512 MiB FAT32 稀疏镜像)、flash.img(完整内部 flash,固件写入的参数、任务等会保留)、mcu_id.txt(随机 96 位 MCU 唯一 ID)。状态跨固件 reset 和多次run.py调用保留;移动或删除该目录即可回到擦除/出厂状态。
  • 虚拟时间默认按墙钟速度限速(real-time paced);--unthrottled则全速运行,用于基准测试和自动化回归。
  • 文档给出的 KakuteF4 启动耗时数据(KakuteF4 boot benchmark,文档实测值):原版 portable 构建约 33.6 倍实时、boot 到主循环墙钟 325 秒;启用完整性能补丁栈后约 5.1 倍实时、boot 到主循环 44 秒墙钟。第一次运行时按这个量级预期等待。

连接 MAVProxy 并确认启动心跳

在另一个终端连接仿真出的串口:

mavproxy.py --master tcp:localhost:5762

连接建立后,MAVProxy 应当持续收到固件发出的 HEARTBEAT 消息。文档对 KakuteF4 的标准arducopterELF 记录了完整的启动结果:参数从仿真 flash 加载、BMP280 气压计校准、ICM20689 探测与陀螺校准、RCOut 初始化、EKF3 激活并完成 tilt 对齐,随后进入主车辆循环并执行 prearm 检查(新板子会提示 "Check frame class and type",属预期残留);MAVLink 通道上可见 heartbeat、statustexts、参数读取以及车辆自己发出的 save-notify 广播。收到稳定心跳并能在 MAVProxy 中读出参数,即可认为固件已启动到主循环。

一个容易踩的坑:5762 端口的 socket 终端一次只服务第一个客户端。断开后想重连,需要重启run.py进程,而不是重连终端。

如果你不想手工接 MAVProxy,仓库提供了自动化等价物:Tools/renode/test_all.py 会扫描build/*/bin下已存在的固件,等待 MAVProxy 检测到心跳,再执行完整的param ftp参数下载并要求其非空。单块板可以这样跑:

Tools/renode/test_all.py 'KakuteF4/arducopter'

自动化心跳检查的判定逻辑也见 test_crashdump.py:以recv_match(type='HEARTBEAT', blocking=True, timeout=2)接收心跳,超时则报timed out waiting for the initial MAVLink heartbeat

常用选项与排查

  • --serial N:改选SERIAL_ORDER中另一个串口索引;--uart-port N改 TCP 端口(默认 5762);--uds则改用 Unix 域套接字(APM-UDS-serialN),避免占用 TCP 端口。注意:暴露哪个 UART 不改变固件参数,所选 UART 仍需在固件里配置了目标协议(如 MAVLink)才有对应流量。
  • --exec可在启动后追加 monitor 命令;--port N用 telnet monitor 替代交互控制台。
  • monitor 里echo的参数要加引号(如echo "=== x ==="):未加引号的===是语法错误,会在仿真跑完之后中止脚本,表现为 Renode 卡在提示符上、quit永远不执行,看起来像挂死。
  • 已知 Renode 模型缺陷:原版STM32_Timer在 CCR 为 0 时不触发比较,约 1/65536 概率命中,症状是虚拟时间还在走、CPU 空闲,但 MAVLink、I2C 等全部停住。run.py生成的板级脚本已内置一行SetHookBeforePeripheralWrite修复,走正常启动路径即可覆盖;自己手写 resc 时不能省这一步。
  • 不要在固件运行时以读写方式在主机上挂载同一张sdcard.img;需要主机侧检查文件系统时先停止 Renode。

后续方向

启动心跳确认之后,Tools/renode/README.md 的其余章节覆盖了与本任务相关的延伸能力:--gdb附加带 ChibiOS 线程信息的 GDB、--can桥接 DroneCAN 多播总线、--ethernet-tap把仿真 MAC 挂到主机 TAP、以及图形化启动器launch.py(板卡选择、串口/I2C/CAN 设备挂载与运行时状态面板)。

【免费下载链接】ardupilotArduPlane, ArduCopter, ArduRover, ArduSub source项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询