赞
踩
前言
文章基于HD-IMX6ULL-MB 系列开发板测试验证,该开发板由武汉芯路遥科技有限公司与武汉万象奥科电子有限公司合作推出。此开发板基于 NXP iMX6ULL 系列 Cortex-A7 高性能处理器设计,适用于快速开发一系列具有创新性的产品如人机界面工业 4.0 扫描仪、车载终端以及便携式医疗设备。
在 X86 架构 Linux 系统下进行 C 程序开发时, 我们使用系统的 gcc 编译器进行代码的编译, 编译生成的可执行程序直接在 X86 架构下的 PC 下运行的,这个过程叫做 本地编译 (Native Compile) 。 而如果该C程序想要编译出来后放到ARM处理器架构的系统上运行, 则需要在 X86 架构Linux系统下使用支持 ARM 的编译器编译, 这个编译器我们通常称为 交叉编译器 (Cross Compiler)。
而在一种平台上编译出能在另外一种体系结构完全不同处理器上运行程序的编译过程,叫做 交叉编译(Cross Compile)。比如在PC平台(X86 CPU)上编译出能运行在以ARM为内核的CPU平台上的程序,编译得到的程序在X86 CPU平台上是不能运行的,必须放到ARM CPU平台上才能运行,虽然两个平台用的都是Linux系统。
交叉编译工具链是一个由编译器、连接器和解释器组成的综合开发环境,交叉编译工具链主要由binutils、gcc和glibc三个部分组成。有时出于减小 libc 库大小的考虑,也可以用别的 c 库来代替 glibc, 例如 uClibc 或 newlib。
之所以几乎所有的ARM开发板开发都选择交叉编译,这是因为这些开发板生产出来后并没有系统,这 时需要在PC上使用交叉编译器交叉编译操作系统源码,为它构建一个完整的 Linux 系统。另外,由于CPU处理能力、外存和内存存储空间的大小限制,它们不足以能够运行 gcc 编译环境,所以嵌入式开发绝大部分的过程都是交叉编译。
Codesourcery一直是在做 ARM 目标 GCC 的开发和优化,它直接提供 Windows和Linux下的二进制版本交叉编译器,不用下载源码包一步一步自己编译,非常方便。它的 ARM GCC 早期在市场上非常优秀,很多公司在作嵌入式产品开发时,都会直接下载使用该公司提供的交叉编译器。
Codesourcery 推出的产品叫 Sourcery G++ Lite Edition, 其中基于 command-line 的编译器是免费的, 在官网上可以下载, 而其中包含的 IDE 和 debug 工具是收费的, 当然也有30天试用版本的。后来CodeSourcery 被明导国际(Mentor Graphics)收购, 现在则被西门子(Siemens) 收购了。
其下载地址为: h ttps://www.plm.automation.siemens.com/global/en/products/embedded-softwa re/sourcery-toolchain-services.html
除了CodeSourcery外,还有一个组织也提供ARM Toolchain,它就是Linaro。Linaro是在2010年台北国际计算机展(COMPUTEX)期间,ARM、Freescale、Samsung ,ST-Ericsson、德州仪器(TI)与IBM等6家大厂,宣布合资成立的非赢利Linux基础架构软件研发商。
Linaro目标在投入新资源和集成业界的努力,改进与优化在ARM-based架构上运行的开放原始码软件及 开发工具,将过去必须由系统单芯片(SoC)业者,各自将本身产品与Linux操作系统集成与开发的重复投 资,透过这间合资公司推出开放原始码的底层软件工具,解决ARM生态系中,重复投资造成的资源浪 费。
其下载链接地址为: h ttps://launchpad.net/linaro-toolchain-binaries
Ubuntu之所以能成为嵌入式系统开发的首选Linux发行版本,正是因为它的软件包在线安装仓库中包含 有海量的开发工具/软件,其中就包括嵌入式系统开发所需的交叉编译器、dtc等开发工具,这也就是为 什么几乎所有主流的半导体厂商在发布SDK时都推荐使用Ubuntu系统。
在Ubuntu 系统中提供了如下四个版本的交叉编译器软件包:
gcc-arm-linux-gnueabi ---- armel,ARM EABI Little-endian
gcc-arm-linux-gnueabihf ---- armhf,ARM Hard Float
gcc-arm-none-eabi ---- bare metal, Linux下用于编译 ARM 架构的裸机系统,使用的是newlib这个嵌入式C库。
gcc-aarch64-linux-gnu ---- arm64,用于编译64位ARM处理器系统
在上面的软件包中,gcc-arm-none-eabi 和 gcc-aarch64-linux-gnu 都比较好理解。而 gcc-arm-linux- gnueabi 与 gcc-arm-linux-gnueabihf 有什么区别呢?这就涉及到 ARM 处理器架构中的浮点运算相关知识了。
出于低功耗、封装限制等种种原因,以前的一些ARM处理器没有独立的硬件浮点运算单元,需要使用软 件来实现浮点运算。随着技术发展,现在高端的ARM处理器基本都具备了硬件执行浮点操作的能力。这 样,新旧两种架构之间的差异,就产生了两个不同的嵌入式应用程序二进制接口(EABI)——软浮点
(SoftFP)与矢量浮点(VFP)。但是软浮点(soft float)和硬浮点(hard float)之间有向前兼容却没有向后兼容的能力,也就是软浮点的二进制接口(EABI)仍然可以用于当前的高端ARM处理器。
在ARM体系架构内核中,有些有浮点运算单元(fpu,floating point unit),有些没有。对于没有fpu内核,是不能使用armel和armhf的。在有fpu的情况下,就可以通过gcc的选项-mfloat-abi来指定使用哪 种,有如下四种值:
1.soft:不用fpu计算,即使有fpu浮点运算单元也不用。
2.armel:(arm eabi little endian)也即softfp,用fpu计算,但是传参数用普通寄存器传,这样中断的时候,只需要保存普通寄存器,中断负荷小,但是参数需要转换成浮点的再计算。
3.armhf:(arm hard float)也即hard,用fpu计算,传参数用fpu中的浮点寄存器传,省去了转换性能最好,但是中断负荷高。
4.arm64:64位的arm默认就是hard float的,因此不需要hf的后缀。
在之前的EABI中,armel(低端ARM硬件)在执行浮点运算之前,浮点参数必须首先通过整数寄存器, 然后传递到浮点运算单元。新的EABI ,也就是armhf,通过直接传递参数到浮点寄存器优化了浮点运算的调用约定。相比我们熟悉的armel,armhf代表了另一种不兼容的二进制标准。在一些社区的支持下,armhf目前已经得到了很大的发展。像Ubuntu,已经计划在之后的发行版中放弃armel,转而支持armhf编译的版本。正如目前依然很火热的Raspberry Pi(ARM11),由于ubuntu只支持armv7架构的编译,Raspberry Pi将不能直接安装ubuntu系统。而 BB Black(Cortex-A8)和 Cubietruct(Cortex-A7)则同时支持ubuntu的armel与armhf的编译。
kernel、rootfs和app编译的时候,指定的必须保持一致才行。使用softfp模式,会存在不必要的浮点到 整数、整数到浮点的转换。而使用hard模式,在每次浮点相关函数调用时,平均能节省20个CPU周期。 对ARM这样每个周期都很重要的体系结构来说,这样的提升无疑是巨大的。在完全不改变源码和配置的 情况下,在一些应用程序上,虽然armhf比armel硬件要求(确切的是指fpu硬件)高一点,但是armhf 能得到20-25%的性能提升。对一些严重依赖于浮点运算的程序,更是可以达到300%的性能提升。
接下来我们以大家熟悉的 hello world 程序为例,讲解嵌入式交叉编译过程。
首先,我们使用 vim 编辑器编写 hello.c 测试程序:
我们知道,C程序必须要使用编译器编译生成可执行程序,才能执行。接下来我们使用 Linux服务器上的
gcc 编译该程序并运行:
我们可以使用 file 命令查看 hello 程序的相关信息,由此可知该程序应该在X86-64位的系统上运行:
我们将该程序下载到开发板上运行试试看,这时系统会提示可执行文件格式出错,不能正常运行。
我们知道C程序具有可移植性,使用PC上的编译器编译生成的程序应该在PC上运行,而不能在其他处理 器架构上运行,那怎样让 hello.c 程序在ARM开发板上运行呢?这里就需要使用ARM的交叉编译器来对该程序进行交叉编译,这样编译输出的可执行程序就能在ARM开发板上运行了。
因为我们的 i.MX6ULL 处理器带有硬件浮点FPU,所以这里我们选择安装硬浮点交叉编译器:
接下来,我们使用 ARM 的交叉编译器编译该 hello.c 程序,并尝试在 X86-64位 Linux服务器上运行,我们会发现 Linux 服务器上默认并不能运行该程序:
接下来我们使用 file 命令查看该程序的相关信息,由此可知该程序应该在ARM处理器系统上运行:
我们将该程序下载到开发板上则能正常运行了。
由此可见:
C程序如果想在PC上运行,则应该用PC的编译器来编译;而该程序想要在ARM开发板上运行,则必 须用ARM的交叉编译器对源码重新进行交叉编译;
C程序具有可移植性是指,C程序源代码不用作任何的修改,使用不同的编译器编译生成的可执行程 序可以在不同的处理器架构平台上运行;
版权声明
本文档所有内容文字资料由凌云实验室郭工编著,主要用于凌云嵌入式Linux教学内部使用,版权归属 作者个人所有。任何媒体、网站、或个人未经本人协议授权不得转载、链接、转帖或以其他方式复制发布/发表。已经授权的媒体、网站,在下载使用时必须注明来源,违者本人将依法追究责任。
Copyright (C)2021 凌云物网智科实验室·郭工
Author: GuoWenxue guowenxue@gmail.com
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。