做嵌入式开发,在公司电脑和个人电脑之间来回折腾环境,是很多人都有过的经历。尤其是 Keil MDK 加 JLink 这套组合,在 Windows 主机上装一次倒不难,但要换电脑、换系统、或者想隔离一个干净环境的时候,重装一遍成本还真不低。我自己的主力机是 Linux,但客户那边交付的工程又是基于 Keil 的,总不能每次都在主机上再开一个 Windows 系统。后来我把 VMware Workstation 里的一套 Windows 7 虚拟机当成了固定的 Keil 开发环境,JLink 烧录、在线调试、串口打印全在虚拟机里完成,用了一年多,踩过不少坑,也摸清了虚拟机里做嵌入式开发的脾气。今天这篇就把“虚拟机安装 Keil、JLink”的完整过程、底层逻辑和排查经验一次讲清楚,希望能帮到正在纠结要不要这样干的人。
先说明一下,这篇博文面向的场景是:用虚拟机作为 ARM Cortex-M 系列的嵌入式开发环境,通过 USB 把 JLink 仿真器接入虚拟机,在 Keil MDK 里完成编译、下载和在线调试。适合哪些人看?想换 Linux 主机又离不开 Keil 的朋友、公司电脑受限想在虚拟机里隔离开发环境的工程师、还有刚开始学嵌入式想在任意系统上搭一套环境的初学者。
1. 项目背景与整体思路:为什么要在虚拟机里搭开发环境
1.1 虚拟机方案解决的核心痛点
很多人一听“虚拟机装 Keil”,第一反应是兼容性差、USB 不稳定、可能跑不动。但你要是真遇到过下面这些场景,就会明白这套方案有多香。
第一是主机系统本身不是 Windows。比如你长期用 Ubuntu 或者 macOS,但工作的代码工程是 Keil 工程,源文件倒是能用编辑器打开,可编译下载怎么办?装个虚拟机是目前最省事的答案。第二是公司电脑管控严格,不让装非授权软件,但整个部门都在用 Keil + JLink,这时候在虚拟机里放一套独立环境,至少能做到环境可备份、可迁移、不污染主机。第三是个人电脑上要同时维护多个版本的 IDE 和工具链,比如有人要保留 Keil 4 的老工程,又装了 Keil 5 的新环境,两个版本在同一台机器上容易起冲突,放在不同虚拟机里就彻底隔离了。
我当时的实际需求更简单:我在 Linux 主机上做代码编辑和 Git 管理,但调试 STM32 必须回到 Keil,而且不想在 Linux 上折腾 WINE 那套。实验下来,虚拟机方案完全能胜任日常开发,尤其对编译频率不高的中小型工程,体验和真机几乎没有差别。
1.2 方案选型:VMware Workstation 还是 VirtualBox
虚拟机软件的选择,决定了后面 USB 识别和性能表现。市面上主流就是 VMware Workstation 和 Oracle VirtualBox,我也都用过,最终长期稳定用的是 VMware Workstation。两者都能做到 USB 设备直通,但 VMware 在 USB 设备识别速度和稳定性上明显更靠谱,特别是 JLink 这种需要持续通信的调试器,在长时间调试时不掉线是最关键的。
这里还有个好消息:VMware Workstation Pro 现在对个人用户已经是免费的,官方个人授权可以在官网直接申请。博通收购 VMware 之后把这个门槛取消了,个人非商业用途直接免费使用,这一点让 VMware 成了我觉得最值得推荐的选择。如果预算和网络条件不允许,VirtualBox 也能用,但建议要有心理准备,它的 USB 驱动兼容性在 Windows 7 虚拟机上偶尔会抽风。
1.3 环境规划与版本基线
在开始安装之前,我建议先规划好版本,避免装到一半发现不兼容。以我自己稳定的组合为例,直接给你一套参考基线:
| 软件 | 版本 | 说明 |
|---|---|---|
| 虚拟机软件 | VMware Workstation 17 Pro | 个人授权免费,USB 3.1 支持好 |
| 虚拟机操作系统 | Windows 7 SP1 64位 | 占用资源少,兼容老工具 |
| 芯片开发工具 | Keil MDK 5.39 | 稳定,社区版可免费用于小工程 |
| 仿真器驱动 | SEGGER J-Link V6.80 及以上 | 官方驱动包,含 JLink Commander |
这套组合的兼容性我实测过,Win7 虚拟机的资源占用比 Win10/Win11 低不少,而且 Keil 5 对 Win7 的支持很完善。你要是新电脑,也可以装 Win10 虚拟机,但内存和磁盘的初始配置要适当调大,后面我会细说。另外注意一点,Keil MDK 有官方社区版,对学习和小型项目完全够用。我建议尽量走官方正规授权流程。
2. 虚拟机系统准备与基础配置
2.1 创建虚拟机时的关键设置
打开 VMware Workstation 新建虚拟机,选择“自定义(高级)”,这一步很重要,默认的“典型”配置会少掉一些关键选项。硬件兼容性选 Workstation 17.x,这个版本对 USB 3.1 和 64 位客户机的支持更好。
到了“客户机操作系统”这一步,选“Microsoft Windows”和“Windows 7 x64”。这里提醒一下,如果你在 VMware 17 上看不到“配置”或“打开”选项,那是因为新版的界面默认用“虚拟机库”代替了传统的“命令面板”,你要点的是主界面中部的绿色“创建新虚拟机”按钮,然后在向导中进行配置,而不是在标签页上右键找“配置”。另外新版 VMware 对 Windows 7 的兼容层有些改动,如果创建时提示不支持的硬件版本,把“硬件兼容性”改成 Workstation 12.x 或 8.x 也是可用的,只是少了少量新特性。
内存建议分配 4GB 以上,如果你的主机内存小于 8GB,那就给虚拟机 2GB,但 Keil 编译时可能会比较吃力。处理器给 2 核就够用,Keil 编译的并行度也就那样,给太多核反而影响主机性能。网络用 NAT 模式即可,虚拟机里不需要和局域网内设备通信,NAT 最稳妥。
2.2 Windows 7 系统安装与 VMware Tools
系统安装镜像用原版 ISO,别用各种精简版,精简版经常会去掉 USB 驱动和 .NET 组件,后面装 Keil 或者 JLink 驱动时会莫名其妙失败。装完系统进入桌面后,第一件事是安装 VMware Tools。
VMware Tools 在虚拟机中的作用经常被低估。它不只是实现主机和虚拟机的剪贴板共享、拖拽文件,它还会安装虚拟机的 USB 控制器驱动、SVGA 显卡驱动和鼠标驱动。不装 VMware Tools,后面你发现 JLink 插上去没有反应,首先要怀疑的就是它。
安装 VMware Tools 的路径很简单:VMware 菜单栏选“虚拟机 -> 安装 VMware Tools”,系统里会弹出一个安装向导,一直下一步。装完重启虚拟机,桌面分辨率会变正常,USB 设备识别的底层问题也就解决了。
2.3 USB 控制器与设备接入配置
在虚拟机设置界面中,找到“USB 控制器”选项,确认勾选了“USB 3.1”或“USB 3.0”。如果你用的是 USB 2.0 的 JLink 老版本,选“USB 2.0”反而更稳。
然后就是接入 JLink 的时机问题。我建议先不要插 JLink,等系统完全启动、VMware 界面就绪后,再把 JLink 的 USB 线插到主机上。这时候 VMware 会弹出一个提示框:“把 J-Link 连接到虚拟机吗?”点“连接”即可。如果你之前点了“记住我的选择”,那以后会自动连接。这个动作也可以在“虚拟机 -> 可移动设备 -> J-Link -> 连接”里手动操作,非常方便。
还有一个细节:如果 VMware 没弹出连接提示,多半是 USB 设备已经被主机的驱动程序占用了,你需要先在“可移动设备”菜单里看那个设备的状态,如果是“已连接(主机)”,就点一下“断开连接(与主机)”,然后再点“连接(连接到虚拟机)”。
2.4 虚拟机性能调优与日常使用习惯
虚拟机跑 Keil,编译性能确实会比主机低一点,但不至于不能接受。以 STM32F103 的工程为例,全量编译大概比裸机慢 10% 到 20%,增量编译基本无感。如果你觉得编译卡,优先看内存是不是不够。Win7 虚拟机 + Keil 5 + 浏览器 + 几个文档,4GB 内存是起步,8GB 才舒服。
磁盘建议 80GB,不是现在要用这么多,而是 Keil 的 Pack 包安装后体积很快膨胀,加上各种 SDK 和例程,你会惊讶空间消耗的速度。存储用“将虚拟磁盘拆分成多个文件”,方便备份和迁移。
另外,我强烈建议给虚拟机做快照。系统装完、驱动装完、Keil 环境配好之后各打一个快照,之后要是环境崩了、注册表乱了,直接恢复快照,比重新折腾一遍省太多时间了。
3. Keil MDK 安装与许可证验证
3.1 版本选择:MDK 5.39 还是更高版本
Keil MDK 的版本选择,直接影响工程兼容性和许可证管理。我推荐 5.39 是因为它相对稳定,对 Cortex-M0/M3/M4 系列支持完善,且 Pack 安装器比较成熟。新版本的 Keil 5.40 之后界面和编译器行为也有调整,但遇到老工程时可能会有细微警告,所以如果你是来搞维护老项目的,装 5.39 更保险。
另外 Keil 本身提供社区版和评估版,个人学习时可以直接用社区版,但注意它有代码量限制,对小工程完全够用。我还是强烈建议使用官方正规许可证流程,既安全又稳定,尤其是企业环境下更是如此。虚拟机里时装正版 License 的体验和主机上是一样的,不会因为虚拟化环境而出现验证失败的问题。
3.2 安装步骤与组件选择
双击安装包,安装向导里会提醒关闭杀毒软件,这个对 Keil 特别重要。Keil 的安装过程中会往系统盘写入驱动文件,很多杀毒软件会误拦截,导致安装完成后 Keil 无法正常启动。
安装路径建议用默认的C:\Keil_v5,不要去改到中文路径或带空格的目录,Keil 对路径的容忍度一直不高。到了“Choose Components”这一步,把MDK Core全部勾选,C/C++ 编译器是必须的。如果是新手,Device Family Pack可以先在线下载,也可以后面在 Pack Installer 里单独装。安装完打开 Pack Installer,搜索你的芯片型号(比如 STM32F103C8),安装对应的 Device Family Pack。这一步是在线下载,需要网络支持良好。
这里补充一个很多人不知道的点:Pack 安装器下载慢或失败时,不要反复点重试,可以先下载 pack 文件到本地,再用“File -> Import”手动导入,比在线安装可靠得多。
3.3 许可证配置与验证
许可证是新手最容易卡住的地方。Keil MDK 分两种授权模式:单机版 License 和浮动 License。单机版直接在 IDE 里打开File -> License Management,在Single-User License下面输入你从官方渠道获取的正版许可证号,点Add LIC即可。
验证是否成功,看 License Management 窗口的“Product”栏里是否出现MDK Professional或MDK Standard,以及到期时间是否为 2030 年或者不限。如果你用的是评估版,License Management 也能看到剩余评估天数。
注意:不要装完 Keil 就去网上找“注册机”,这类破解工具在虚拟机里运行反而更容易被杀毒软件检测和查杀,而且国外芯片厂商的开发工具大多自带联网验证,一旦被封会导致工程无法编译。我用的一直是官方正规流程,稳定且没有后顾之忧。
3.4 Keil 工程首次编译验证
环境装完,最好先建一个最小工程验证一下编译链路是否正常。以一个 STM32F103C8 的空工程为例:创建工程后在 Device 选择界面选STMicroelectronics -> STM32F1 Series -> STM32F103C8,然后添加一个空的 main.c,写一个简单的 GPIO 闪烁程序,编译。
编译结果看 Build Output 窗口。正常情况会显示0 Error(s), 0 Warning(s)。如果出现An error occurred while loading the flash loader algorithm或者找不到编译器等错误,先检查 Pack 是否安装完整,再看文件路径有没有中文。
顺带提一下,Keil 的调试器里“Watch 窗口”可以显示结构体变量,很多人第一次用找不到。在调试模式下,View -> Watch Window 1,然后在 Watch 里按F2输入变量名,如果变量是结构体,它会自动展开成员列表;如果看不到成员,看看变量是否被优化掉了,把优化等级改为-O0再看。
4. JLink 驱动安装与 USB 设备映射
4.1 确认虚拟机内的 USB 设备接入状态
JLink 驱动安装之前,先确认虚拟机到底有没有识别到 JLink 硬件。打开虚拟机的“设备管理器”,找到“通用串行总线控制器”。如果 JLink 正确连接,里面会出现一个带黄色感叹号的未知设备或者带名字的J-Link。如果什么都没有,那问题出在 USB 映射层面,而不是驱动问题。
这个排查顺序非常重要。很多人一看到设备管理器没有 JLink,就直接去装驱动,结果安装程序提示找不到设备。其实只要在 VMware 的“可移动设备”菜单里,看到 J-Link 后面写了一个“已连接(虚拟机)”,就说明 USB 层已经通了,剩下只是驱动问题。
4.2 JLink 驱动安装与设备管理器检查
JLink 驱动一般从 SEGGER 官网下载官方驱动包,文件名为JLink_Windows_Vxxx.exe,这里面其实是一个全家桶,包含 USB 驱动、JLink Commander、GDBServer、DLL 库等。安装的时候勾选全部组件,包括USB Driver for J-Link,其他选项我建议全选,因为日常开发不一定哪天就要用到 GDBServer 或者 RTT。
装完驱动,重新插拔一次 JLink(在 VMware 里先断开再连接),设备管理器里的未知设备就会变成JLink或者J-Link,并且没有感叹号。如果你在“通用串行总线控制器”里看到Unknown Device,驱动没装上,建议检查系统是否缺少 VC++ 运行库,Win7 装机镜像精简版经常会缺,装个vcredist集合包基本能解决。
4.3 JLink 与目标板的物理连接要点
虚拟机里的驱动装好了,硬件连接也得跟上。JLink 和目标板之间一般用 SWD 四线方式连接,比 JTAG 节省引脚,也够日常调试用。SWD 接口定义如下:
| JLink 引脚 | 功能 | 接到目标板 |
|---|---|---|
| 1 | VTref(目标参考电压) | 目标板 3.3V 电源 |
| 2 | SWDIO | PA13 / SWDIO |
| 3 | SWCLK | PA14 / SWCLK |
| 4 | GND | 公共地 |
| 7 | NRST(可选) | 复位脚 |
这里最容易出问题的是 VTref。JLink 是靠 VTref 引脚来检测目标板是否供电的,如果 VTref 没接,JLink 会报Cannot measure target voltage,因此很多调试器连接失败都和这个引脚有关。接线完成后打开 JLink Commander 验证一下,界面输入connect,按提示选择设备型号和接口,如果能正常识别 ID code,说明连接没有问题。
还有一个常被忽略的点:JLink 的线序和杜邦线颜色并不统一,不是每一种杜邦线都按红黄绿黑的顺序排。接线前建议用万用表确认一遍 JLink 排针 1、2、3、4 脚分别对应哪根线,避免把 SWDIO 和 SWCLK 接反。
4.4 在 Keil 中配置 Debugger 并完成一次烧录
Keil 里配置 JLink 调试器,路径是Options for Target -> Debug。右侧找到Use下拉框,选择J-LINK / J-TRACE Cortex,然后点旁边的Settings。
Settings 弹窗里面有Debug和Flash Download两个核心配置。Debug 页里,如果 JLink 连接正常,SW Device区域会列出你的目标芯片 ID,比如STM32F103C8显示为0x1BA01477。如果没有显示,多半是接线或驱动问题。Flash Download页勾选Reset and Run,这个选项很重要,勾选后烧录完代码目标板会自动复位运行,否则就会出现“烧录成功但按复位才跑”的现象。Programming Algorithm 里要添加目标芯片对应的 Flash 算法,STM32F1 选STM32F10x Med-density Flash。
配置好后直接点 Keil 工具栏的Download,Build Output 窗口会显示Application running,烧录成功。此时你可以断开 JLink,目标板独立上电运行,程序就在跑了。
5. 常见问题排查与实操经验
5.1 VMware 17 与 Windows 7 虚拟机的兼容性冷战
前面提到过,新版本 VMware Workstation 对 Windows 7 虚拟机的支持有些微妙的变化。你在创建 Win7 虚拟机时可能会遇到“没有配置和打开选项”的情况,这通常是 VMware 的“虚拟机库”界面和传统菜单不一致导致的。解决方式是:在 VMware 主界面的“虚拟机库”里面选中你的虚拟机,右侧会显示“打开此虚拟机”,点那个按钮而不是找传统右上角的“打开”。如果创建向导里没有 Windows 7 的选项,添加虚拟机时选择“稍后安装操作系统”——真的,创建向导中没出现 Windows 7 列表时,你直接选“Microsoft Windows”,版本那栏选“Windows 7 x64”,然后继续安装即可。
另外,Windows 7 在 VMware 17 里如果频繁出现 Aero 特效错误,装 VMware Tools 后基本能解决。如果还不行,把虚拟机的显卡加速关掉,只保留基础 3D 支持。
5.2 网络适配器 vmnet1 有感叹号
我在安装完 VMware 之后,偶尔会遇到主机网络适配器 vmnet1 上有个黄色感叹号,这个不影响虚拟机内 NAT 上网,但看起来总让人心里发毛。其实这个感叹号多数时候是 VMware 的虚拟网卡与主机的网络桥接服务没起来。在主机上以管理员身份打开命令提示符,输入:
net stop vmware net start vmware或者去“服务”里找到VMware NAT Service、VMware DHCP Service,把这两个服务的启动类型改成“自动”并启动,感叹号一般就消失了。
提醒一下,很多人在 Win10/Win11 虚拟机上遇到网络感叹号,其实不是 VMware 问题,而是主机开了Hyper-V与 VMware 的虚拟化冲突。把 Windows 功能里的 Hyper-V 关掉,VMware 网络就正常了。
5.3 JLink 连接目标板失败(cannot connect to target)
JLink 连接失败是日常调试里最磨人的一个问题,常见报错包括Cannot connect to target、Could not connect to target和No device found on SWD。
排查顺序我建议先从物理层看:目标板供电了吗?量一下 3.3V 引脚,如果是 0V,优先查电源。VTref 接了吗?这是我在前面强调过的。SWDIO 和 SWCLK 有没有接反?对调一下试试。如果这时候连上了,那恭喜你,问题解决。
如果换了线还是连不上,考虑两个高级原因。第一,目标芯片被读保护了,芯片中设置了 RDP,或者之前的程序配置了不正确的调试引脚复用。这个时候尝试在 JLink Commander 里执行unlock Kinetics或者对 STM32 执行erase、unlock相关命令,有些芯片可以全片擦除后恢复调试口。第二,目标板外部干扰太强,SWD 引脚高速信号受干扰,可以把 SWD 速率调低,在 KeilSettings页把Max Clock从 4MHz 降到 1MHz,很多时候就稳了。
5.4 STM32 上电不能自动运行,但点 Run 就能跑
这个现象非常典型,尤其是新画板子的朋友常常遇到。程序在点击 JLink 的 Run 之后运行正常,但目标板重新上电以后不跑,或者复位键一松开就停住。
先确认 Keil 的Flash Download里有没有勾选Reset and Run。勾选后,JLink 在烧录结束时会自动拉一下目标板的复位脚,释放后从 Flash 启动。如果已经勾选还是不行,查 BOOT0 引脚的接法。STM32 的 BOOT0 如果接高电平,上电后会进入 Bootloader 而不是执行 Flash 中的用户程序。把 BOOT0 拉低,大部分问题就解决了。
还有一种情况是程序本身在启动阶段跑飞,比如晶振配置不对,外部晶振没焊接或者起振慢,导致代码卡死在 SystemInit。这种问题用 JLink 在线调试,单步执行看 PC 指针有没有进hardfault_handler就能定位。
5.5 虚拟机内 JLink 偶尔掉线/USB 设备被主机抢占
虚拟机里用 JLink,最怕的就是调试到一半设备掉线。掉线原因一般是主机的 USB 电源管理策略在作怪,Windows 会在设备空闲时把 USB 设备挂起省电。解决方法是:主机和虚拟机的电源选项里,都关闭 USB 选择性暂停;设备管理器里找到 JLink,在“电源管理”标签页取消“允许计算机关闭此设备以节约电源”。
如果掉线发生在把鼠标点回主机窗口的时候,大概率是 VMware 的 USB 自动切换策略导致的。你把鼠标焦点放回虚拟机、一碰 USB 设备,VMware 因为之前选过“自动连接”,会重新枚举设备。这个枚举过程会造成调试断线。解决方法是:在 VMware 的“可移动设备”菜单里,把 JLink 的连接方式改为“不再自动连接”,需要时手动连接,不要让它自动来回切换。
5.6 其他杂项:卸载、扩展、格式化工程
有些朋友可能在虚拟机上装了 Keil 之后,发现版本不对、或者想换一个芯片厂家的开发环境。卸载 Keil 不要直接删文件夹,要用控制面板的“程序和功能”先卸载Keil MDK Core,再删除残留目录和注册表键HKEY_CURRENT_USER\Keil。否则下次安装时,Pack 管理器可能会报错。
如果你是用虚拟机的目的不只是 Keil 和 JLink,还想搭 GNURM 工具链或者做基于 CMake 的构建系统,也是完全可以的。JLink 命令行工具JLinkExe可以脱离 Keil 独立烧录固件,配合 CMake 或者脚本可以做到一键打包烧录。设置好环境变量,在命令行里执行:
JLink.exe -device STM32F103C8 -if SWD -speed 4000 -autoconnect 1 -CommanderScript flash.jlink这样可以说非常契合现在很多项目的自动构建流程,哪怕你不是 Keil 用户,一样可以用虚拟机里的 JLink 驱动在 Linux 主机上完成烧录。
最后的几点个人经验
虚拟机里跑 Keil 和 JLink 这个方案,我前后折腾过不少时间,最大的体会是:这套环境一旦配置好,后面迁移成本几乎为零。整台虚拟机就是一个文件夹,拷到新电脑上直接打开就能用,不用重装系统、不用重新配驱动、不用再激活软件,这是裸机 Windows 给不了的优势。
最后再分享一个小技巧:如果你要备份虚拟机里的环境,别直接复制整个 VM 文件夹,太占空间。可以先用虚拟机快照,再在 VMware 里选择“管理 -> 清理磁盘”,把未使用的快照和数据压缩掉,然后把.vmdk文件压缩备份,效果和全量备份差不多,但体积能小一半以上。这套“虚拟机 + Keil + JLink”的组合,我现在用了两年多,已经成了固定的开发基础设施。希望对看到这篇文章的你有帮助。