简介:面向ARM架构嵌入式开发者提供的ARM Compiler 5.06(960) Windows安装包,需配合Keil MDK使用,核心作用是把C源码高效编译为32位ARM处理器机器码,解决本地工具链搭建与老旧工程兼容问题。压缩包共3个文件,约80.52MB,含msi安装主程序、exe引导启动文件和一份html版发布说明;安装程序负责在Windows x86平台完成部署,html文档记录版本960的更新内容、改进与已知问题,便于读者判断兼容性、提前规避踩坑。armcc通过Plum Hall C Validation Suite验证,对ANSI C支持严格,并提供代码大小与运行速度优化选项,支持ARM、Thumb、Thumb-2多种指令子集,适合资源受限的MCU项目。借助Keil图形化工程管理与调试环境,可完成编辑、编译、链接到JTAG/SWD下载调试的完整流程。已有3607人学习下载,适合从入门到进阶的嵌入式开发者搭建稳定可用的编译环境。
1. 装完 Keil 才发现没有 AC5:先把这个 MSI 备好
前段时间接手一个 Cortex-M3 的老工程,接手的环境里装的是较新的 MDK,打开工程点开 Options for Target,Target 页的 ARM Compiler 下拉框里只有 version 6 一条。编译一下,启动文件、厂商外设库、链接脚本全线报错,改了半天才发现问题不在代码——这颗芯片的 SDK 和几个第三方静态库,全是当年用 armcc 5.06 编出来的。ARMCC 5.06 这套编译器就是 ARM Compiler 5.06 update 6,构建号 b960,MDK 5.37 之后不再随安装包分发,必须单独拿ARMCompiler_506_Windows_x86_b960.msi装。AC6 换了 LLVM 后端,源码级不兼容的地方一大片,老工程直接迁过去往往比装回 AC5 更费时间。这篇记录的就是这套装法:装哪、怎么装、怎么挂进 Keil、装坏了怎么救。
2. 版本对不清就别动手:AC5、MDK 与 b960 的对应关系
动手前,先要把“我要的到底是哪个东西”确定下来。这里涉及三个层面:编译器版本、构建号、宿主 IDE 版本。只要在这个问题上判断错一次,后面所有步骤都会白做:装完发现进不了 Keil、或者进了 Keil 但版本不对,这种情况很常见。
2.1 拆开文件名:5.06 是主版本,960 是构建号
ARMCompiler_506_Windows_x86_b960.msi这个名字里塞了三条信息。506是 ARM Compiler 5.06 的主版本号;x86表示这是一个 32 位安装包,在 64 位系统上照样能装,只是默认落在Program Files (x86)下;b960是构建号,对应 update 6。所以口头说的“AC5”“ARMCC 5.06”“ARM Compiler 5.06 update 6 (build 960)”,指的都是同一套东西。
麻烦的地方在于,Keil 的 Target 下拉框里只显示version 5这种大版本,不显示构建号。也就是说,你没法从界面上判断当前挂的是不是 960。要确认是不是 960,只有两条路:一条是在命令行敲armcc --vsn,看它打印的 Component 行;另一条是打开编译产物里的 map 文件,看链接器版本行。这两条后面都会用到。
另一个容易混淆的点是 MDK 自带与独立安装的关系。MDK 5.36 及更早的版本,安装包里自带一份 AC5,位置在C:\Keil_v5\ARM\ARMCC;从 5.37 开始这份被拿掉了,Target 页只剩 AC6。所以如果你的机器是新装的 MDK,别在Keil_v5\ARM下面找,那里不会有。
| MDK 版本 | 是否自带 AC5 | 你需要做的 |
|---|---|---|
| 5.36 及更早 | 自带,通常在Keil_v5\ARM\ARMCC | 先跑armcc --vsn,build 不是 960 再考虑补装 |
| 5.37 及以后 | 不带,只有 AC6 | 必须装这个 MSI,并在 uVision 里手动注册路径 |
| 只做命令行构建 | 与 MDK 无关 | 只装 MSI,把bin加进 PATH 即可 |
| AC5、AC6 工程并存 | 视情况 | 两套编译器分目录存放,靠工程里的编译器选择区分 |
2.2 装前检查:旧 ARMCC 目录、TOOLS.INI 和权限
装之前有三件事要先做,都是出过一次问题之后才养成习惯的。第一是看机器上有没有旧的 AC5 目录,有的话先记下版本,避免装完两个版本混着用;第二是备份TOOLS.INI,uVision 把编译器路径记在这个文件里,改坏了要么启动报错、要么所有工程都找不到编译器;第三是确认自己有管理员权限,MSI 默认往Program Files (x86)写并登记注册表,权限不够会直接以 1603 之类的错误码退出。
# 1) 看 Keil 安装目录下现有的编译器目录有哪些 Get-ChildItem "C:\Keil_v5\ARM" -Directory -ErrorAction SilentlyContinue # 2) 如果自带 AC5 存在,先记下它当前是哪个 build & "C:\Keil_v5\ARM\ARMCC\bin\armcc.exe" --vsn # 3) 备份 TOOLS.INI,改坏了能原样还原 Copy-Item "C:\Keil_v5\TOOLS.INI" "C:\Keil_v5\TOOLS.INI.bak" -Force第一行的作用是确认有没有“自带的那份”,输出里出现ARMCC就说明是老版本 MDK;第二行只有在前一步找到了目录时才有意义,--vsn是 armcc 查版本的固定参数,选项卡里看不到的构建号全靠它。第三行的备份是应急措施,TOOLS.INI是个纯文本文件,uVision 会在你添加自定义编译器时往里写路径,手改或者写错一个引号,整个 IDE 的编译器列表就乱了。备份文件放同目录、加.bak后缀就行,还原时直接覆盖回去。
2.3 安装路径怎么定:别带空格,更别带中文
MSI 默认装到C:\Program Files (x86)\ARM\ARM_Compiler_5.06u6,这个路径本身带空格和括号。大多数情况下它能正常工作,因为 Keil 内部调用时会自己加引号;但一旦你把工程放进带空格或中文的目录,再配合命令行脚本构建,就会开始出现一些难以理解的报错。我一般会把工具链装到一个短路径下,比如D:\Toolchain\ARMCC506,工程目录也保持全英文、无空格。
这不是过度谨慎。AC5 的构建链路里,armcc 负责编译,armlink 负责链接,fromelf 负责把 axf 转 bin,三个进程之间靠命令行参数传递文件路径,中间任何一层对空格的处理不一致,报出来的错误都不是“路径有问题”,而是cannot open source input file这类看起来像头文件缺失的提示。第一次遇到这种提示时,我花了很久去查 include 路径,最后发现是输出路径里的空格导致的。这也是“后悔药”要提前备好的原因。
3. 安装 ARMCC 5.06(960):图形安装、静默安装与便携解包
真正点安装只要几分钟,麻烦的是安装前后的准备和检查。这一章把三种装法都写清楚:图形界面装一台机器、静默参数批量装多台、管理安装解包成绿色工具链。你可以根据手上是单机还是机房环境选择。
3.1 图形化安装:一路下一步,但两处要看清楚
双击 MSI,前面几步都是常规的许可协议和组件确认,中间会有一个安装路径页,默认就是C:\Program Files (x86)\ARM\ARM_Compiler_5.06u6。如果按 2.3 的建议改路径,就在这一页改,改完记下来,后面挂进 Keil 要用。最后一页点 Install,等进度条走完。
装完之后先看目录结构,确认文件齐全。AC5 的安装目录是固定布局,缺了任何一个子目录都说明安装不完整:
| 路径 | 内容 |
|---|---|
bin\armcc.exe | C/C++ 编译器驱动,也是最常用来查版本的可执行文件 |
bin\armasm.exe | 汇编器,启动文件.s走它 |
bin\armlink.exe | 链接器,输出 axf 和 map |
bin\fromelf.exe | 镜像转换,axf 转 bin、hex、反汇编 |
bin\armar.exe | 静态库打包 |
include\ | C 库头文件,stdio.h、string.h这些 |
lib\ | 运行时库,--cpu不同会挑不同的.a |
bin目录是整个工具链的关键入口,后面无论是 Keil 里注册路径还是命令行加 PATH,指的都是它,不是它的上一层,也不是某个 exe 文件。
3.2 静默安装与解包:msiexec 的几种用法
要给多台机器装,或者写进部署脚本,就得用 msiexec 的静默参数。最常用的一条是/qn,全程无界面;配合/norestart防止安装完自动重启打断别的任务;再加/l*v把详细日志写出来,出问题时日志是唯一的线索。MSI 的报错界面经常只给一个错误码,真正的失败原因都在日志里。
# 静默安装:无界面、不重启、输出详细日志 msiexec /i "D:\pkg\ARMCompiler_506_Windows_x86_b960.msi" /qn /norestart /l*v "D:\pkg\ac5_install.log" # 安装完成后立刻回看日志末尾,有 1603 之类的错误码就在这里 Get-Content "D:\pkg\ac5_install.log" -Tail 40/i表示安装,后面跟 MSI 的完整路径,路径有空格时引号不能省。/qn是完全没有用户界面,适合脚本;如果这是你第一次装、想看着它走完,/qb会显示一个基本的进度条,比/qn好排查。/l*v是日志级别,v表示最详细,日志会包含每个组件、每个目录的写入动作。
想改安装目录就在/qn后面加属性赋值,比如INSTALLDIR="D:\Toolchain\ARMCC506"。但不同厂商的 MSI 用的目录属性名不一样,常见的有INSTALLDIR、APPDIR、TARGETDIR,写错了不会报错、只会被忽略然后照默认路径装。稳妥的做法是用 Orca 这类工具打开 MSI,看 Property 表和 Directory 表里到底是哪个属性名,再照着写。
还有一种做法是管理安装,也叫解包。它不执行真正的安装流程,只是把 MSI 里的文件铺到一个目录下:
# 管理安装:只解包,不写注册表,得到一份可直接拷贝的工具链 msiexec /a "D:\pkg\ARMCompiler_506_Windows_x86_b960.msi" /qb TARGETDIR=D:\Toolchain\ARMCC506/a就是管理安装开关,TARGETDIR指定解包落点。解出来的目录结构和正常安装完全一致,bin、include、lib都在。这种做法的好处是便携:拷到没有安装权限的机器上,Keil 里照样能把编译器路径指过去;坏处是注册表没写,某些依赖注册表查询的工具认不到它。做 CI 构建机或者临时验证环境时,我更倾向用解包,不污染系统。
3.3 装完第一件事:用 armcc --vsn 对版本
不管用哪种方式装的,装完都别急着开 Keil。先直接在命令行敲一次版本查询,确认落地的确实是 b960 这个构建。
# 直接调绝对路径,避免 PATH 里还有别的 armcc 干扰 & "C:\Program Files (x86)\ARM\ARM_Compiler_5.06u6\bin\armcc.exe" --vsn期望看到的输出大致是这么三行:
Product: ARM Compiler 5.06 Component: ARM Compiler 5.06 update 6 (build 960) Tool: armcc看的就是第二行的update 6 (build 960)。如果这里显示的是update 5或者更早的构建号,说明你调用的是机器上另一个 armcc,而不是刚装的这个——这在之前装过 MDK 自带 AC5 的机器上很常见,因为 PATH 里可能已经有旧路径。用绝对路径调用就是为了排除这种干扰。
这一步看起来多余,但它能把后面两类问题提前挡掉:一类是安装包本身没装完整,另一类是系统里存在多个 armcc 互相抢占。如果在这一步就发现版本不对,后面的 Keil 配置全都不用做了。
3.4 PATH 怎么加:先临时验证,再持久化
命令行构建、脚本构建都要求armcc能被直接找到,所以要把它加进 PATH。但加 PATH 这件事本身也有风险:setx在旧版本 Windows 上对超过 1024 字符的 PATH 会截断,一旦截断,系统里其他工具的命令就全找不到了。
# 第一步:只在当前会话里临时加,先确认能用 $env:Path = "D:\Toolchain\ARMCC506\bin;" + $env:Path armcc --vsn # 第二步:确认没问题后,先把当前用户 PATH 导出备份一份 [Environment]::GetEnvironmentVariable("Path", "User") | Out-File D:\pkg\path_user_bak.txt # 第三步:追加而不是覆盖,注意保留原有内容 $old = [Environment]::GetEnvironmentVariable("Path", "User") [Environment]::SetEnvironmentVariable("Path", "D:\Toolchain\ARMCC506\bin;" + $old, "User")第一步改的是进程级环境变量,关掉窗口就失效,适合做验证。第二步导出的是用户级 PATH,出事能照着文本还原。第三步用User作用域而不是Machine,避免影响整机其他账户,也避开了管理员权限要求。
提示:不要用
setx PATH "%PATH%;新路径"这种写法。它会把系统 PATH 和用户 PATH 合并后写回用户变量,长期下来 PATH 越来越长,迟早撞上长度限制。
4. 把 AC5 接进 Keil:编译器路径、Target 参数与命令行三件套
MSI 装完只是把文件放到了磁盘上,Keil 并不知道它的存在。这一章做两件事:让 uVision 认识这份编译器,以及让工程和命令行都用对参数。前者是界面操作,后者是参数取舍,两边都要对,构建结果才可控。
4.1 在 Folders/Extensions 里注册自定义编译器路径
新版 uVision 允许注册多个编译器版本,入口在项目管理对话框里。步骤是固定的:打开 uVision,菜单Project → Manage → Project Items,切到Folders/Extensions页签,下半部分有一个 ARM Compiler 区域,下拉里除了已有的版本,还有一条类似Add another ARM Compiler Version to List...的选项。选中它,弹出目录选择框,把路径指到bin目录。
这里的路径精度是关键:要指到...\ARM_Compiler_5.06u6\bin,不能指到上一层...\ARM_Compiler_5.06u6,也不能指到bin\armcc.exe这个文件本身。指错了不会立刻报错,只是 Target 页的下拉里仍然看不到 version 5,很容易让人以为安装失败了。
注册成功后,uVision 会把这条路径写进安装根目录的TOOLS.INI。文件里大致是这样一段结构(示意,实际内容以工具自己写入的为准):
[UV2] ORGANIZATION="..." NAME="..." EMAIL="..." [ARM] PATH="D:\Toolchain\ARMCC506\bin"[ARM]段的PATH就是编译器入口。这个文件不要手改,尤其是不要手动往里塞多条路径去“试试看”,写乱了 uVision 可能直接找不到任何编译器。真要改,先按 2.2 备份。
4.2 Target 选项与 C/C++ 参数:从 AC6 切回 AC5 要清干净
路径注册好之后,回到Options for Target → Target页,ARM Compiler 下拉里应该能看到 version 5 了,选它。然后重点检查 C/C++ 页,这里是从 AC6 工程切回 AC5 时最容易出错的地方。
AC6 是 armclang,走的是一套 GNU 风格的选项;AC5 是 armcc,只认自己那套。如果你把 AC6 工程的 Misc Controls 原样留着,里面会有-fno-common、-Wno-...、-std=gnu11这类参数,AC5 一个都不认,编译第一步就报Error: C3900U: Unrecognized option。正确做法是把 Misc Controls 清空,再按需一条条加回去。
| 参数 | 作用 | 常用写法 | 注意 |
|---|---|---|---|
--cpu | 指定目标内核 | --cpu=Cortex-M3 | 编译、汇编、链接三处必须一致 |
--c99 | 打开 C99 支持 | --c99 | AC5 默认偏 C90,老代码不开会报变量声明位置错 |
-O0/-O2 | 优化等级 | 调试-O0,发布-O2 | -O3在部分老库上会触发内联问题 |
-g | 生成调试信息 | 配合-O0 | 只开-g不开-O0,单步会跳 |
--apcs=interwork | ARM/Thumb 互调 | 一般默认就带 | 手工改链接脚本时留意 |
--split_sections | 每个函数单独成段 | 配合链接期--remove | 明显减小 Flash 占用 |
--diag_suppress | 屏蔽指定编号告警 | 如--diag_suppress=1295 | 按编号屏蔽,别一把全关 |
除参数之外还有两处常见设置:Output 页勾上Create HEX File,方便烧录;Linker 页如果用的是 Target 对话框里的内存布局,就保持Use Memory Layout from Target Dialog,如果工程自带.sct分发文件,就切到手动指定并填对路径。
4.3 命令行三件套:armcc、armlink、fromelf
Keil 图形界面背后调的就是这三条命令,把它们的参数搞明白,出问题时才能自己复现和定位。顺序也是固定的:先编译成.o,再链接成.axf,最后转成.bin或者.hex。
# 编译:只编译不链接,输出目标文件 armcc --cpu=Cortex-M3 -c --c99 -O2 -g -I ./inc -D BOARD_V1 -o build/main.o src/main.c # 链接:指定分散加载文件,打印尺寸信息并生成 map armlink --cpu=Cortex-M3 build/main.o build/startup.o --scatter=app.sct --info=sizes --map --output=build/app.axf # 转换:从 axf 里导出纯二进制镜像 fromelf --bin --output=build/app.bin build/app.axf-c是只编译不链接,缺了它 armcc 会尝试自己完成链接。-I后面跟头文件搜索目录,可以写多次;-D是宏定义,等价于源码里#define BOARD_V1。-o指定输出文件,目录不存在时不会自动创建,所以build目录要先建好。
armlink 这一条里,--scatter指定分散加载文件,决定代码和数据放在哪块 Flash、哪块 RAM;--info=sizes会在链接结束时打印各段大小,这是判断镜像有没有超容量最直接的方式;--map生成 map 文件,后面验证版本要靠它。--cpu必须和编译时写的一致,不一致会出现“同一份代码编出来的东西链接不上”这种非常难查的问题。
fromelf 是镜像转换工具,--bin表示输出裸二进制,--output指定落点。如果是要给烧录工具用的 hex,就把--bin换成--i32或对应格式。
4.4 AC5 与 AC6 参数对照:迁移时对着这张表改
手上如果有两套工程,一套 AC5 一套 AC6,来回切的时候对照这张表改,比照着报错一条条试要快得多。
| 功能 | AC5(armcc) | AC6(armclang) |
|---|---|---|
| 编译器驱动 | armcc | armclang |
| 指定内核 | --cpu=Cortex-M4 | --target=arm-arm-none-eabi -mcpu=cortex-m4 |
| C 标准 | --c99 | -std=c99 |
| 优化 | -O2 | -O2 |
| 宏定义 | -D | -D |
| 头文件路径 | -I | -I |
| 弱符号 | __weak | __attribute__((weak)) |
| 字节对齐打包 | __packed、__align(n) | __attribute__((packed))、__attribute__((aligned(n))) |
| 链接器 | armlink | armlink,参数大体通用 |
| 镜像转换 | fromelf | fromelf,参数大体通用 |
表里最需要注意的是关键字那一栏。AC5 提供了一批以双下划线开头的扩展关键字,__weak、__packed、__align、__irq这些,写起来干净,但只有 armcc 认。AC6 走 GNU 的__attribute__语法,同一份源码在两边切换时必须改。这也是老工程不能"顺手迁到 AC6"的核心原因之一:不是编不过,是要改的源码位置太分散。
5. 排查:AC5 装完之后最常翻车的五件事
下面五条是这套环境里出现频率最高的问题,按“看到什么现象、为什么、怎么解”的顺序记。有些问题看着像安装失败,实际是配置差一层;有些看着像代码问题,实际是版本问题。
5.1 Target 下拉里始终没有 version 5
现象:Options for Target → Target页的 ARM Compiler 下拉里只有 version 6,或者只有一条 default,反复重装 MSI 也没变化。
原因:MDK 5.37 之后本来就不带 AC5,下拉框里的条目来自两个地方——安装包自带,以及用户在Folders/Extensions里手动注册的路径。如果注册时把路径指到了bin的上一层或者armcc.exe文件本身,uVision 校验时找不到编译器入口,就不会把这条加进下拉。
解决:重新走一遍Project → Manage → Project Items → Folders/Extensions,路径精确到bin目录。添加完把 uVision 完全关闭再打开,让它重新读一次TOOLS.INI。如果还不行,打开TOOLS.INI看[ARM]段的PATH有没有被正确写入,没有就还原 2.2 的备份重来。
5.2 链接报 L6050U 代码超限
现象:编译都正常,到链接这一步报Error: L6050U: The code size of this image exceeds the maximum allowed for this version of the linker.
原因:这是评估版 32KB 代码限制的提示,跟 AC5 本身没关系。编译器装得对不对是一回事,能不能产出超过 32KB 的镜像由 Keil 那边的授权状态决定。AC5 单独安装不会改变这个限制。
解决:先确认授权状态是否正常,检查是不是在换机器、重装系统之后授权没跟上。临时验证代码是否真的超标,可以打开-O2并加上--split_sections,链接时配合--remove裁掉未引用段,看尺寸是否刚好卡在边界附近。如果裁完仍然超,那就是工程本身规模问题,不是配置问题。
5.3 cannot open source input file
现象:编译报Error: #5: cannot open source input file "xxx.h": No such file or directory,但你确认过这个文件就在工程目录里。
原因:三种可能——头文件目录没加到Include Paths;加了但路径里带空格没有正确引用;工程从别的机器拷过来,路径是绝对路径,指向了原机器的目录。
解决:在 C/C++ 页的Include Paths里逐条补齐,尽量用相对工程根目录的写法。命令行构建时对应的是-I参数,路径带空格要加引号。另外养成一个习惯:路径里不要出现中文和空格,这一条能挡掉后面一大半难以理解的报错。
5.4 一堆 C3900U 和语法错误
现象:从 AC6 工程切回 AC5 之后,编译一开始就滚出一串Error: C3900U: Unrecognized option,或者源码里报__attribute__相关的语法错误。
原因:AC5 不认 armclang 的选项,也不认 GNU 的__attribute__扩展写法。工程里的 Misc Controls 和源码关键字都是按 AC6 写的,切回 AC5 就全部失效。
解决:把 Misc Controls 清空,再一条条按需要加回 AC5 认的参数;源码里的__attribute__((packed))、__attribute__((weak))、__attribute__((aligned(n)))分别替换成__packed、__weak、__align(n)。替换时注意这类关键字往往出现在启动文件、外设寄存器定义和中断处理函数里,改完要重新编译全部文件,不能只做增量编译。
5.5 装完 Keil 打不开或者所有工程都找不到编译器
现象:打开 uVision 弹窗提示找不到工具链,或者干脆启动即退出;已存在的工程全部报编译器缺失。
原因:TOOLS.INI被写入了一条无效路径,或者安装目录被手动移动过、文件不全。uVision 启动时会读这个文件,路径指向一个不存在的目录就会把整条编译器记录判为失效。
解决:先用 2.2 备份的TOOLS.INI.bak覆盖回去,确认 IDE 能正常启动;然后把 MSI 重新装一遍到确认无误的路径,进目录看bin下armcc.exe、armasm.exe、armlink.exe、fromelf.exe四个文件是否齐全,缺任何一个就重装,不要试图手工补文件。
6. 装完怎么验证:三条命令确认 b960 真的在干活
到这一步,文件装了、路径注册了、参数也配了,但“配了”和“生效了”是两件事。我见过不止一次:Keil 里下拉框显示 version 5,实际调用的却是另一个目录里的旧版 armcc,编出来的东西和预期不一样,查了半天才发现是路径问题。所以每次装完,我都会强制走完下面三条验证,全通过才动真实工程。
第一条,命令行直接查版本:
armcc --vsn期望输出里Component那一行是ARM Compiler 5.06 update 6 (build 960)。如果 PATH 里还有别的 armcc,就先去掉 PATH 再查一次,或者用绝对路径调用,确认版本来源唯一。
第二条,命令行完整走一遍编译和链接:
# 最小验证文件,内容只有一行空的 main echo "int main(void){return 0;}" > hello.c armcc --cpu=Cortex-M3 -c --c99 -O0 -g -o hello.o hello.c armlink --cpu=Cortex-M3 hello.o --info=sizes --map --output=hello.axf第一步验证 armcc 能正常启动并产出目标文件,第二步验证 armlink 能正常链接并打印尺寸。因为没有启动文件和入口,链接期会提示没有入口点的警告,这条在验证阶段可以忽略,重点看它有没有跑完、有没有生成hello.axf和hello.map。
第三条,在 Keil 里
本文还有配套的精品资源,点击获取