return(0); }
编译以上3个文件,有如下几种方法: 方法1:
[root@localhost codetest]#arm-linux-gcc -c h1.c [root@localhost codetest]#arm-linux-gcc -c h2.c
[root@localhost codetest]#arm-linux-gcc -o hello hello.c h1.o h2.o 方法2:
[root@localhost codetest]#arm-linux-gcc -c h1.c h2.c
[root@localhost codetest]#arm-linux-gcc -o hello hello.c h1.o h2.o 方法3:
[root@localhost codetest]#arm-linux-gcc -c -o h1.o h1.c [root@localhost codetest]#arm-linux-gcc -c -o h1.o h1.c
[root@localhost codetest]#arm-linux-gcc -o hello hello.c h1.o h2.o 方法4:
[root@localhost codetest]#arm-linux-gcc -o hello hello.c h1.c h2.c -c:只编译不连接。 -o:编译且连接。
2. 产生一个预处理文件,适合看一个宏在源文件中产生的结果。 [root@localhost codetest]#arm-linux-gcc -E h1.i h1.c E:产生一个预处理文件. 1.3.3.2.2
arm-linux-ar 和 arm-linux-ranlib 的使用
静态库是在编译时需要的库。 1. 建立一个静态库
[root@localhost codetest]#arm-linux-ar -r libhello.a h1.o h2.o 2. 为静态库建立索引
[root@localhost codetest]#arm-linux-ar -s libhello.a [root@localhost codetest]#arm-linux-ranlib libhello.a 3. 由静态库产生可执行文件
[root@localhost codetest]#arm-linux-gcc -o hello hello.c libhello.a 1.3.3.2.3
arm-linux-objdump 的使用
1. 查看静态库或.o文件的组成文件
[arm@localhost gcc]$ arm-linux-objdump -a libhello.a 2. 查看静态库或.o文件的组成部分的头部分
[arm@localhost gcc]$ arm-linux-objdump -h libhello.a 3. 把目标文件代码反汇编
[arm@localhost gcc]$ arm-linux-objdump -d libhello.a 1.3.3.2.4
arm-linux-readelf 的使用
1. 读elf文件开始的文件头部
[arm@localhost gcc]$ arm-linux-readelf -h hello ......
2. 读elf文件中所有ELF 的头部:
[root@localhost codetest]#arm-linux-readelf -e hello
......
3. 显示整个文件的符号表
[root@localhost codetest]#arm-linux-readelf -s hello ......
4. 显示使用的动态库
[root@localhost codetest]#arm-linux-readelf -d hello ...... 1.3.3.2.5
arm-linux-strip 的使用
1. 移除所有的符号信息
[root@localhost codetest]#arm-linux-strip ––strip-all hello strip-all:是移除所有符号信息 2. 移除调试符号信息
[root@localhost codetest]#arm-linux-strip -g hello 1.3.3.2.6
arm-linux-objcopy 的使用
生成可以执行的2进制代码
[root@localhost codetest]#arm-linux-objcopy -O binary hello hello.bin 1.3.3.2.7
arm-linux-nm 的使用
列出目标文件的符号清单
[root@localhost codetest]#arm-linux-nm hello.o
1.4 SSH Secure Shell客户端软件的安装及使用
实现更安全的远程登录,可进行ftp操作。
1.5 串口终端Procomm Plus的使用
可以运行命令脚本,实现多个命令的自动运行
1.6 使用Source insight进行代码阅读
Linux源代码阅读的利器
1.7 文件比较工具Araxis Merge2001的使用
可以方便对比文件之间的差异
1.8 文件编辑工具UltraEdit的使用
第二部分最小系统的启动
2 第二章u-boot的移植
2.1 u-boot介绍
Uboot是德国DENX小组的开发用于多种嵌入式CPU的bootloader程序, UBoot不仅仅支持嵌入式Linux系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。UBoot除了支持PowerPC系列的处理器外,还能支持MIPS、 x86、ARM、NIOS、XScale等诸多常用系列的处理器。本文的代码取自于uboot1.1.4。
2.2 获取u-boot
从下面地址下载uboot的源代码。 http://sourceforge.net/projects/uboot [uboot@localhost uboot]#tar xjvf uboot1.1.4.tar.bz2 [uboot@localhost uboot]#cd uboot1.1.4
2.3 u-boot体系结构
1. 目录树
.
|board |common |cpu |disk |doc |drivers |dtt
|examples |fs
|include |lib_arm |lib_generic |lib_i386 |lib_m68k
|lib_microblaze |lib_mips |lib_nios |lib_nios2 |lib_ppc |net |post |rtc `tools 2. board:和一些已有开发板有关的文件. 每一个开发板都以一个子目录出现在当前目录中,比如说:SMDK2410,子目录中存放与开发板相关的配置文件.
3. common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。例如bootm
命令对应就是cmd_bootm.c。
4. cpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录arm920t等。
5. disk:对磁盘的支持。
6. doc:文档目录。Uboot有非常完善的文档,推荐大家参考阅读。 7. drivers:Uboot支持的设备驱动程序都放在该目录,比如各种网卡、支持CFI的Flash、串口和USB等。
8. fs: 支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。
9. include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。该目录下configs目录有与开发板相关的配置头文件,如smdk2410.h。该目录下的asm目录有与CPU体系结构相关的头文件,asm对应的是asmarm.9. lib_xxxx: 与体系结构相关的库文件。如与ARM相关的库放在lib_arm中。
10. net:与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。
11. tools:生成Uboot的工具,如:mkimage, crc等等。
2.4 u-boot编译及配置
2.4.1 u-boot的Makefile分析
u-boot的Makefile从功能上可以分成两个部分。一部分是用来编译生成uboot.bin文件;另一部分是用来执行每种board相关的配置。下面以smdk2410为例来说明作了哪些配置。
$make smdk2410_config
在shell执行以上命令,对应于Makefile执行的命令是 smdk2410_config : unconfig @./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
首先执行如下命令,删除文件include/config.h include/config.mk board/*/config.tmp,后续会发现这些文件是如何建立的。
unconfig: @rm -f include/config.h include/config.mk board/*/config.tmp
然后运行命令@./mkconfig $(@:_config=) arm arm920t smdk2410 NULL s3c24x0,mkconfig是脚本文件,传入的参数$1至$6分别为:smdk2410 arm arm920t smdk2410 NULL s3c24x0,根据传入的参数执行如下命令
cd ./include rm –f asm ln –s asm-arm asm rm –f asm-arm/arch ln –s arch-s3c24x0 asm-arm/arch rm –f asm-arm/proc ln –s proc-armv asm-arm/proc 生成文件config.mk,文件内容为: ARCH = arm
CPU = arm920t BOARD = smdk2410 SOC = s3c24x0
生成文件config.h,文件内容为: /* Automatically generated - do not edit */
#include
至此make smdk2410_config的命令全部执行完毕。配置完成与board相关的信息,下面就可以编译此board的u-boot.bin文件,执行如下命令:
$make CROSS_COMPILE=arm-linux-
Makefile的执行首先包含include include/config.mk文件,获取ARCH CPU BOARD VENDOR SOC的定义,然后根据宏的配置编译指定的文件,最终生成u-boot.bin文件,执行流程请自行分析。
2.4.2 u-boot.bin的生成
根据以上对于makefile的分析,u-boot.bin的生成分为两步。如下: 对于board进行配置: $make smdk2410_config
进行编译生成u-boot.bin: $make CROSS_COMPILE=arm-linux-
2.5 u-boot的启动过程及工作原理
2.5.1 启动模式介绍
大多数 Boot Loader 都包含两种不同的操作模式:\启动加载\模式和\下载\模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看,Boot Loader 的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。
启动加载(Boot loading)模式:这种模式也称为\自主\(Autonomous)模式。也即 Boot Loader 从目标机上的某个固态存储设备上将操作系统加载到 RAM 中运行,整个过程并没有用户的介入。这种模式是 BootLoader 的正常工作模式,因此在嵌入式产品发布的时侯,Boot Loader 显然必须工作在这种模式下。
下载(Downloading)模式:在这种模式下,目标机上的 Boot Loader 将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被 BootLoader 保存到目标机的 RAM 中,然后再被 BootLoader 写到目标机上的FLASH 类固态存储设备中。BootLoader 的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用 BootLoader 的这种工作模式。工作于这种模式下的 Boot Loader 通常都会向它的终端用户提供一个简单的命令行接口。
UBoot这样功能强大的 Boot Loader 同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。
大多数bootloader都分为阶段1(stage1)和阶段2(stage2)两大部分,uboot也不例外。依赖于CPU体系结构的代码(如CPU初始化代码等)通常都放在阶段1中且通常用汇编语言实现,而阶段2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
2.5.2 阶段1介绍
uboot的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要代码部分如下: 2.5.2.1
定义入口
由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
1. board/smdk2410/uboot.lds: ENTRY(_start) ==> cpu/arm920t/start.o (.text) 2. uboot在ram的代码区(TEXT_BASE = 0x33F80000)定义在board/smdk2410/config.mk 2.5.2.2
设置异常向量
.globl _start