嵌入式系统设计与实践 I
编辑:谭石坚
时间:2017.1
目 录
1 交叉编译器.....................................................................................................................................3
1.1 gcc 的历史.............................................................................................................................3
1.2 GNU 编译器套件.................................................................................................................. 3
1.3 制作交叉编译器..................................................................................................................5
2 GCC‐ARM 裸奔程序设计.................................................................................................................9
2.1 了解 4412SOC 的启动流程.................................................................................................9
2.1.1 4412 SOC 的体系结构...............................................................................................9
2.1.2 tiny4412 从 SD 启动的流程....................................................................................11
2.1.3 IRAM 的内存布局....................................................................................................12
2.1.4 SD 卡/EMMC 的布局...............................................................................................13
2.2 GCC‐ARM 编程基本知识....................................................................................................13
2.3 tiny4412 点灯裸奔程序设计实例..................................................................................... 17
2.4 C 语言的裸奔闪灯程序......................................................................................................21
3 u‐boot 移植....................................................................................................................................23
3.1 u‐boot 的基本配置编译.....................................................................................................23
3.2 u‐boot 的使用.....................................................................................................................24
3.3 u‐boot 的配置编译详细分析.............................................................................................25
3.4 u‐boot 源码分析.................................................................................................................26
3.4.1 启动流程.................................................................................................................27
3.4.2 u‐boot 命令的执行代码分析................................................................................. 29
3.4.3 添加自定义命令.....................................................................................................33
3.5 u‐boot 的移植与设置.........................................................................................................34
3.5.1 u‐boot 移植注意事项..............................................................................................34
3.5.2 u‐boot 的一些设置..................................................................................................34
4 内核移植与启动...........................................................................................................................37
4.1 linux 基本配置编译............................................................................................................37
4.2 linux 内核生成过程详解....................................................................................................37
4.3 启动 linux 内核..................................................................................................................38
4.3.1 设置启动参数.........................................................................................................38
4.3.2 设置 CPU 状态........................................................................................................40
4.4 u‐boot 添加一个启动 zImage 的命令...............................................................................40
5 根文件系统...................................................................................................................................43
5.1 构建简单根文件系统........................................................................................................43
5.2 NFS 测试根文件系统 ....................................................................................................... 44
5.3 编写启动脚本....................................................................................................................45
5.3.1 移植 bash..............................................................................................................47
5.3.2 配置文件...............................................................................................................47
5.4 常用软件移植....................................................................................................................49
5.4.1 移植文件系统工具 e2fsprogs.................................................................................49
5.4.2 移植串口通信应用程序 lrzsz................................................................................ 49
5.5 系统部署............................................................................................................................50
6 项目扩展.......................................................................................................................................51
1 交叉编译器
在一种计算机体系结构中运行的编译器,能编译出在另外一种体系结构下运行的代码,
我们就称这种编译器支持交叉编译。这个编译过程就叫交叉编译。简单地说,就是在一个平
台上生成另一个平台上的可执行代码。在开源软件中,最著名的编译器是 gcc,其支持多种
体系结构的 CPU,因此得到广泛的应用。在 Linux 中,开发软件时不管是本地编译还是交叉
编译,绝大多数都是使用 gcc。
1.1 gcc 的历史
gcc 是 GNU Compiler Collection(GNU 编译器套件)的简称,gcc 是 GNU 自由软件的一
个很重要的组成部分。
GNU 计划,又称革奴计划,是由 Richard Stallman 在 1983 年 9 月 27 日公开发起的。它
的目标是创建一套完全自由的操作系统。GNU 是“GNU is Not Unix”的递归缩写。
到了 1990 年,GNU 计划已经开发出的软件包括了一个功能强大的文字编辑器 Emacs[1],
GCC(GNU Compiler Collection,GNU 编译器集合),是一套由 GNU 开发的编程语言编译器,
以及大部分 UNIX 系统工具。唯一依然没有完成的重要组件就是操作系统的内核( 称为
HURD)。
1991 年 Linus Torvalds 编写出了与 UNIX 兼容的 Linux 操作系统内核并在 GPL 条款下发布。
1992 年 Linux 与其他 GNU 软件结合,完全自由的操作系统正式诞生。该操作系统往往被称
为“GNU/Linux”或简称 Linux。
GNU 的官网:http://www.gnu.org/
Linux 的官网:https://www.kernel.org/
1.2 GNU 编译器套件
gcc 是 GNU 编译器套件,由二进制处理工具(binutils)、编译工具(gcc)、C 库(glibc)、以及
调试器(gdb)组合而成。
对于 C 程序开发来说,更加关注的是编译器工具、链接库、头文件三大部分的位置,在
本地(local)的 linux 系统中,这三大部分默认的位置如下:
编译器工具的默认路径: /usr/bin/
/usr/lib/
函数库的默认路径:
/usr/include
头文件的默认路径:
GNU 提供的工具包括二进制处理工具,编译器,调试器等,如下表:
工具
addr2line
ar
as
c++filt
表 1‐1 GNU 工具表
功能说明
把程序地址转换为文件名和行号
建立, 修改档案或从档案中抽取成员
汇编器,主要用来编译汇编文件
连接器使用它来过滤 C++ 和 Java 符号,防止重载函数冲突。
cpp
elfedit
g++
gcc
gcov
gdb
gprof
ld
ldd
nm
objcopy
objdump
ranlib
readelf
size
strings
strip
C 预处理器
更新 elf 格式文件的头部和 elf 文件
C++编译器
C 编译器
测试代码覆盖率的工具
调试器
精确地给出函数被调用的时间和次数
链接器
显示共享库的依赖情况
列出目标文件中的符号信息
拷贝和转换目标文件,用于格式转换
显示目标文件的信息,可以用于反汇编
生成归档文件的索引表,用于制造共享库
显示 elf 文件的相关信息
列出段节大小和总共大小
显示文件中的可打印字符
丢弃目标文件中的全部或者特定符号,减小文件体积
GNU 工具的使用举例:
一个阶乘的 C 程序代码如下 test.c:
#include
int fact(int n)
{
if(n==1 || n==0)
else return n*fact(n‐1);
return 1;
printf("\t %d!=%d \n",9,fact(9));
return 0;
}
int main(void)
{
}
(1)C 程序编译
分步骤编译:
$ cpp test.c ‐o test.i
$ /usr/lib/gcc/i686‐linux‐gnu/4.8.4/cc1 test.i ‐o test.s
$ as test.s ‐o test.o
$ ld test.o /usr/lib/i386‐linux‐gnu/{crt1.o,crti.o,crtn.o} ‐dynamic‐linker /lib/ld‐linux.so.2
‐lc ‐o test
也可以直接一步编译:
$ gcc test.c
‐o test
‐g
‐v
(2)二进制处理工具
编译出来的程序 test,可以使用下面的工具处理:
查看符号地址:
$ nm test
从地址得到源文件和行号:
$ addr2line ‐e test ‐a 0804841d
显示程序的信息:‐h 显示头部信息;‐d 显示链接库信息
$ readelf ‐h test
$ readelf ‐d test
显示段大小:
$ size test
格式转换:转换成二进制格式
$ objcopy
反汇编:
$ objdump ‐d test >test.dis
去除符号信息:
$ strip ‐s
‐O binary
test
test
test.bin
(3)测试工具 gprof,gcov
gcov 是一个测试代码覆盖率的工具
$ gcc ‐fprofile‐arcs ‐ftest‐coverage ‐o test test.c
$ ./test
$ gcov test.c
生成的文件 test.c.gcov 就是代码覆盖率的报告文件
gprof 是一个精确地给出函数被调用的时间和次数
$ gcc ‐pg test.c ‐o test
$ ./test
$ gprof ‐b test gmon.out >gprof.txt
生成的文件 gprof.txt 就是结果文件
1.3 制作交叉编译器
对于嵌入式 linux 系统开发来说,开发 ARM 上的软件都需要交叉编译,这就要求我们首
先要有一个交叉编译器。开发板厂商一般都会提供交叉编译器。网上很多地方都可以下载制
作好的 ARM 交叉编译器,启动比较著名的 ARM 交叉编译器下载网站是:
https://launchpad.net/gcc‐arm‐embedded/+download
由于 GNU 编译器套件是开源的项目,作为学习我们也可以自己制作一个交叉编译器。
GNU 编译器套件的源码都可以从 ftp.gnu.org 上获取,源码分成如下几部分:
binutils :提供二进制处理的工具
gcc
:提供强大的 gcc 编译器
glibc :提供标准 C 库
gdb
交叉编译器制作的步骤如下图:
:提供调试器
编译binutils源码包
第一次编译gcc源码包
编译glibc源码包
编译完整的gcc
图 1‐1 交叉编译器制作步骤
交叉编译器的制作步骤非常繁琐,因此有人将交叉编译器制作的步骤做成脚本,叫
crosstool,后来这个脚本越来越完善升级为 crosstool‐ng。
其官方网站:http://www.crosstool‐ng.org/
下载连接:http://www.crosstool‐ng.org/download/crosstool‐ng/crosstool‐ng‐1.22.0.tar.bz2
crosstool‐ng 的宗旨就是:让交叉编译器的制作,更加简单,让制作交叉编译器的工具,
更加好用。
crosstool‐ng 的使用的基本逻辑如下:
(1)下载,编译,安装 crosstool‐ng 工具本身;
(2)用 crosstool‐ng 这个工具(即 ct‐ng)去制作(配置和编译)所需要的交叉编译器。
下面是使用 crosstool‐ng 制作交叉编译器的步骤:
(1) 下载、配置、安装 crosstool‐ng:
$ mkdir /home/sice/sources
$ cd /home/sice/sources/
$ wget ‐c http://www.crosstool‐ng.org/download/crosstool‐ng/crosstool‐ng‐1.22.0.tar.bz2
$ tar jxf crosstool‐ng‐1.22.0.tar.bz2
$ cd crosstool‐ng/
$ ./configure ‐‐prefix=/home/sice/ctool
$ make
$ make install
安装后,可以删除过程文件:
$ cd ..
$ rm crosstool‐ng ‐fr
$ cd ..
(2) 建立制作交叉编译器工作目录:
$ mkdir build
$ cd build/
(3) 配置交叉编译器:
$ /home/sice/ctool/bin/ct‐ng list‐samples
$ /home/sice/ctool/bin/ct‐ng
arm‐unknown‐linux‐gnueabi
$ /home/sice/ctool/bin/ct‐ng menuconfig
配置如下:
Paths and misc options
‐‐‐>
(${HOME}/sources) Local tarballs directory
(/opt/crosstool/4.8.5) Prefix directory
Toolchain options
‐‐‐>
(sice) Tuple's vendor string
Operating System ‐‐‐>
Linux kernel version (3.2.72)
[ ] Check installed headers
‐‐‐>
Binary utilities
‐‐‐>
binutils version (2.22)
‐‐‐>
C‐library
‐‐‐>
C compiler
‐‐‐>
gcc version (4.8.5)
‐‐‐>
Debug facilities
‐‐‐>
[*] gdb ‐‐‐>
gdb version (7.8)
‐‐‐>
glibc version (2.19)
Minimum supported kernel version (Specific kernel version)
(3.0) Minimum kernel version to support
‐‐‐>
‐‐‐>
保存配置。
(4) 开始制作交叉编译器
$ sudo chown ‐R sice /opt
$ /home/sice/ctool/bin/ct‐ng build
$ sudo chmod u+w ‐R /opt/crosstool/4.8.5
$ cd ../
$ rm build/ ‐fr
$ rm ‐fr ctool/
(5) 交叉编译制作好后,安装在/opt/crosstool/4.8.5 目录下,一般可以将交叉编译工具
简化为以 arm‐linux‐开头的命令,下面的脚步用于建立相应的符号连接。
$ cd /opt/crosstool/4.8.5/bin/
$ for file in addr2line ar as c++ cc c++filt cpp ct‐ng.config elfedit g++ gcc gcc‐4.8.5 gcc‐ar
gcc‐nm gcc‐ranlib gcov gdb gprof ld ld.bfd ldd ld.gold nm objcopy objdump populate ranlib
readelf size strings strip
$ do
$ ln ‐s arm‐sice‐linux‐gnueabi‐$file arm‐linux‐$file
$ done
(6) 设置交叉编译器所在的路径添加到环境变量 PATH 中,使得能够在命令行中直接找
到交叉编译工具。
$ sudo gedit /etc/profile
在打开文件的最后添加下面一行:
export PATH=/opt/crosstool/4.8.5/bin:$PATH
保存文件,使用下面的命令使得设置生效:
$ source /etc/profile
或者注销再登录,使得设置生效。
设置好后,在命令行可以直接使用 arm‐linux‐gcc 等命令了。
本节课重点:
1 了解交叉编译器制作的过程,掌握 crosstool‐ng 的使用;
2 掌握 GCC 工具的使用:cpp,cc1,gcc,as,ld,objcopy,objdump 等。