Renode仿真STM32H7

QEMU、Proteus

Views:  times Updated on May 20, 2025 Posted by elmagnifico on May 19, 2025

Foreword

之前做了QEMU模拟运行FreeRTOS,模拟STM32,但是毕竟不是官方QEMU,对于嵌入式这边的芯片或者设备模拟还是差一点。

https://www.qemu.org/docs/master/system/arm/stm32.html

Renode比较知名的就是用来模拟物联网设备,这种设备往往都弱一些,MCU这种比较多。

具体关于这两个说法有很多,谁更合适还是要实际用一用,体验一下才行

Renode

https://renode.io/

https://github.com/renode/renode

Renode 的指令模拟器使用 C 语言编写,外设模拟器使用 C# 语言编写,兼顾了运行效率和开发效率.

image-20250519163959004

Windows下直接安装即可,启动以后是一个命令行程序,这里可以加载我们的模拟固件

测试

start @scripts/single-node/stm32f746.resc

不建议跑这个例子,只是个输出helloworld,超级卡

start @scripts/single-node/stm32f746_mbed.resc

image-20250519164918218

启动以后就能看到输出了

stm32f746.resc文件解析

# 定义仿真平台和描述
:name: STM32F746
:description: This script runs Dartino on STM32F7 Discovery.

# 创建仿真机器
using sysbus
$name?="STM32F746"
mach create $name

# 加载平台描述
machine LoadPlatformDescription @platforms/boards/stm32f7_discovery-bb.repl

# 配置显示和分析器
# 设置LTDC(LCD-TFT显示控制器)在仿真中的虚拟帧率为每秒100帧;
# 详细解释如下:
# ltdc:指的是仿真平台中的LTDC外设(LCD-TFT显示控制器);
# FramesPerVirtualSecond:表示“每虚拟秒的帧数”,即仿真环境下LTDC每秒刷新多少帧;
# 100:具体的帧率数值,这里设置为100帧每秒;
# 作用:
# 在Renode仿真环境中,LTDC的显示刷新速度会按照这个帧率进行模拟。这样可以控制仿真中LCD显示的流畅度和性能,便于调试和观察# 显示效果;
# 总结:
# 这条指令就是让仿真的LTDC每秒刷新100帧,用于控制虚拟LCD的显示速率;
ltdc FramesPerVirtualSecond 100

showAnalyzer usart1
showAnalyzer ltdc

# 指定要加载的固件,需要elf,而不是bin
$bin ?= @https://dl.antmicro.com/projects/renode/dartino-lines.elf-s_486816-cd8876ab9de60af779f4429dfe16c79bf831b84d


# 可以在模拟启动以后开启Gdb,这样就能直接接入进行调试
# machine StartGdbServer 3333 true

# 定义reset宏
macro reset
"""
    sysbus LoadELF $bin
"""

# 自动运行reset宏
runMacro $reset

platforms/boards/stm32f7_discovery-bb.repl,关于硬件的描述在本地就有,看一下具体内容

using "platforms/cpus/stm32f746.repl"

phy: Network.EthernetPhysicalLayer @ ethernet 0
    Id1: 0x0007
    Id2: 0xC0F1
    AutoNegotiationAdvertisement: 0x00A1
    AutoNegotiationLinkPartnerBasePageAbility: 0x001

phy1: Network.EthernetPhysicalLayer @ ethernet 1
    Id1: 0x0007
    Id2: 0xC0F1
    AutoNegotiationAdvertisement: 0x00A1
    AutoNegotiationLinkPartnerBasePageAbility: 0x001

touchscreen: Input.FT5336 @ i2c3 0x38
    isRotated: true
    MaxX: 480
    MaxY: 272
    -> gpioPortI@13

可以看到这里定义了两个phy给以太网用,还有一个触摸屏,使用的是i2c3的接口,地址0x38,大小,使用的GPIO

使用外设指令,可以查看当前设备的外设和地址

peripherals

image-20250519175919143

STM32H7 模拟

由于官方没有给h7的resc文件,我们就模仿f7写一个

:name: STM32H743
:description: This script runs demo on STM32H743.

using sysbus
$name?="STM32H743"
mach create $name

# 由于没有h7的board 所以这里用cpu模拟
machine LoadPlatformDescription @platforms/cpus/stm32h743.repl

# 模拟所有串口,注意串口名称可能不同
showAnalyzer usart1
showAnalyzer usart2
showAnalyzer usart3
showAnalyzer uart4
showAnalyzer uart5
showAnalyzer usart6
showAnalyzer uart7
showAnalyzer uart8

$bin ?= @platforms/bin/stm32h743.bin

macro reset
"""
    sysbus LoadELF $bin
"""

runMacro $reset

启动测试

start @scripts/single-node/stm32h743.resc

image-20250519184611816

其他指令

Hook

在访问特定外设进行读取后执行 Python 脚本

(machine) sysbus SetHookAfterPeripheralRead gpioPortA "print '%s peripheral has been accessed to read'"

在访问特定外围设备进行写入之前执行 Python 脚本

(machine) sysbus SetHookBeforePeripheralWrite peripheral "print '%s peripheral has been accessed to write'"

include

include可以包含多个模拟器,启动的时候就会都启动,如果是多芯片模拟就比较适合

include @scripts/single-node/quark_c1000.resc

模拟传感器

Renode里有模拟传感器数据的方式,相当于是你给一个数据表,类似CSV结构的,然后指定好接口,频率什么的,硬件就可以直接从这个表中读取到对应的传感器数据了

https://renode.readthedocs.io/en/latest/basic/resd.html

传感器本身的寄存器或者配置,这个机制需要额外去实现,官方有具体的例子

https://github.com/renode/renode-infrastructure/blob/3f1abde88ac5a2dae326b77ab91892f335e78f80/src/Emulator/Peripherals/Peripherals/Sensors/ADXL345.cs

看起来还是比较简单的,就是列出来可能会用到的寄存器,然后实现他的读写,数据寄存器需要额外的一个喂数据接口即可。

大部分外部传感器可以仿照这个来,只要补充寄存器定义和某些返回数据的接口即可

Summary

这个是打印机固件仿真逆向的项目

https://github.com/nviennot/stm32-emulator?tab=readme-ov-file

There’s some existing work in the STM32 emulation space:

  • Mini404 emulates the Prusa Mini. Quite a feat. See the project’s hw/arm/prusa for the peripherals.
  • Qiling emulates all kinds of devices, including STM32s. It would be a good candidate, but wasn’t fitting the bill because 1) it’s written in Python, and is very slow. 2) It doesn’t support what I really want which is tracing in registers that I care about.
  • Renode: Emulate all sorts of devices, written in C#. The configuration files are finicky, and it’s overall pretty slow. I didn’t like it.
  • Tinylabs’ flexsoc-cm3: This is Elliot’s project to have the real stm32 peripherals to be accessible directly to a host that is emulating a CPU. I haven’t tried it, but it looks promising.
  • Use GDB and single step everything. That might be too slow.

前人的经验,主要是嫌弃模拟比较慢

Proteus的仿真也很常见,但是也只适合小型程序仿真,不适合复杂程序。而且绑定了硬件整体也必须得用Proteus才行,两边要配合起来,实际现实中用的还是比较少。可能是以前的PCB比较贵、周期长,没验证好直接打板成本很高吧,所以才有Proteus的仿真,但是现在速度快、成本低,完全用不到。

https://www.arm.com/zh-TW/products/development-tools/simulation/virtual-hardware

还有一个是ARM官方的虚拟化硬件,不过这个东西没有实例,也不知道具体细节是什么样的

比较复杂的是实现外设仿真,这个部分还得看怎么处理

Quote

https://github.com/silent-rain/stm32f103-tutorial/blob/master/docs/Renode%E4%BB%BF%E7%9C%9F%E6%A8%A1%E6%8B%9F.md