ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Keil MDK老工程报错ARM Compiler 5缺失?完整解决方案一次说透

Keil MDK老工程报错ARM Compiler 5缺失?完整解决方案一次说透 老项目打不开、一编译就报“ARM-Compiler Arm Compiler 5.06 update 7 (Build 960) which is not available”这个问题从MDK 5.37开始就没消停过。最近帮朋友看一个遗留工程又撞上了这堵墙。网上说法很多但要么讲得半截要么给的方法在新版本下根本不管用。我把自己实际测试通过的完整方案整理成这篇从报错原因、编译器判断讲起再给三条可行的安装路径附带配置步骤和踩坑实录一次说透。1. 报错信息拆解是哪个环节在找ARM Compiler Version 51.1 你实际看到的报错长什么样先还原一下现场。用Keil MDK打开别人发来的工程或者自己翻了很久的老工程双击编译后Build Output窗口会出现类似下面这样的信息*** Target STM32F103ZET6 uses ARM-Compiler Arm Compiler 5.06 update 7 (Build 960) which is not available.有些版本还会提示Fatal error: Arm Compiler 5 is not installed.还有的干脆是弹窗提示Target uses ARM-Compiler Arm Compiler 5.06 update 7 (Build 960) which is not available Please install the ARM Compiler.无论是哪种形态核心含义就一句话这个工程文件里明确写了“我要用ARM Compiler 5”但你当前安装的Keil环境里没有这个东西。1.2 新风向MDK 5.37开始AC5不再是标配很多刚入坑的朋友不理解为什么我明明装了Keil却提示编译器缺失因为从MDK 5.37版本开始ARM官方把ARM Compiler 6简称AC6设为了默认编译器ARM Compiler 5简称AC5不再随安装包自动安装。如果你在安装过程中没有手动勾选对应组件或者你用的安装包本来就是5.37之后的版本那你的Keil里就只会有AC6没有AC5。更早之前的MDK版本比如5.30、5.32、5.36安装包会同时带上AC5和AC6。这也是为什么很多老开发者的电脑上从未遇到过这个报错——他们的Keil是几年前的版本AC5一直在只是他们没意识到而已。1.3 AC5和AC6到底是什么关系AC5和AC6是两款完全不同的编译器不是同一个东西的5.0和6.0版本。AC5使用的是ARM自家的armcc编译器技术编译器二进制文件也叫armcc.exe。它在MDK里的默认安装路径是C:\Keil_v5\ARM\ARMCC\bin\armcc.exeAC6采用的是Clang前端加LLVM后端的开源工具链编译器二进制文件名是armclang.exe默认路径是C:\Keil_v5\ARM\ARMCLANG\bin\armclang.exe这两者在命令行参数、编译语法、优化规则、内联汇编写法上都有差异。老工程在创建时指定的编译器和当前环境安装的编译器对不上就必然出现这个报错。1.4 哪些工程最容易踩这个雷以我接触到的案例来看下面几类工程最容易中招几年前的STM32标准外设库工程、老版本HAL库工程使用了一些小芯片厂商SDK的项目尤其国产Cortex-M0/M3/M4的SDK工程中大量使用了AC5特有的关键字例如__irq、__forceinline、__packed直接在工程配置里硬编码了AC5版本的工程文件这些工程在创建时IDE自动写入了类似下面的内容TargetArmCompile Compiler5.06 update 7 (Build 960)/Compiler /TargetArmCompileKeil打开工程时读取到这里就去系统里找对应版本的编译器找不到就直接给你报错。2. 动手装之前先判断你的工程是必须AC5还是可以顺手迁到AC62.1 先看工程文件里的编译器配置遇到报错后很多人的第一反应是赶紧找AC5安装包但我的建议是先花一分钟做判断因为有些工程根本没必要装AC5直接迁移到AC6反而更省事。打开工程目录下的.uvprojx文件用记事本或VS Code都行搜索Compiler关键字你会看到类似这样的片段TargetArmCompile ArmMisc VariousControls MiscControls /MiscControls /VariousControls /ArmMisc Compiler5.06 update 7 (Build 960)/Compiler /TargetArmCompile这里写的是5.06 update 7说明工程指定了AC5。再看工程里的源代码如果能快速翻到几个源文件重点看有没有以下特征使用了GNU风格的__attribute__((...))语法这在AC5和AC6下都能编译使用了ARMCC风格的__asm块例如__asm void delay_us(uint32_t us) { // assembly code }使用了__packed、__irq、__forceinline等ARMCC保留关键字如果代码里大量出现第二种和第三种写法那这工程对AC5的依赖很深建议直接装AC5如果代码基本是标准C没有太多编译器相关特性那完全可以直接切到AC6。2.2 看芯片和SDK的兼容要求芯片型号和SDK版本也决定了你该走哪条路。如果你的芯片是Cortex-M0/M3/M4这些老内核AC5和AC6都支持大概率可以切换。但如果你用的芯片是Cortex-M23、M33、M35P、M55这样的新内核AC5的支持就有限了这些新内核主要在AC6下才能充分发挥能力。更关键的是SDK。有些芯片厂商的SDK虽然官方说支持AC5和AC6但SDK的内部实现里用了大量AC5风格的汇编和底层文件。你在替换编译器时这些文件会直接编译失败。我遇到过一个例子某国产Cortex-M3芯片的SDK它的启动文件.s是用armcc格式写的在AC5下编译完美切成AC6后报了一堆类似unknown asm instruction的错误。这种工程的最终配置在老SDK没有被更新之前只能老实待在AC5。2.3 按工期和风险去选别只贪图省事我给朋友的建议通常是这样的判断优先级场景建议方案理由老SDK 老芯片 大量ARMCC语法直接装AC5迁移成本高得不偿失标准C99代码 HAL库先试AC6迁移成本低新编译器还能提速启动文件/链接脚本有特殊处理装AC5慎重迁移链接脚本差异会导致诡异问题新内核芯片M33/M55等必须AC6AC5对新内核支持有限简单原则如果这个项目只是临时维护、改个小功能那就老实用AC5别去惹那个迁移的浑水如果项目还要长期迭代、后续要加很多功能那就评估一下迁移到AC6的成本值得的话尽早迁。3. 安装AC5的三条可行路径官方补装、独立安装包、旧环境拷贝3.1 路径一重新运行MDK安装包勾选AC5组件这个方法只适用于你手头的MDK安装包版本在5.37或更早。操作方式很简单找到你当初安装MDK时用的安装包或者重新下载一个5.37版本的安装包双击运行选择“Modify / Update”模式跳过License那些常规步骤在组件选择界面找到“ARM Compiler 5.06 update 7”这个选项勾选它继续下一步安装完成后打开Keil报错大概率就消失了这里有个细节如果你用的安装包是5.38或5.39版本组件列表里可能已经没有AC5了这个方法就行不通。5.38开始AC5基本从MDK安装包里被拿掉了官方说法是需要单独下载。3.2 路径二单独下载AC5独立安装包这是目前最主流、也最推荐的方式。在Keil官网的MDK-ARM下载页面上往下翻会有一个“Legacy Products”或者“Previous Releases”区域里面可以找到“Arm Compiler 5.06 update 7 (Build 960)”的独立安装包。下载完成后直接双击运行安装界面会提示你选择安装路径。请注意这里的关键操作是让AC5的安装路径和你的MDK安装路径保持一致。比如你的MDK装在D:\Keil_v5那AC5就应该装到D:\Keil_v5\ARM\ARMCC。安装程序一般会自动识别MDK的安装路径但如果你当初选择了非默认路径安装程序可能检测不到需要手动指定。安装过程很快AC5本身也就一百多MB。装完后打开Keil在工程配置里切一下编译器就能用了。3.3 路径三从旧环境拷贝ARMCC目录应急方案如果你手头有另一台电脑装了老版本MDK5.36及更早那么最快的方案是把那台电脑上Keil安装目录里的ARM\ARMCC文件夹整体拷贝过来放到新电脑Keil安装目录的ARM\ARMCC位置。需要注意几点整个ARMCC目录必须完整复制不能只拷bin目录新老Keil的安装路径不要求完全一致但建议保持一致的目录结构比如都是D:\Keil_v5\ARM\ARMCC拷贝完成后打开Keil在Options for Target里切换到AC5看能否正常识别这个方法在网络不好、官网下载极慢的时候特别管用。我自己有一次在客户现场就靠这个办法救急客户新电脑上Keil死活下不下来AC5我从自己笔记本上直接拷了过去省了一个下午的时间。3.4 安装过程中的一个隐性坑管理员权限无论哪种安装方式都建议右键“以管理员身份运行”。AC5安装程序会在MDK安装目录下写入文件同时需要修改部分注册表信息。如果权限不足有时候安装程序会报错但更坑的是有时候它不报错只是静默安装到了错误的虚拟化路径比如C:\Users\xxx\AppData\Local\VirtualStore\Keil_v5Keil自然识别不到。装完后你可以检查一下Keil安装目录下ARM文件夹里有没有自动生成一个ARMCC子目录。如果装有但目录是空的基本就是权限问题重新以管理员身份装一遍一般能解决。4. 安装之后的硬配置让Keil正确识别并通过AC5编译4.1 安装成功后先验证编译器是否被识别AC5装完别急着双击工程编译先确认Keil是否真的识别到了这个编译器。操作如下打开Keil MDK点击菜单栏“Project” - “Manage” - “Project Items”在弹出的窗口里切到“Folders/Extensions”选项卡往下找“ARM Compiler”相关区域看列表里有没有出现“5.06 update 7”或类似条目如果你看到版本号出现了说明Keil已经找到AC5。另一种快速验证方式打开任意一个工程进入Options for TargetAltF7切到Target选项卡在“ARM Compiler”下拉框里点开看有没有5.06 update 7。4.2 在工程设置里切换编译器编译器已经识别到了接下来要让出问题的工程切到AC5打开报错的工程按AltF7打开Options for Target切到“Target”选项卡找到“ARM Compiler”下拉框选择你刚安装的“5.06 update 7 (Build 960)”点击OK保存然后点击Rebuild重新编译按钮正常情况下就能通过。有些工程可能不只是编译器版本的问题切换之后还会暴露其他错误比如头文件路径丢失、宏定义不完整等。这类问题属于工程配置范围和AC5缺失本身的关联不大需要逐个排查编译错误信息。4.3 手动指定AC5路径的两种方法如果AC5明明装了但下拉框里死活看不到可以手动指定编译器的安装路径。方法一在Options for Target - Target选项卡 - ARM Compiler下拉框右侧点击“...”按钮弹出路径选择对话框直接指向AC5的bin目录例如D:\Keil_v5\ARM\ARMCC\bin选择后Keil会读取这个路径下的armcc.exe来编译。方法二改环境变量。在系统环境变量里新建一个ARMCC5变量值指向D:\Keil_v5\ARM\ARMCC但这个方法需要重启Keil才生效而且不一定完全可靠我更推荐用方法一直接选路径简单粗暴、当场生效。4.4 编译过程中的常见问题补充切换编译器后如果遇到报错先不要慌有几个高频问题编译报错提示找不到某个头文件检查C/C选项卡里的Include Paths路径是否还正确。报错说某个宏未定义检查C/C选项卡里的Define内容老工程常常依赖一些没有被自动迁移的宏。报错说链接脚本找不到看一下Linker选项卡里是否指定了.sct文件AC5和AC6默认的链接脚本格式不同AC6用的.sct有时要手动重新指定一下。工具链切换这种事很多时候不是装个编译器就完事耐心看编译输出逐行解决反而不容易翻车。5. AC5与AC6在工程层面的隐性差异说不定你被“强制迁移”反而因祸得福5.1 先把差异摊开讲不是简单换个版本号很多人以为AC5和AC6就是版本高低的关系实际是完全不同的编译工具链。AC5基于ARM自家多年的编译器技术armcc这个名字用了十几年AC6则基于Clang/LLVM是开源生态里成长起来的。这句话落到操作层面意味着两件事第一同一个C文件在AC5和AC6下编译出来的机器码可能有明显差异尤其涉及优化等级时。第二你写的代码如果依赖了编译器的特定行为比如未定义行为的执行顺序、位的溢出处理方式等在AC6下可能会表现出不同的结果。有朋友遇到过同样的代码AC5下编译正常AC6下编译直接硬件异常。排查下来是一段利用整数溢出做校验的代码AC5和AC6优化后的行为不同导致结果对不上。5.2 语法层面的典型差异清单我整理了一份高频差异方便你做迁移评估时快速对照语法/用法AC5armccAC6armclang内联汇编__asm { MOV R0, #0 }__asm volatile(mov r0, #0)结构体紧凑打包__packed struct__attribute__((packed))强制内联__forceinline__attribute__((always_inline))中断关键字__irq__attribute__((interrupt(IRQ)))字节序转换__REV/__REV16不在默认头文件中可能需要包含cmsis_compiler.h饱和运算__SSAT/__USAT同上需要包含CMSIS头文件如果老工程大量使用了左侧这些写法直接迁移到AC6肯定要改不少代码。但如果只是零星几处改装起来也快。5.3 优化差异带来的实际影响AC6基于LLVM开O2后的优化能力比AC5强不少编译速度也快。我实测一个基于STM32F103的中型项目AC5编译大概70秒AC6只需要20秒左右。代码体积方面AC6通常也会略小一些。但优化强就意味着它更大胆地利用未定义行为进行优化。一份正常代码在AC5下运行没问题换到AC6开O2后却出现随机死机、变量被“优化”掉之类的现象这种情况并不罕见。如果你决定迁移建议先在低优化等级如O0或O1下验证功能再逐步提升优化等级。5.4 启动文件和链接脚本的坑这可能是很多人迁移时最痛的一环。老工程的启动文件如果是从厂商老SDK里拷的格式基本都是armcc风格的汇编。AC6对汇编的支持是GNU风格直接把armcc风格汇编文件扔给AC6去编译大概率报错。解决办法一般是去芯片厂商官网下载新版SDK里配套的AC6版本启动文件或者用CMSIS提供的通用启动文件。链接脚本也一样Keil里AC5和AC6使用的分散加载文件.sct格式差异很大通常会在Linker选项卡里重新生成并手动编辑一次。这些都是实打实的工作量。所以我才在前面强调如果不是长期维护的项目不要轻易迁移。5.5 顺势而为新工程优先用AC6对于新工程我的态度很明确直接选AC6别再用AC5写新代码了。理由就两点一是AC6是持续维护的新内核新指令集支持都在AC6这边AC5已经进入维护末期新芯片的SDK逐步放弃AC5。二是AC6对现代C标准的支持更好C99、C11、部分C特性都能用代码写起来更顺手。如果有人告诉我他新项目还在用AC5我第一反应就是他吃老本习惯了或者被老坑折磨怕了。6. 实测中的三个经典踩坑案例与完整排查链路6.1 坑一装了AC5但Keil下拉列表里看不到现象AC5独立安装包正常装完路径也对着但打开Options for TargetARM Compiler下拉框里只有AC6没有AC5。这个坑我在好几台电脑上见过反复排查后归纳出两个最常见原因。第一个是Keil版本过老。某些MDK版本在AC5没有安装在预期路径时自动扫描逻辑不完善。解决办法是手动指定路径具体操作见4.3节。第二个是安装路径被重定向。Windows的用户账户控制可能导致安装程序把文件写到了虚拟存储目录。排查方法先看C:\Keil_v5\ARM或你的安装目录下有没有ARMCC文件夹再看文件夹里有没有armcc.exe。如果文件在但Keil不认试着重启一次Keil或者重启电脑。如果以上都不行最后一个绝招是找到Keil安装目录下的TOOLS.INI文件打开看[ARM]段里面会有一行类似PATHD:\Keil_v5\ARM\确认这个路径指向的是你的MDK安装根目录且与AC5实际安装位置一致。6.2 坑二切换AC5后依然报编译器缺失现象AC5能看到了也切换到AC5了但编译时依然提示找不到ARM Compiler 5。这个问题的关键往往在工程文件里。有些工程在创建时.uvprojx文件里不仅写了编译器版本还写了编译器的具体安装路径格式类似TargetArmCompile TargetArmCompilePathD:\MyTools\Keil\ARM\ARMCC/TargetArmCompilePath /TargetArmCompile如果这个路径与当前电脑上的实际路径不一致即使系统里装了AC5工程依然会拿着这个旧路径去找编译器结果自然是找不到。解决办法有两种第一种用文本编辑器打开.uvprojx把TargetArmCompilePath改成你电脑上AC5的实际路径保存后重新打开工程。第二种直接把工程里的这个字段删掉让Keil自己按默认逻辑去搜索编译器。这个方法更省事删了之后Keil会自动找默认路径下的ARMCC。需要注意修改.uvprojx之前最好先关闭Keil避免Keil退出时把你改的内容覆盖回去。改完先备份一个原文件防止改错。6.3 坑三编译通过但烧录失败现象AC5装好工程编译一次通过程序也能生成hex/bin文件但用ST-Link或J-Link下载时失败Keil提示类似Flash Download failed或Cannot access target的错误。这个现象和编译器缺失是两码事但确实有很多人把这两个问题串在一起。一般来说烧录失败时先排查三处第一处调试器配置。Options for Target - Debug选项卡确认当前选的是ST-Link、J-Link还是其他下载器点右侧Settings看能不能识别到设备。第二处Flash Download算法。在同样的Settings窗口里切到Flash Download选项卡确认Programming Algorithm列表里有对应芯片的算法文件。换过芯片型号的人最容易漏这一步。第三处芯片供电和复位电路。连接不稳、供电不足、复位电路异常都会导致烧录失败。这类问题在旧笔记本USB口供电不足的情况下非常常见。如果以上都没问题最后再看一下工程里Target选项卡的Xtal频率设置。有些主板对下载时序比较敏感外部时钟频率填错可能导致下载时同步不上。Xtal变灰、无法修改的情况通常和芯片型号选择有关系确认器件型号选对即可。6.4 一个容易忽略的收尾操作清理和缓存编译通过后如果发现程序行为异常先右键点击工程名选择“Rebuild all target files”或者手动Delete掉之前AC6编译时留下的所有中间文件。AC5和AC6的编译产物混在一起可能导致链接时使用到旧的中间文件引发一些奇怪问题。最稳妥的做法是在工程目录下手动删除Objects和Listings文件夹里的内容然后Rebuild。这一步虽然简单但经常能“神奇地”解决很多切换编译器后的诡异现象。7. 收尾的经验清单换完编译器后的常规验证项7.1 编译无错是第一步后续验证更重要很多朋友以为编译过了就万事大吉其实编译通过只说明代码语法和配置层面没问题运行行为对不对、性能有没有变化、功耗有没有异常都是需要重新验证的。我自己的习惯是换完编译器后按下面这个清单逐项过一遍验证项验证方式关注点烧录正常ST-Link/J-Link下载下载过程无错误校验通过时钟与启动调试器连接后读取SysTick外设时钟主频配置是否正常没有进入HardFault外设功能逐个模块跑一遍功能测试串口、ADC、PWM、定时器等行为一致内存占用看Build Output中的RAM使用量是否超出芯片RAM是否有栈溢出隐患相对编译速度记录完整编译耗时AC6通常比AC5快感受一下差异代码体积对比AC5和AC6生成的hex/bin大小优化等级不同可能体积不同长期稳定性持续运行或压力测试确认没有优化导致的偶发问题7.2 从这次问题里总结出的三个习惯第一个习惯不管从谁手里接手工程先看.uvprojx文件里的编译器版本和路径再决定要不要打开编译。这一步能避开很多莫名其妙的报错。第二个习惯新装Keil时直接在安装组件里勾上AC5。即使你现在用不到保不齐哪天打开一个老工程有AC5在就不慌。MDK组件选择界面加了这一项也不影响什么顶多占一百多MB磁盘。第三个习惯定期清理工程里的中间文件。很多“编译不过”“烧录失败”问题其实都是旧中间文件在捣乱。干净目录重新编译往往一通百通。7.3 根据我的实际经验给你一个最终建议如果你正在为AC5缺失头疼我建议按这样的优先级处理先用旧环境拷贝或独立安装包把AC5装上让手头的工程先跑起来这是止血跑起来之后再抽时间评估工程能不能迁移到AC6这是根治如果工程短期不动那就维持AC5等下次有大改版时再统一迁移。嵌入式开发里工具链问题永远不是最有技术含量的问题但永远是最耽误时间的问题。Compiler Version 5缺失这个坑本质上就是工具链生态在切换新老架构时留下的过渡阵痛你我都躲不开不如花半小时把它彻底弄清楚、处理好后面能省出大把时间做正经的开发和调试。
返回列表