VSCode + Renode:打造现代化的嵌入式仿真开发环
在传统的嵌入式开发中,我们往往需要依赖实体开发板、仿真器(ST-Link/J-Link)、各种驱动、复杂的 IDE(如 IAR、Keil),不仅环境搭建繁琐,还会受到硬件数量、条件、测试风险的限制。
但随着 Renode(Antmicro) 的成熟,现在我们终于可以:
- 使用 VSCode + GCC 做现代化的编辑体验
- 使用 Renode 模拟 **CPU + 外设 **
- 使用 GDB Server 实现调试
- 甚至可以在服务器(树莓派/OrangePi)上远程跑 Renode
过去几天,我一步步搭好了从 VSCode → Renode → GDB 的完整链路,并解决了一堆坑。 这篇文章记录完整的流程、关键配置、常见错误与解决方式。
📌 一、为什么选择 Renode + VSCode?
现代嵌入式开发已经从这样的方式:
❌ IAR + 实物板子 + 烧录器 + 串口线 + 硬件依赖 ❌ 调试断点和步进完全依赖物理板子 ❌ 一个芯片换平台就要重装一堆东西
逐渐走向:
✔ VSCode + GCC:轻量现代化开发体验 ✔ Renode:模拟 STM32/ESP32 等设备,包含 UART、SPI、I2C、GPIO、DMA ✔ GDB Remote:跨平台、可远程调试 ✔ 自动化、可脚本化
这套方式在国外公司非常常见,原因是:
- 更高的开发效率
- 测试可自动化
- CI/CD 可跑仿真
- 对硬件依赖更低
而在国内还不太普及,所以我自己实践后写下这篇文章,希望帮助更多人。
步骤:
- 安装Renode
- 配置Renode(编辑Renode的脚本)
- 配置VScode(.vscode/tasks.josn/.vscode/launch.josn)
- 测试
目标:
- 实现编写代码控制renode模拟外设工作
- 可以使用vscode配合renode对代码进行仿真
📌 二、安装 Renode
Renode 提供多个版本,你只需要选一个能跑的:
资源下载:[Renode的github仓库](renode/renode: Renode - Antmicro’s open source simulation and virtual development framework for complex embedded systems)
我的选择:
renode-latest.linux-portable-dotnet.tar.gz
理由:
- 自带 dotnet runtime
- 不依赖系统的 dotnet/mono
- 可在 OrangePi / Raspberry Pi 上运行
解压后直接运行:
./renode
📌 三、配置Renode
写一个最基础的Renode.resc文件(STM32F103),这个Renode.resc相当于你要模拟MCU的配置表,Renode加载这个.resc,模拟出你想要的环境
这是我最终可运行的版本(可直接用):
using sysbus mach create "stm32f103" machine LoadPlatformDescription @platforms/cpus/stm32f103.repl # 加载固件,renode加载orangepi上.elf文件 machine LoadELF @/home/orangepi/object/renode_portable/firmware.elf # 打开 UART2 showAnalyzer sysbus.usart2 # 开 GDB 服务(端口 3333),让vscode可以使用GDB配合renode实现可视化debug machine StartGdbServer 3333 true start
你可以把它保存为:
run_stm32.resc
📌 四、VSCode 调试配置
配置launch.json,这是最关键的一步。
直接贴可运行版本(适用于 ARM Cortex-M3 / STM32F1):
{ "version": "0.2.0", "configurations": [ { "name": "Debug STM32F103 on Renode Remote", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/build/firmware.elf", "cwd": "${workspaceFolder}", "miDebuggerPath": "arm-none-eabi-gdb", "miDebuggerServerAddress": "xxx.xxx.xxx.xxx:3333", "preLaunchTask": "Run Renode Remote", "stopAtEntry": true, "setupCommands": [ { "text": "set pagination off" }, { "text": "set confirm off" }, { "text": "set print pretty on" } ], /* On restart: pause, reload ELF, reset CPU (mimic your manual sequence) */ "postRemoteConnectCommands": [ { "text": "monitor machine Pause" }, { "text": "monitor sysbus LoadELF @/home/orangepi/object/renode_portable/firmware.elf" }, { "text": "monitor cpu Reset" } ], "externalConsole": false, "targetArchitecture": "arm" } ] }
核心点:
"miDebuggerPath": "arm-none-eabi-gdb", "miDebuggerServerAddress": "xxx.xxx.xxx.xxx:3333",
解释:
- miDebuggerPath:本机要使用的 GDB(你电脑上安装的)
- miDebuggerServerAddress:远端 Renode 的 GDB server 监听地址
"preLaunchTask": "Run Renode Remote",
VSCode 会先执行名称为 "Run Renode Remote" 的任务(在 tasks.json 里)。
"postRemoteConnectCommands": [ { "text": "monitor machine Pause" }, { "text": "monitor sysbus LoadELF @/home/orangepi/object/renode_portable/firmware.elf" }, { "text": "monitor cpu Reset" } ],
这是整个调试流程的灵魂。
逐句解释:
① 暂停仿真
monitor machine Pause
防止 Renode 继续运行旧固件。
② 在 Renode 内重新加载 ELF
monitor sysbus LoadELF @/home/orangepi/object/renode_portable/firmware.elf
原因:
- VSCode 每次 build 完成本地有一个 ${workspaceFolder}/build/firmware.elf
- 但是远程服务器上的 ELF 通常在另一个目录,比如 /home/orangepi/object/...
- 重新加载 ELF 可以让 Renode 与最新符号一致
这是 “本地 build → scp → 远端自动加载” 的机制。
③ 重置 CPU(类似 reset halt)
monitor cpu Reset
相当于:
- 程序从头开始运行
- 下一步 VSCode 会停在 main()
这个序列相当于模拟 FreeRTOS 中的 debug reset。
Tasks.json配置
出了launch.json,还有tasks.json需要配置,配置如下:
{ "version": "2.0.0", "tasks": [ /* === 1. CMake Configure === */ { "label": "CMake Configure", "type": "shell", "command": "cmake", "args": [ "-S", "${workspaceFolder}", "-B", "${workspaceFolder}/build", "-DCMAKE_BUILD_TYPE=Debug" ], "problemMatcher": ["$gcc"] }, /* === 2. CMake Build === */ { "label": "CMake Build", "type": "shell", "command": "cmake", "args": [ "--build", "${workspaceFolder}/build", "--config", "Debug" ], "dependsOn": ["CMake Configure"], "problemMatcher": ["$gcc"] }, /* === 3. 上传 ELF === */ { "label": "Upload ELF", "type": "shell", "command": "scp", "args": [ "${workspaceFolder}/build/firmware.elf", "root@192.168.31.135:/home/orangepi/object/renode_portable/" ], "dependsOn": ["CMake Build"], "problemMatcher": [] }, /* === 4. 上传 RESC === */ { "label": "Upload RESC", "type": "shell", "command": "scp", "args": [ "${workspaceFolder}/renode/platform.resc", "root@xxx.xxx.xxx.xxx:/home/orangepi/object/renode_portable/" ], "problemMatcher": [] }, /* === 5. 关闭旧 Renode 实例 === */ { "label": "Close Renode Remote", "type": "shell", "command": "ssh", "args": [ "root@xxx.xxx.xxx.xxx", "pkill renode || true" ], "problemMatcher": [] }, /* === 6. 启动 Renode Remote(后台任务) === */ { "label": "Run Renode Remote", "type": "shell", "command": "ssh", "args": [ "root@xxx.xxx.xxx.xxx", "/home/orangepi/object/renode_portable/renode /home/orangepi/object/renode_portable/platform.resc" ], "dependsOn": [ "Upload ELF", "Upload RESC", "Close Renode Remote" ], "isBackground": true, "problemMatcher": { "owner": "Renode", "pattern": [ { "regexp": "^(?!.*)", "file": 0, "line": 0, "message": 0 } ], "background": { "activeOnStart": true, "beginsPattern": "Renode, version .*", "endsPattern": ".*Loaded SVD.*" } } } ] }
测试
使用vscode的一键debug,可以看到vscode正常和renode通讯,打断点和uart输出正常:

更多推荐



所有评论(0)