现在的嵌入式开发大部分都是ARM处理器了,从MCU级别的M0,M3,M4,M23,M33,到MPU级别的ARM9,ARM11,ARM-A5x,ARM-A7x。开发者很少去注意使用的编译器,一般都是使用的是IDE自带或者开发板(芯片)厂家提供的编译器。等碰到问题百度时候最终才发现很多问题和编译器有关,如果一开始就对编译器有个基本的了解完全可以避免类似问题,下面就系统的介绍一下ARM编译器的选择和使用。
1. ARM处理器的分类
1.1. 按系列分类
- Cortex-M系列(通用微处理器)
包括Cortex-M0、M3、M4,新的M23,M33,以及早期的ARM7TDMI,这类处理器一般不跑操作系统,或者只跑个RTOS
- Cortex-R系列(实时微处理器)
这类处理器可以认为是在Cortex-M的基础上增强了实时性能,用于高安全,高实时的场合,这种处理器说实话我没用过,也没研究过,只在安全PLC的产品中见过。
- Cortex-A系列(带MMU的处理器)
包括Cortex-A5,A7,A9,到现在的A5x,A7x,以及早期的ARM9,ARM11。这类处理器一般跑Linux,安卓之类的带内存管理功能的操作系统,利用这类操作系统的强大功能去实现复杂的应用。
1.2. 按指令集分类
- V4指令集
ARM7TDMI、ARM9TDMI、Intel StrongARM
- V5指令集
ARM926EJ、Intel XScale
- V6指令集
ARM11,M0
- V7指令集
ARM-A系列中的32位,M3,M4,M7
- V8指令集
ARM-A系列中的64位,M23,M33,M55,A系列32位用V8的比较少,但也有。
1.3. 按硬件浮点分类
这种分类有些牵强,但是和编译器有较大关系,几种之间不兼容,所以这里单独列一下。
- 无硬件浮点单元
浮点运算通过软件完成,低端的M0,M3,M23;部分A系列的都没有。对应浮点编译选项为soft。
- 有硬件浮点单元,但是传参数用普通寄存器传
编译器后缀有el的对应这种形式,对应浮点编译选项为softfp,这种形式的产品比较少,后面会详细说明。
- 有硬件浮点单元,传参数也用浮点单元的寄存器传
编译器后缀有hf的对应这种形式,对应浮点编译选项为hard
32位CPU带硬件浮点运算功能的大部分都是这种。
64位CPU都带硬浮点,也是这种。
2. ARM编译器的分类
交叉编译工具链的一般命名规则为:arch [-vendor][-os] [-(gnu)eabi]
arch - 体系架构,如ARM,MIPS
verdor -工具链提供商
os - 目标操作系统
eabi - 嵌入式应用二进制接口
2.1. arm-none-eabi编译器
可以在下面这个网址下载:
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads
这种编译器的名字中没有包含操作系统的信息,所以这种编译器用于编译裸机或者使用RTOS的程序,M0,M3之类的单片机都使用的是这种编译器。
对应的64位为aarch64-none-elf。
2.2. arm-none-linux-eabi编译器
可以在下面这个网址下载:
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads
这种编译器的名字中包含linux,所以这种编译器用于编译linux中的程序,32位编译器一般默认都是软件浮点。
对应的64位为aarch64-none-linux-eabi,64位编译器默认都是硬件浮点。
2.3. arm-linux-androideabi编译器
顾名思义是安卓编译器,64位为aarch64-linux-eabi
3. ARM编译器和ARM架构相关的编译选项
其实各芯片厂家提供的编译器主要作用就是指定了下面这些选项的默认值(当然不仅仅是下面这些选项),使用户使用起来更方便,不需要手动去指定了。
3.1. -mcpu和-march
-mcpu用于指定cpu的类型,例如cortex-a7,cortex-a9,cortex-a53,cortex-a73之类的。
-march用于指定cpu的指令集,例如armv6,armv7。
一般都是直接指定-mcpu,编译器能正确推断出-march的值。
3.2. -mfloat-abi和-mfpu
-mfloat-abi用于指定软浮点还是硬浮点
soft:软浮点
softfp:硬件浮点但是参数传递使用普通寄存器
hard:硬浮点并且参数传递使用硬浮点寄存器
一般armv5的CPU是soft,armv6以上的是hard,softfp的比较少
注意:不同mfloat-abi编译出来的库一般不兼容,所以整个linux系统中所有程序和库的mfloat-abi应该保持一致。
-mfpu用于指定硬浮点的类型,可以是vfp,vfpv3,neon-vfpv4。
一般32位CPU选择vfp或者vfpv3,64位CPU选择neon-vfpv4,或者直接不选择,让编译器根据CPU选择默认值即可。不同mfpu选项应该是能兼容的,这个没测试,印象中是可以的,只要CPU本身有相应的硬件支持就行。
3.3. 通过-print-multi-lib选项,可以查看编译器支持的选项
3.4. 通过readelf -a命令,查看程序和库对应的编译选项
欢迎大家关注我的公*号:embedded_bug