GNU是一个自由软件工程项目,目标在于创建一个完全兼容于UNIX的自由软件环境。GNU已经开发出了大部分UNIX系统的程序库和工具,如功能强大的文字编辑器Emacs, GUN开发编译器GCC等。尤其是Linux与其它的GNU软件结合,诞生了GNU下完全自由免费的操作系统。GNU软件功能完善而强大,丝毫不输商业软件,其开源免费的特性也得到了世界各地程序员的积极响应,让GNU软件尤其是Linux得到了相当广泛的应用。笔者此处就搭建Arm交叉编译环境作一个简单的介绍。

1、交叉编译工具链概述

代码编译主要分为预处理、编译、汇编、链接这四个步骤,这个流程需要多个开发工具配合使用。例如预处理和编译需要使用gcc工具,gcc产生汇编代码;汇编代码需要使用as工具把汇编指令对照翻译成机器指令;最后通过链接器ld将各个目标文件组装一起,解决符号依赖、库依赖,生成可执行文件。

除此之外,项目开发往往还需要使用其它的工具。例如通过objcopy将某种格式的目标文件转换成另外格式的文件(elf转hex、bin等);用size显示目标文件各个节的大小和目标文件的大小;用ar生成库文件;生成反汇编调试等等。因此,整个开发过程需要的是一套编译工具链。

2、交叉编译工具链命名方式

由于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;

3、库选择

不管是裸机交叉编译工具链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交叉编译工具,避免多余的交叉编译工具链。

4、制作交叉编译工具链

制作arm交叉编译工具链一般有几种方法。

4.1. 分步架构

分步编译和安装交叉编译工具链所需要的库和源码。由于各个GNU工具相互之间对版本依赖较大、补丁依赖、命令工具依赖等,一旦编译失败,解决完需再重新编译,如此往复,非常浪费精力以及时间,采用这种方法,只能自寻烦恼。

4.2. 脚本工具架构

使用如crosstool-ng脚本可以解决各个GUN工具的版本依赖以及补丁。多次编译后,总能架构成功。但采用通用的GNU源码编译工具,而不是针对arm架构,往往代码优化,性能等不能达到最佳,同时脚本工具所能支持的Arm交叉编译工具链版本往往也不高。采用这种方法,相对吃力不讨好。

4.3. 开源项目工具链

显然一些公司、开源组织已经意识到需要单独维护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应用程序。

5、使用交叉工具链

解压arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2,打开etc/profile,增加交叉工具链的环境变量即可。

注意:
1、一般对于linux应用程序arm交叉编译工具链,往往约定用 arm-linux- 作为linux开发交叉编译工具链的前缀,可以创建arm-linux-工具链的软链接。
2、同时,也可以使用这个交叉编译工具链编译裸机程序,可以采用约定的arm-none-eabi-作为裸机开发交叉编译工具链的前缀,可以创建arm-none-eabi-工具链的软链接。
3、上面的1和2,实际上两者使用的都是同一个编译程序,只是通过软链接制作了两种不同的前缀,以便符合我们的习惯而已!!!

创建的链接脚本link.sh如下,在工具链目录下执行即可(Eastar:通过实践,我把该脚本放在了/home/arm/src/arm-2014.05/bin目录下去执行。 为了顺利执行,需要将其属性设置为可执行。),该脚本内容如下:

#!/bin/bash
for file in $(ls arm-none-linux-gnueabi*)
do
ln -s $file arm-linux${file#arm-none-linux-gnueabi}
ln -s $file arm-none-eabi${file#arm-none-linux-gnueabi}
done

Eastar:
因为我使用的是arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2压缩包格式,所以需要把该脚本文件解压后的放到arm-2014.05/bin目录下,然后运行该脚本,即可产生两种软件链接:一种以arm-linux-开头,一种以arm-none-eabi-开头;
如下图所示,其中左侧和右侧开头的淡蓝色字体就是我刚刚生成的对应的软连接:

6、结语

笔者直接用CodeSourcery已编译好的Arm交叉编译工具链arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2去编译newlib,来支持完整的裸机开发。
有了完整的c库支持,以及linux下集成开发环境eclipse,可以解决依赖关系,可视化选项设置等,避免写makefile脚本,裸机开发与windows下mdk、iar开发并没有太大的差异。
同时,不同版本交叉编译工具链只是简单的编译选项、语法严格等方面的差异,采用这个交叉工具链无需或只需简单地改动即可编译s3c2416以及s5pv210的uboot、linux内核。实现一个交叉编译工具链即可支持裸机、bootloader、linux内核、linux应用程序的开发。

补充:
1、介绍CodeSourcery工具链的文章和下载地址
http://blog.csdn.net/aiqing0119/article/details/46887581
2、将解压的工具链路径添加到etc/environment的PATH的方法:
PATH=”/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/home/arm/src/arm-2014.05/bin

文档更新时间: 2018-10-26 13:06   作者:SofTool