u-boot工程结构和u-boot操作概述
转自
http://blog.csdn.net/HumorRat/archive/2010/11/28/6041576.asp
网上类似的文章很多,本文以u-boot 2010.09为基础,基于个人的一些实践经历在这里进行一些记录,以防自己忘记。
一、u-boot的工程结构。
对于此版本之前的工程结构,网上文章很多,最多的就是 u-boot 1.1.6 u-boot 1.3.4 以及 u-boot 2009.03。
从u-boot 2010.09开始,工程结构发和了一些变化。变化,使得结构更清晰,更简洁,修改起来也更容易。
首先对根目录中的目录和文件进行一些简单说明:
|-api u-boot的一些编程接口(u-boot越来越向着操作系统的方向发展了,有点像DOS了)
|-arch 体系结构相关的内容,都是关于CPU和SOC的内容
|-board 和具体板子相关的内容,包括板子的初始化、片上资源初始化的代码
|-common u-boot的通用代码,包括main函数,命令处理,执行等等的代码
|-disk 磁盘操作相关的代码?这个部分我还没有看。
|-doc u-boot的文档
|-drivers 驱动程序代码
|-examples api应用的一些示例
|-fs 文件系统相关的代码
|-include 头文件目录
|-configs 板级相关的头文件
|-linux 从linux内核中引用来的头文件
|.....
|-lib 与体系无关的通用函数库
|-nand_spl nand引导器,这个应该是这个版本新增的,提供了一种新的方式来制做如nand或sd载入u-boot的方式
|-net 网络相关的代码
|-onenand_ipl 这个不大清楚,猜想与nand_spl可能类似,等有时间看看文档再补充
|-post 没用到呢,也不大清楚
|-tools 一些工具类和脚本类的代码,用于生成配置文件和一些编译相关的与HOST体系相关的东焉
上面这些是目录,下面是一些重要文件(代码根目录的)
Makefile make核心文件
config.mk 供make来引用的一些公共的参数据和规则,如从 .S -> .o 文件的编译参数 .c -> .o 的编译参数等等。
rules.mk 供make来引用的一些规则,主要是depend一类的依懒文件的生成
mkconfig 这是一个可执行脚本,用于生成特定板子的配置文件,以及建立适应特定板子的目录结构(主要是软连接)
boards.cfg 所有和板子相关的配置文件,这些信息在该版本之前都是在Makefile中的,从这个版本开始独立成一个文件,便于移植和改造。
二、配置u-boot
首先,我们先不急于展开来分析Makefile,这样的同类文章在网上一搜一大把。
我们将从操作的角度来思考和移植这个系统。
对于要编译一个对于特定板子的u-boot,首先需要执行的是配置,这个操作在之前的版本上也是一样。这里有一些变化,之前的配置文件都是写在 Makefile的主文件中的。而从这个版本开始,配置文件独立出来,放在boards.cfg中。而同时是由makefile来调用mkconfig这 个可执行脚本来生成相关配置和文件的。
对于配置,这个指令没有变。 make xxxxx_config,xxxxxx是板子的名称。
(这里先插入一句,我的移植目标的板子是一块友善的sbc2410x,一块比较老的板子,虽然在u-boot的库中已有移植,但一方面为了自己学习和理 解,所以决定自己动手,完全重新移植一次;另一方面,这个移植好的u-boot连nand启动都不支持。所以,我选择smdk2410作为移植范例来操 作。同时,我从源码中删掉了已包含的sbc2410x的移植。同时这次学习过程也有助于我下面自己为2440,6410以及将来想学习的omap3530 再移植u-boot和其他程序。)
为了分析makefile,我选择采用smdk2410这个板子先进行配置。
首先,解压u-boot的源码,进入u-boot的根目录,执行 #make smdk2410_config。
(对于GNU MAKE,有详细的说明,可以从网上搜索"GNU MAKE 中文手册"这里只描述和这个移植相关的部分。)
显然, smdk2410_config 这是一个目标。什么是目标?那首先要说make本身。
当执行make后,make会搜索当前目录中是否有 Makefile 或 makefile 这两个文件(二者有其一就可以)。makefile是一个格式化的类似于脚本的文件,下面引用一段文字,摘自GNU MAKE 中文手册
一个简单的Makefile描述规则组成:
TARGET... : PREREQUISITES...
COMMAND
...
...
target: 规则的目标。通常是最后需要生成的文件名或者为了实现这个目的而必需的中间过程文件名。可以是.o文件、也可以是最后的可执行程序的文件名等。另外,目标 也可以是一个make执行的动作的名称,如目标“clean”,我们称这样的目标是“伪目标”。参考4.6 Makefile伪目标一节
prerequisites:规则的依赖。生成规则目标所需要的文件名列表。通常一个目标依赖于一个或者多个文件。
command:规则的命令行。是规则所要执行的动作(任意的shell命令或者是可在shell下执行的程序)。它限定了make执行这条规则时所需要的动作。
一个规则可以有多个命令行,每一条命令占一行。注意:每一个命令行必须以[Tab]字符开始,[Tab]字符告诉make此行是一个命令行。make按照命令完成相应的动作。这也是书写Makefile中容易产生,而且比较隐蔽的错误。
命令就是在任何一个目标的依赖文件发生变化后重建目标的动作描述。一个目标可以没有依赖而只有动作(指定的命令)。比如Makefile中的目标“clean”,此目标没有依赖,只有命令。它所定义的命令用来删除make过程产生的中间文件(进行清理工作)。
在 Makefile中“规则”就是描述在什么情况下、如何重建规则的目标文件,通常规则中包括了目标的依赖关系(目标的依赖文件)和重建目标的命令。 make执行重建目标的命令,来创建或者重建规则的目标(此目标文件也可以是触发这个规则的上一个规则中的依赖文件)。规则包含了文件之间的依赖关系和更 新此规则目标所需要的命令。
一个Makefile文件中通常还包含了除规则以外的很多东西(后续我们会一步一步的展开)。一个最简单的Makefile可能只包含规则。规则在有些Makefile中可能看起来非常复杂,但是无论规则的书写是多么的复杂,它都符合规则的基本格式。
make程序根据规则的依赖关系,决定是否执行规则所定义的命令的过程我们称之为执行规则。
好,对于make smdk2410_config,则应该从Makefile中去寻找smdk2410_config:这个目标。
但是,在新版本的Makefile中,是没有的(老版本中可以找到)
取尔代之的是 %_config:: unconfig 这个目标。%是通配符,代表任意字符。
我们可以看到,这个目标的命令是下面的
@$(MKCONFIG) -A $(@:_config=)
这个目标依懒于unconfig目标
实际上,$(MKCONFIG) = mkconfig,这是个变量 $(@:_config)即,取出这个目标_config之前的部分作为变量
所以 make smdk2410_config,实际效果是:
1)先执行unconfig的命令
2)执行 mkconfig -A smdk2410
而实际上,由于makefile是逐行解析的,在这之上的很多代码都会被执行,主要是一些参数设置的语句。在后面完全解析makefile的时候再细解析。
mkconfig脚本都执行了哪些操作呢?
mkconfig首先会读取boards.cfg。来看一下boards.cfg这个文件
有效内容的格式是这样的:
# Target ARCH CPU Board name Vendor SoC
###########################################################################
sbc2410x arm s3c2410x - -
smdk2410 arm arm920t - samsung s3c24x0
Target:目标名称。
arch:CPU的体系结构。
CPU :具体的CPU型号/类型。
board name:板子的名称,这个是可选的。
Vendor:制造商,这个也是可选的
SoC:片上系统的名称。
以smdk2410为例,体系结构是arm(这个主要影响后面的汇编和编译参数)。CPU的核心是arm920t,由samsung制造。其片上系 统为s3c24x0。这里简单对片上系统说两句。片上系统主要是指制造商为了加快芯片开发和制造,制做了很多成形的硬件模块。对于不同的CPU核心,只要 将这些硬件模块连接到核心,就可以组成强大的处理器,这些处理器可以集成总线如(I2C,I2S),可以集成存储控制器,如(SDRAM控制器,NAND FLASH控制器)。实际上,现代的x86处理器,也都已演变成了片上系统。新一代的intel和amd处理器,都将内存控制器集成到了CPU内部。所 以,从这个意义上说,有些处理器,可以是不同的处理核心(CPU),但确可以使用相同的或非常相似的外设代码,原因就是他们的SoC很类似。如三星公司的 s3c2410 和 s3c2440,其外围的很多设备代码都可以通用。
回到一开始的问题上来:
mkconfig 会根据输入的参数在boards.cfg中寻找匹配的Target。找到后进行如下的工作。
1)建立连接 include/asm ---> arch/arm/include/asm //这里起作用的是arch参数arch=arm
2)建立连接 include/asm/arch ----> include/asm/arch-s3c24x0 //这里起作用的是SoC这个参数
//若配置文件没有SoC这个参数,则会建立
//include/asm/arch ---> include/asm/arch-arm920t 此时 CPU这个参数会起作用
3)建立连接 include/asm/proc-armv ----> include/asm/proc //这个仅对ARM处理器起作用
4)生成 include/config.mk 文件
该文件的内容会是:
arch=arm
cpu=arm920t
board=smdk2410
vendor=samsung
soc=s3c24x0
这些都是根据相应的boards.cfg中的参数来设定的。这个config.mk后面会被makefile引用,用于编译生成可执行的文件。
5)生成 include/config.h
主要内容为
#define CONFIG_BOARDDIR board/samsung/smdk2410
#include <config_defaults.h>
#include <configs/smdk2410.h>
#include <asm/config.h>
该文件用于在编译过程中被代码文件作为通用头文件引用。
三、编译系统
make
或者 make all
这样将执行一个编译过程,最终会生成 u-boot u-boot.bin u-boot.map 文件,其中 u-boot 是链接好的文件,可以用过file指令来查看文件信息,可以用arm-linux-objdump进行反编译。u-boot.bin用于烧入目标板。u- boot.map是各文件在u-boot中的地址分布。
接下来的文章,将一点一点的展开关键文件,并详细的说明对代码的移植过程,以及对系统功能如何来扩展。