象棋小子 1048272975
GNU是一个自由软件工程项目,目标在于创建一个完全兼容于UNIX的自由软件环境。GNU已经开发出了大部分UNIX系统的程序库和工具,如功能强大的文字编辑器Emacs, GUN开发编译器GCC等。尤其是Linux与其它的GNU软件结合,诞生了GNU下完全自由免费的操作系统。GNU软件功能完善而强大,丝毫不输商业软件,其开源免费的特性也得到了世界各地程序员的积极响应,让GNU软件尤其是Linux得到了相当广泛的应用。笔者此处就搭建Arm交叉编译环境作一个简单的介绍。
代码编译主要分为预处理、编译、汇编、链接这四个步骤,这个流程需要多个开发工具配合使用。例如预处理和编译需要使用gcc工具,gcc产生汇编代码;汇编代码需要使用as工具把汇编指令对照翻译成机器指令;最后通过链接器ld将各个目标文件组装一起,解决符号依赖、库依赖,生成可执行文件。
除此之外,项目开发往往还需要使用其它的工具。例如通过objcopy将某种格式的目标文件转换成另外格式的文件(elf转hex、bin等);用size显示目标文件各个节的大小和目标文件的大小;用ar生成库文件;生成反汇编调试等等。因此,整个开发过程需要的是一套编译工具链。
由于GNU工具链支持众多不同架构、不同厂商、运行不同系统的CPU,为了便于区分,交叉编译工具链有相应的命名规则:arch [-vendor] [-os] [-(gnu)eabi]
arch:体系结构,如ARM、MIPS
vendor:工具链提供商
os:目标操作系统,如linux表用于linux操作系统,none表没有操作系统的裸机
eabi:嵌入式应用二进制接口,如对于ARM架构,ARM公司规范了其调用标准AAPCS
根据对操作系统的支持与否,Arm交叉编译工具链可分为支持和不支持操作系统。
arm-none-eabi:不支持Linux操作系统,通常用于裸机编程,使用面向嵌入式的小型c标准库,如uclibc、newlib等。
arm-linux-gnueabi、arm-none-linux-gnueabi:支持linux操作系统,通常使用glibc。
不管是裸机交叉编译工具链arm-none-eabi还是linux交叉编译工具链arm-linux-gnueabi,其实没有本质的区别,工具链都能编译成相应架构的指令、链接生成可执行代码。只不过arm-none-eabi默认使用的是非linux接口的c库,适合于裸机开发,无法开发基于linux的应用程序。而arm-linux-gnueabi默认使用的是linux接口的c库,适合于linux应用程序开发,而裸机开发不能尝试去链接c库,不然会链接失败,因为没有linux的实现。
通常用c开发,重新实现c库往往不现实,需要交叉编译工具链已实现标准c库的支持。对于arm交叉编译工具链,一般会支持三个最基本的库(静态库为例):libgcc.a、libc.a、libm.a。
其中libgcc.a在编译gcc时产生,提供平台相关的底层运行库,大多数用于目标处理器的算术运算。如对于arm9,不支持硬件除法,硬件浮点,代码中任何除法、浮点相关操作都应该去链接libgcc.a,由libgcc.a提供除法、浮点操作的软件模拟实现。但对于支持硬件除法、硬件浮点的cortex-a架构cpu,无需libgcc.a提供软实现,编译器直接生成除法或浮点指令,处理速度是软实现远远不及的。
libc.a、libm.a为c标准函数库以及数学处理库,任何c编译器均应支持。
用于裸机开发以及用于linux应用开发的Arm交叉编译工具链实质是一样的,只不过采用库的策略差异。理论上只要用裸机开发的交叉编译工具链编译一个基于某个linux内核头的c库(如glibc),那么就可以实现linux应用程序的编程。同样,linux应用开发的交叉编译工具链只要再编译一个基于裸机开发的c库(如newlib),即可实现标准的裸机编程,与windows下mdk、iar等裸机开发无异。
arm交叉工具链支持各个arm架构版本,工具链版本越高,所能支持的arm版本也越高。对于arm7/arm9,支持生成armv4指令集;对于cortex-m,可以支持armv6-m/armv7-m指令集;对于cortex-a,可以支持armv7-a指令集等等。通常对于版本跨度不太的arm交叉编译工具链,无需改动或简单的版本差异改动,就能够很好地实现bootloader、linux内核、linux应用程序、裸机的编译。因此,往往无需绑定使用不同芯片厂商、不同架构cpu、不同应用目标所附带的Arm交叉编译工具,避免多余的交叉编译工具链。
制作arm交叉编译工具链一般有几种方法。
分步编译和安装交叉编译工具链所需要的库和源码。由于各个GNU工具相互之间对版本依赖较大、补丁依赖、命令工具依赖等,一旦编译失败,解决完需再重新编译,如此往复,非常浪费精力以及时间,采用这种方法,只能自寻烦恼。
使用如crosstool-ng脚本可以解决各个GUN工具的版本依赖以及补丁。多次编译后,总能架构成功。但采用通用的GNU源码编译工具,而不是针对arm架构,往往代码优化,性能等不能达到最佳,同时脚本工具所能支持的Arm交叉编译工具链版本往往也不高。采用这种方法,相对吃力不讨好。
显然一些公司、开源组织已经意识到需要单独维护Arm交叉编译工具链了。这些工具链可以直接解压使用(已经是二进制可执行代码),可以基本兼容各个linux发行版,如ubuntu、centos等。这些工具链往往针对arm架构使用了特定的优化,也经过一定的测试,可使用到较高版本的交叉编译工具链。非常省时省事,可以直接采用这种方法构架Arm交叉编译工具链。
GNU 推出的裸机开发Arm交叉编译工具链
https://launchpad.net/gcc-arm-embedded
Linaro(ARM、Samsung、Freescale等联合非营利开源公司)
http://www.linaro.org/
CodeSourcery公司
https://www.mentor.com/embedded-software/codesourcery/
笔者使用CodeSourcery的arm-none-linux-gnueabi交叉编译工具链,工具包为arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2,可以直接开发linux应用程序。
解压arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2,打开etc/profile,增加交叉工具链的环境变量即可。
一般对于linux应用程序arm交叉编译工具链,往往约定用arm-linux-作为linux开发交叉编译工具链的前缀,可以创建arm-linux-工具链的软链接。
同时,也可以使用这个交叉编译工具链编译裸机程序,可以采用约定的arm-none-eabi-作为裸机开发交叉编译工具链的前缀,可以创建arm-none-eabi-工具链的软链接。
创建的链接脚本link.sh如下,在工具链目录下执行即可。
#!/bin/bash
for file in $(ls arm-none-linux-gnueabi*)
do
ln -s $filearm-linux${file#arm-none-linux-gnueabi}
ln -s $file arm-none-eabi${file#arm-none-linux-gnueabi}
done
笔者直接用CodeSourcery已编译好的Arm交叉编译工具链编译newlib,来支持完整的裸机开发。有了完整的c库支持,以及linux下集成开发环境eclipse,可以解决依赖关系,可视化选项设置等,避免写makefile脚本,裸机开发与windows下mdk、iar开发并没有太大的差异。同时,不同版本交叉编译工具链只是简单的编译选项、语法严格等方面的差异,采用这个交叉工具链无需或只需简单地改动即可编译s3c2416以及s5pv210的uboot、linux内核。实现一个交叉编译工具链即可支持裸机、bootloader、linux内核、linux应用程序的开发。