简介:Arm Compiler 5.05 update 1(build 106)是面向嵌入式开发者的经典 ARM 编译器安装包,适用于使用 Keil MDK 进行 ARM 平台工程开发、需要指定旧版编译工具链的中高级开发者,可解决新版编译器兼容性不足或工程需固定 r5p5-01rel1 版本的问题。资源包共 3 个文件,以 msi 安装数据、exe 安装引导程序及 html 说明文档为主,压缩包约 80.56MB,解压后可获得完整安装程序,安装至 Keil 安装路径下的 ARMCC 5.05 目录即可在 Manage Project Items 中注册调用。目前已有 890 人学习下载,说明该版本在存量工程维护中仍有稳定需求。对于需要复现旧项目编译环境、排查编译器版本差异或搭建多版本工具链共存的读者,这份资源提供了可直接落地的安装文件与版本说明,便于快速完成环境配置与工程迁移验证。
1. 装 ARM Compiler 5.05 之前,先把版本号读明白
上周帮一个做嵌入式移植的朋友收拾一台旧开发机,他卡在armcc报错上整整两天,最后发现不是代码问题,而是装的编译器版本和工程里写死的工具链对不上。Arm Compiler 5.05 update 1(build 106)这个版本号看着不起眼,但它是很多老工程、老 SDK、老启动文件默认认的那一档,装错一个小版本,链接阶段就可能冒出莫名其妙的符号错误。这篇笔记按我实际装机的顺序写:先确认环境,再下载解压,然后配环境变量和 license,最后用一段最小工程验证armcc真能出可执行文件。适合手里有老工程要维护、或者第一次接触 ARM 编译工具链的开发者照着走。
2. 环境准备与版本选择:为什么偏偏是 5.05 update 1
2.1 先搞清楚 AC5 和 AC6 的分界
Arm Compiler 5 系列(简称 AC5)和后来的 Arm Compiler 6 是两套完全不同的前端。AC5 基于 ARM 自己的编译器,对老式 ARM 汇编语法、__asm内联、分散加载文件(scatter file)的支持非常成熟;AC6 换成了基于 LLVM 的架构,语法更严格,很多老工程直接迁过去会报一堆错。5.05 update 1(build 106)属于 AC5 后期的一个稳定更新档,常见于一些老版本 IDE 自带的工具链目录里,也是不少芯片厂商 SDK 文档里点名要求的版本。
我一般会先看工程根目录有没有类似toolchain配置、.uvprojx里的编译器路径、或者 Makefile 里写死的CC := armcc。如果工程里出现--c99、--cpu Cortex-M3、--scatter这类参数,基本可以判定是 AC5 的用法。这时候硬上 AC6,最常见的翻车就是--c99不被识别、内联汇编语法报错、启动文件里的AREA段定义解析失败。
2.2 宿主机环境对照
AC5 是 32 位时代的产物,官方安装包多为 Windows 版本,Linux 下一般靠解压后直接调用二进制。下面这张表是我实际验证过的环境组合,供对照:
| 宿主机 | 是否可用 | 说明 |
|---|---|---|
| Windows 7 / 10 64 位 | 可用 | 官方安装包直接装,注意装到无空格、无中文的路径 |
| Windows 11 | 可用 | 需以管理员身份运行安装器,个别机器要关掉安装器的兼容性检查 |
| Linux x86_64 | 可用(解压方式) | 直接调用bin/armcc,需补 32 位运行库 |
| macOS | 不推荐 | 官方无原生支持,老版本靠兼容层,坑多 |
Linux 下补 32 位库是绕不开的一步,常见做法是装libc6:i386、libstdc++6:i386这类包。我遇到过一台机器armcc一跑就报No such file or directory,其实是动态链接器找不到 32 位解释器,file bin/armcc一看是 ELF 32-bit 就明白了。
2.3 版本号里的 build 106 意味着什么
5.05 update 1是主版本加更新包,build 106是具体构建号。同一 update 下不同 build 之间可能有 bug 修复差异,工程里如果锁了 build 号,最好别随意换。判断当前装的是哪一版,最直接的办法是跑:
armcc --vsn输出里会带ARM Compiler 5.05 update 1 (build 106)字样。如果只显示5.05而没有 update 和 build,说明装的是基础版,和工程要求可能对不上。这一步别省,我见过有人装完以为成了,结果--vsn一跑发现是另一个 build,链接行为就是不一样。
3. 下载、解压与目录规划:别把工具链塞进带空格的路径
3.1 安装包获取与校验
AC5 的安装包一般是一个自解压 exe 或者压缩包,文件名里通常带版本号。拿到之后先核对文件大小和来源,别拿到半截包就装。Windows 下双击前,我习惯先看属性里的数字签名或者比对官方给的校验值;Linux 下解压前先unzip -l看一眼目录结构,确认里面有bin/、include/、lib/三件套。
解压或安装的目标路径有两条硬规矩:不能有空格,不能有中文。C:\Program Files\ARM\...这种默认路径看着规整,但老工具链里有些脚本对空格处理不干净,编译到一半路径被截断的玄学问题就是这么来的。我一般统一放到C:\ARM\AC5_05u1或者 Linux 下的/opt/arm/ac5_05u1。
3.2 目录结构说明
装好后核心目录大致是这样:
AC5_05u1/ ├── bin/ # armcc、armasm、armlink、fromelf 等可执行文件 ├── include/ # 标准头文件 ├── lib/ # 运行时库,按 cpu 和浮点选项分目录 ├── sw/ # 示例与部分配置 └── license/ # license 相关文件(视安装方式而定)bin/下最常用的四个命令要记牢:armcc编译 C,armasm汇编,armlink链接,fromelf把 elf 转 bin/hex。lib/下面按armlib、cpplib分,还会按--cpu和浮点 ABI 再分子目录,链接时选错库目录会报找不到__main之类的符号。
3.3 环境变量配置
Windows 下把bin目录加进PATH,Linux 下写进 shell 配置文件。我一般还会额外设一个ARMCC5_HOME指向安装根目录,方便脚本里引用:
# Linux,写入 ~/.bashrc export ARMCC5_HOME=/opt/arm/ac5_05u1 export PATH=$ARMCC5_HOME/bin:$PATH:: Windows,系统环境变量里追加 set ARMCC5_HOME=C:\ARM\AC5_05u1 set PATH=%ARMCC5_HOME%\bin;%PATH%设完开一个新终端验证,别在当前窗口里测,环境变量没刷新导致的“明明配了却不生效”是最常见的假故障。which armcc(Windows 用where armcc)能定位到刚配的路径,才算这一步过了。
提示:如果机器上同时装了 AC5 和 AC6,两个
bin目录都进PATH会互相覆盖。常见做法是只把常用的那个放全局PATH,另一个用绝对路径或独立脚本切换。
4. 配置 license 与编译参数:让 armcc 真正能出活
4.1 license 的两种常见形态
AC5 没有 license 时,armcc能编译但链接会受限,或者直接报 license 错误。常见形态有两种:一种是安装时通过 license 文件激活,文件里带机器绑定信息;另一种是环境变量指向 license 服务或文件。我一般先看安装目录下有没有license相关文件,再确认环境变量:
# 常见做法:指向 license 文件 export ARMLMD_LICENSE_FILE=/opt/arm/license.datWindows 下同理,在系统环境变量里加ARMLMD_LICENSE_FILE。配完跑一次armcc --vsn,如果 license 有问题,这一步通常就会带出提示。别等到编译大工程才发现 license 没生效,那时候报错信息混在一堆编译日志里,排查成本高得多。
4.2 一个最小编译命令拆解
验证工具链是否可用,不用一上来就编整个工程,先拿一个最小 C 文件试:
# 编译一个最简单的 C 文件到目标文件 armcc --cpu Cortex-M3 -c -O1 --c99 main.c -o main.o逐段说明:--cpu Cortex-M3指定目标核,必须和工程一致,选错会生成不兼容的指令;-c表示只编译不链接;-O1是优化等级,调试阶段常用-O0,发布再往上调;--c99打开 C99 支持,老工程里很常见;-o指定输出。这一步能过,说明编译器本体和头文件路径没问题。
接着链接:
# 链接成 elf,指定入口和分散加载文件 armlink main.o --scatter=project.sct --entry=Reset_Handler -o project.elf--scatter指定分散加载文件,决定代码和数据放到哪块存储;--entry指定入口符号,裸机工程一般是复位处理函数。链接报L6218E: Undefined symbol多半是库没带全或者启动文件没参与编译,先查lib/路径和启动文件是否在源文件列表里。
4.3 常用参数取舍表
| 参数 | 作用 | 什么时候用 |
|---|---|---|
--cpu | 指定目标核 | 必填,和芯片手册一致 |
-O0/-O1/-O2 | 优化等级 | 调试用 O0,发布用 O1/O2 |
--c99 | C99 标准 | 老工程常见,AC6 下不认这个写法 |
--scatter | 分散加载 | 裸机、需要精确控制内存布局时 |
--fpu | 浮点单元 | 带 FPU 的核要显式指定,否则软浮点 |
-g | 调试信息 | 需要单步调试时加 |
参数不是越多越好,--fpu和--cpu配错是浮点运算结果异常的常见根源。我一般会先照工程原有配置抄一遍,再逐项确认,而不是自己从头拼参数。
5. 避坑与排查:装 AC5 最容易翻车的几处
5.1 现象:armcc命令找不到
原因通常是PATH没生效或者路径写错。先echo $PATH看有没有目标目录,再确认bin下确实有armcc可执行文件。Windows 下注意分号分隔,Linux 下注意冒号,混用会导致整段PATH失效。
5.2 现象:Linux 下报No such file or directory
前面提过,多半是缺 32 位运行库。file bin/armcc确认是 32 位 ELF 后,装对应的i386库。别被“文件明明存在”迷惑,这个报错指的是解释器缺失,不是文件缺失。
5.3 现象:链接报__main未定义
原因一般是运行时库路径没配对,或者--cpu和库目录不匹配。检查lib/下对应 cpu 的子目录是否存在,链接命令里有没有正确带库搜索路径。另一种可能是启动文件没参与编译,__main由启动代码提供。
5.4 现象:编译通过但程序跑飞
这类问题最费时间。常见原因是分散加载文件里的内存地址和实际芯片不符,或者--fpu选项和硬件不匹配导致浮点指令异常。我一般先用fromelf --text -c project.elf反汇编看入口附近指令,再对照芯片手册确认地址映射。
5.5 现象:同一工程换机器后行为不一致
多半是工具链 build 号不同。两台机器都跑armcc --vsn对比,build 号不一致就统一到工程要求的版本。别小看这个差异,优化器的细微改动足以让依赖未定义行为的代码表现不同。
6. 装完怎么验证:用最小工程跑通一条完整链路
验证不能只看armcc --vsn有输出就收工,那只能证明命令在。真正要确认的是“编译、汇编、链接、格式转换”整条链路都能出活。我一般准备一个三文件的最小工程:一个启动汇编、一个 C 源文件、一个分散加载文件,走一遍完整流程。
先编译汇编和 C:
# 汇编启动文件 armasm --cpu Cortex-M3 startup.s -o startup.o # 编译 C 源 armcc --cpu Cortex-M3 -c -O0 --c99 main.c -o main.o再链接并转格式:
# 链接 armlink startup.o main.o --scatter=project.sct --entry=Reset_Handler -o demo.elf # 转 bin,便于烧录验证 fromelf --bin --output=demo.bin demo.elf四步都无报错,且demo.bin大小合理(不是 0 字节、不是异常巨大),基本可以判定这套 AC5 装好了。接着用fromelf --text -c demo.elf看一眼反汇编,确认入口地址和分散加载文件里写的一致,这一步能提前发现内存布局配错的问题。
下面这张验证清单我每次装完都会过一遍:
| 检查项 | 命令 | 期望结果 |
|---|---|---|
| 版本正确 | armcc --vsn | 显示 5.05 update 1 (build 106) |
| 编译可用 | armcc -c main.c | 生成 .o,无报错 |
| 汇编可用 | armasm startup.s | 生成 .o,无报错 |
| 链接可用 | armlink ... | 生成 .elf,无未定义符号 |
| 格式转换 | fromelf --bin ... | 生成非空 .bin |
| 入口正确 | fromelf --text -c | 入口地址与 sct 一致 |
还有一个小技巧:把上面几条命令写进一个check.sh或check.bat,每次换机器或升级工具链后跑一遍,比手工敲可靠。我吃过一次亏,某台机器上armcc单独跑没问题,但armlink因为库路径没配全一直失败,直到编大工程才暴露,白折腾半天。从那以后我每次装完工具链都强制走一遍这条最小链路,四步全绿才敢往工程上接。希望这套流程能帮到你,少在版本和环境上绕弯路。
本文还有配套的精品资源,点击获取