目录

1. uboot源码目录简介

2. uboot编译原理引入

2.1 功能模块配置

2.1.1 在.c文件中不编译相应的功能语句

2.1.2 在make时不编译相应的功能模块

2.2 跨平台编译环境配置

3. uboot配置过程解析

3.1 make x210_sd_config

3.1.1 执行unconfig目标

3.1.2 调用mkconfig脚本生成配置文件

3.1.3 将TEXT_BASE写入config.mk配置文件

3.2 mkconfig脚本分析

3.2.1 参数对应关系

3.2.2 参数检查

3.2.3 建立体系结构相关的软链接

3.2.4 建立config.mk供Makefile使用

3.2.5 建立config.h供源文件使用

4. uboot主Makefile解析

4.1 生成uboot版本信息

4.2 获取编译主机信息

4.3 配置静默编译

4.4 配置原地编译 / 输出目录编译

4.4.1 原地编译与输出目录编译

4.4.2 如何配置输出目录编译

4.4.3 Makefile中如何处理输出目录编译

4.5 导入include/config.mk

4.6 配置工具链前缀

4.7 导入$(TOPDIR)/config.mk

4.7.1 定义obj & src变量

4.7.2 定义工具链

4.7.3 加载ARCH / CPU / SoC / Board配置文件

4.7.4 导入链接器脚本

4.7.5 设置编译选项

4.7.6 设置编译默认规则

4.8 定义目标文件

4.9 定义最终目标

5. uboot链接器脚本分析

6. 向uboot中添加功能模块

6.1 添加uboot中自带功能模块

6.1.1 在板级配置头文件中添加配置项

6.1.2 在源码中引用dm9000.c的相关函数

6.1.3 重新编译uboot

6.2 添加自定义功能模块

6.2.1 添加功能模块代码

6.2.2 修改子Makefile

6.2.3 修改板级配置头文件

6.2.4 重新编译uboot


1. uboot源码目录简介

x210 uboot目录结构如下图所示,

说明1:x210使用的uboot版本相对较早(2008年8月版本)且经过裁剪(去掉了除ARM外其他架构的内容),目前新的uboot目录结构有所调整

① 增设了arch目录,统一管理不同架构的cpu和lib_arch目录

② 将common目录中与命令相关的源文件单独建立cmd目录进行管理

③ 修改了配置方式

原先所有配置项均在主Makefile中,现在新建configs目录统一管理所有板级配置文件(板级配置头文件仍在include/configs目录下)

④ 修改了主Makefile,将原先以.mk文件形式包含的配置文件纳入主Makefile(能这么做也就是因为将板级配置命令均移出了主Makefile)

说明2:uboot的目录的整体结构是随着层次递进的

ARCH        -->        CPU        -->        SoC        -->        board

arm                          arm920t                s5pc1xx              smdkc110

mips                         armv7                   s5pc11x              x210

就具体子目录而言:

① 架构相关目录(此处架构指CPU架构 + SoC型号)

cpu/    lib_arm/    board/

② 架构无关硬件相关目录(主要是配置片外外设,e.g. dm9000网卡芯片)

drivers/

③ 硬件无关目录(如命令解析 / 网络协议实现 / 文件系统支持)

common/    net/    fs/    api/

④ 通用以及配置头文件(尤其要注意板级配置头文件)

include/

2. uboot编译原理引入

2.1 功能模块配置

uboot提供的功能模块非常之多,比如网卡驱动就有许多种,但是我们往往只使用众多功能模块中的一小部分。为此,我们需要在编译时排除那些我们不使用的功能模块以减小最终编译出的uboot.bin体积

要排除某一功能模块需要完成如下2个步骤:

2.1.1 在.c文件中不编译相应的功能语句

对于非必须的可选功能模块语句用条件编译命令提供编译开关,为了集中管理这些功能语句开关,可以建立专门的配置头文件config.h

这样就可以在config.h中集中管理功能模块语句是否编译

2.1.2 在make时不编译相应的功能模块

经过上一个步骤,虽然.c文件中使用功能模块的语句可以根据条件不予编译,但是相应的功能模块(如led.c ---> led.o)依然会被编译。因为Makefile的依赖中依然有相应的.o文件,所以他们依然会被编译

所以还要修改Makefile,对功能模块的编译进行控制。修改的思路和之前相同,我们添加这些带有参数的目标

而在编译中仅让变量objs-y所包含的.o文件参与,这样通过控制objs-$(CONFIG_LED) += drivers/led.o中变量CONFIG_LED的值就可以决定相应的功能模块是否被编译

注意:只要不出现在编译目标之中,默认规则并不会编译相关源文件

此处我们同样可以建立配置文件config.mk统一管理

这样只要在Makefile中包含了config.mk,自然就对相应功能模块是否编译进行了控制。

说明1:根据上面的介绍,只要这两个配置文件保持一致,也就是说在config.h中被定义的功能模块在config.mk中也被定义为y,那么就可以实现对相应功能模块及功能语句是否被编译进行控制

说明2:config.h供源代码使用,config.mk供Makefile使用,在实现层面一般只要配置其中一个文件, 然后通过脚本分析产生另一个文件

在uboot的配置中,是修改config.h文件,然后在主Makefile中使用sed解析并生成config.mk文件

在Linux内核的配置中,则是修改config.mk文件,然后自动生成config.h文件

2.2 跨平台编译环境配置

上面介绍的内容只是涉及某一个功能模块(在实现层面就是某个.c或.s文件)是否被编译,下面介绍的跨平台编译环境的配置则涉及整个目录是否被编译

uboot是一个跨平台软件,他支持多种架构的CPU,对不同架构的支持往往包含在arch目录中(之前的uboot是cpu目录)

不同的架构使用不同的编译器,而且在众多架构中一次只能编译其中一种,而其余目录的内容不予编译,这点在Makefile中需要有所体现

通过变量ARCH我们可以对不同平台的编译环境进行配置

通过这个变量也控制了对哪些目录下的内容进行编译

3. uboot配置过程解析

3.1 make x210_sd_config

编译uboot前的配置就是执行make x210_sd_config命令

x210_sd_config目标如下

执行该目标会完成3个任务:

3.1.1 执行unconfig目标

unconfig伪目标用于清除上次配置生成的文件

说明:生成的配置文件简介

在删除的地方反而更容易集中查看生成的配置文件~.~,这些配置文件的生成细节详见下文分析

① include/config.h

include/config.h在配置过程中自动生成,内容就是包含板级配置头文件include/configs/x210_sd.h

② include/config.mk

include/config.mk在配置过程中自动生成,该文件定义了一组变量,供主Makefile包含

③ include/autoconf.mk

include/config.mk在配置过程中自动生成,该文件通过解析板级配置头文件生成,供Makefile包含,用于控制功能模块的编译

④ board/samsung/x210/config.mk

board/samsung/x210/config.mk在执行x210_sd_config目标时生成,该文件记录了uboot的链接地址

3.1.2 调用mkconfig脚本生成配置文件

此处调用mkconfig脚本时会传递6个参数,下面分析一下第1个参数的构成方式,

$(@:_config=):将目标($@)中的_config替换为等号后的内容,此处为空,所以该参数就是x210_sd

因此,传递给mkconfig的参数如下,

$1:x210_sd

$2:arm

$3:s5pc11x

$4:x210

$5:samsung

$6:s5pc110

$#:6

注:$#代表脚本命令行参数个数,并不包含$0,即脚本名称

3.1.3 将TEXT_BASE写入config.mk配置文件

TEXT_BASE用于在链接时指定uboot.bin的链接地址,该信息保存在board/samsung/x210/config.mk中,供主Makefile包含使用

3.2 mkconfig脚本分析

3.2.1 参数对应关系

根据mkconfig脚本注释,传递给该脚本的参数对应关系如下,

Target:x210_sd

Architecture:arm

CPU:s5pc11x

Board:x210

VENDOR:samsung

SOC:s5pc110

说明1:VENDOR和SOC参数为可选项,因此合法的参数个数为4 / 5 / 6。至于这2个参数如何使用,后文有分析~~

说明2:如果没有VENDOR和SOC参数,传递时该位置可以留空也可以用NULL(mkconfig脚本中会分析),但是如果有SOC但是没有VENDOR,则VENDOR处只能使用NULL,以便占位。

3.2.2 参数检查

说明1:while循环用于解析参数中的特殊选项,此处第1个参数就不是特殊选项,所以进入*)分支,直接跳出循环。

此处需要注意的是,使用shift命令可以实现对shell脚本参数的遍历(shift会同时修改$#和$1的值)

说明2:如前所述,合法的参数个数为[4, 6]。注意,这是去除特殊选项之后的参数个数~~

当然,根据这个while循环的结构,如果调用mkconfig脚本时需要带有特殊选项,需要在各有效参数之前

3.2.3 建立体系结构相关的软链接

说明1:此处创建软链接的操作都是在include/目录下完成的

在mkconfig脚本起始处便cd ./include,进入include目录下操作

说明2:通过建立头文件目录的软链接,实现uboot的跨平台移植性。例如start.S中包含了下面2个头文件。

asm/proc/domain.h就是asm-arm/proc/domain.h

regs.h就是s5pc110.h,该头文件对SoC的SFR进行了定义

说明3:根据上文,对于asm-arm/mach这个软链接,首先指向了arch-s5pc110,之后将其覆盖指向arch-s5pc11x

需要注意的是,include/asm-arm目录下并没有arch-s5pc110目录,但是依然可以调用

ln  -s  arch-s5pc110  asm-arm/arch

因为软链接的本质是新建一个文件,该文件中存储的就是指向文件的文件名,只不过此处指向一个不存在的文件,该软链接无效而已

3.2.4 建立config.mk供Makefile使用

生成的config.mk只是包含ARCH / CPU / BOARD / VENDOR / SOC这5个变量的定义,供主Makefile包含使用(主Makefile中会导出这些变量,使其在整个工程中生效)

3.2.5 建立config.h供源文件使用

生成的config.h只是包含了板级配置头文件include/configs/x210_sd.h,该板级配置头文件中包含了开发板的所有配置项,因此代码中只要包含<config.h>即包含了所有配置项

根据上文介绍,包含<config.h>后就可以在源代码中控制功能模块调用语句的条件编译

说明:如果调用mkconfig脚本时带有-a选项,则不会新建config.h,而是将内容追加到原有config.h之后(这个用法不常见~~)

4. uboot主Makefile解析

说明:本节并不是从all目标开始分析主Makefile,而是按Makefile的顺序分析该文件

4.1 生成uboot版本信息

说明1:此处需要注意的是,定义VERSION_FILE变量时使用了等号(=),因此是引用时展开,所以在定义中可以使用尚未定义的obj变量

如果此处使用(:=),将会在定义处展开,那么此处$(obj)的值就是空

说明2:对version_autogenerated.h的使用

include/version_autogenerated.h会被include/version.h包含,因此在实际使用中,只要包含<version.h>即可获得uboot版本信息

4.2 获取编译主机信息

4.3 配置静默编译

如果调用make带上-s选项,该选项(s)会成为变量MAKEFLAGS的一部分,此时会将变量XECHO置为空,从而实现静默编译(即编译时不出现Makefile的打印信息)

4.4 配置原地编译 / 输出目录编译

4.4.1 原地编译与输出目录编译

uboot提供了2种编译方式(Linux内核等复杂工程也都提供),

① 原地编译

含义:在.c/.S源码目录生成目标文件(.o)

优点:处理简单

缺点:

a. 污染源文件目录

b. 一套源代码只能按照一种配置进行编译,一旦更换配置,需要先make clean之后才能更换配置编译

当然也可以每种配置各使用一套源代码,但这将加大维护的难度(e.g. 一个文件需要修改,需要在每套源代码中都实现)

② 输出目录编译

含义:在编译时指定输出目录,然后在指定的输出目录生成目标文件(.o)

优点:

a. 不再污染源代码目录

b. 一套代码更换配置编译时,只需指定不同的输出目录即可

4.4.2 如何配置输出目录编译

uboot提供2种方式指定输出目录,

① 命令行中添加 O=xxx,示例如下,

make O=/tmp/build distclean
make O=/tmp/build x210_sd_config
make O=/tmp/build all

② 导出BUILD_DIR变量,示例如下,

export BUILD_DIR=/tmp/build
make distclean
make x210_sd_config
make all

注意:对于移植后的uboot版本,如果添加的代码不支持输出目录编译,该功能就无法使用。x210的uboot版本在新增的代码中并不支持该功能,所以无法使用。

4.4.3 Makefile中如何处理输出目录编译

说明1:根据主Makefile的处理逻辑,如果在指定O=xxx的情况下,也导出了BUILD_DIR变量,那么O=xxx的优先级更高

说明2:CURDIR是Makefile的内置变量,无需定义,其值为当前目录的绝对地址

说明3:obj & src变量在uboot顶层目录的config.mk中定义,但是在包含config.mk之前某些目标需要使用这些变量,所以此处定义一次

4.5 导入include/config.mk

如上文分析,include/config.mk由mkconfig脚本生成,此处包含该文件并导出其中各变量

4.6 配置工具链前缀

此处根据导出的ARCH变量配置合适的工具链前缀,并导出CROSS_COMPILE变量

4.7 导入$(TOPDIR)/config.mk

uboot的顶层目录的config.mk文件用于进行进一步的配置,具体内容如下

4.7.1 定义obj & src变量

可见此处如果采用原地编译,obj & src会被置为空

4.7.2 定义工具链

4.7.3 加载ARCH / CPU / SoC / Board配置文件

说明1:此处使用sinclude包含配置文件是防止如果没有该配置文件导致报错(并不是每个配置文件都要存在~~)

说明2:此处包含的include/autoconf.mk文件非常重要,该文件由板级配置头文件x210_sd.h解析而来,该文件可用于控制功能模块的编译

说明3:VENDOR & SOC变量的使用

如前文所述,在调用mkconfig脚本时,这两个变量可选,如包含的话用法如下,

board/$(VENDOR)/$(BOARD):构成开发板路径,比如三星将其开发板目录置于board/samsung目录下(当然,出于历史原因,为了保持向后兼容三星某些开发板目录并没有放置在board/samsung目录下)

cpu/$(CPU)/$(SOC):构成SoC路径,目前新版uboot中$(CPU)目录一般是ARM核的架构目录(e.g. armv7),$(SOC)目录为该架构下的SoC目录(e.g. s5pc1xx)

下图为2012-10版本的uboot示例

说明4:此处导入的$(TOPDIR)/board/$(BOARDDIR)/config.mk文件就是配置uboot时生成的文件,其中包含链接地址的定义

4.7.4 导入链接器脚本

4.7.5 设置编译选项

要设置的编译选项很多,此处列出比较重要的2点,

① -DTEXT_BASE=$(TEXT_BASE)

在x210中相当于在编译时定义如下的宏,

#define TEXT_BASE 0xc3e00000

该宏在uboot代码中会被多次使用,以便获取uboot的链接地址,只不过使用该值的方式是定义_TEXT_BASE变量

注:这也相当于实现了Makefile配置文件与源代码配置文件的交互

② -I选项的设置

设置-I选项时要注意对输出目录编译方式的支持

4.7.6 设置编译默认规则

此处可见对输出目录编译方式的支持,如果使用该方式,会在指定目标生成目标文件

4.8 定义目标文件

可见编译时会将大多数目录下的文件编译为静态库供最终链接使用

注:在uboot阶段也只能以静态库的方式链接,此时没有操作系统,是无法使用动态库的

4.9 定义最终目标

可将uboot最终的链接过程与我们裸机代码工程相同

说明1:include/autoconf.mk文件的生成

在编译$(OBJS)和$(LIBS)时均会依赖include/autoconf.mk,因为是否编译某个源文件需要autoconf.mk的控制

而生成autoconf.mk的方式则是使用define2mk.sed脚本解析include/config.h(该头文件中就是包含板级配置头文件include/x210_sd.h),这与之前uboot编译原理引入部分的分析是一致的。

说明2:由于uboot的运行环境类似裸机代码,所以最终烧写运行的是u-boot.bin而不是ELF格式的u-boot文件,u-boot.bin由u-boot经过objcopy转换而来,仅包含ELF格式文件中的可执行部分

5. uboot链接器脚本分析

说明1:链接器脚本的链接起始地址指定为0x00000000,这是因为在使用链接器脚本的同时使用-Ttext选项指定了代码段链接地址,而-Ttext指定的优先级高于链接器脚本

因此在实现中,使用链接器脚本确定ELF文件布局,使用-Ttext选项确定链接地址

说明2:由于要截取uboot.bin的前8KB作为BL1,因此必须把代码重定位可能用到的内容链接到代码段最前端(e.g. x210实现代码重定位的文件就是cpu/s5pc11x/movi.c)

说明3:注意uboot中的2个自定义段

① .u_boot_cmd段

uboot命令的描述结构体被链接到该段,使用__u_boot_cmd_start和__u_boot_cmd_end可以实现对所有uboot命令结构体的遍历

补充:对链接器脚本变量的使用,可参考如下笔记,

有道云笔记

② .mmudata段

uboot使用的Translation Table会被链接到.mmudata段

6. 向uboot中添加功能模块

6.1 添加uboot中自带功能模块

说明:以添加dm9000网卡驱动为例

6.1.1 在板级配置头文件中添加配置项

在include/configs/x210_sd.h中添加宏定义

#define CONFIG_DRIVER_DM9000

至于如何知道这个配置项的名称,可以查看driver/net目录下的Makefile文件,配置头文件中的配置项名和Makefile中必须一致。

6.1.2 在源码中引用dm9000.c的相关函数

#ifdef CONFIC_DRIVER_DM9000dm9000_initialize();
#endif

6.1.3 重新编译uboot

顶层Makefile会根据板级配置头文件生成autoconf.mk给各Makefile包含使用

说明:概括来说,添加一个已有模块的方法就是修改板级配置头文件,然后在make的过程中会自动生成include/autoconf.mk文件供Makefile包含以决定需要编译哪些模块

6.2 添加自定义功能模块

说明:以添加farsight_net.c驱动为例

6.2.1 添加功能模块代码

在相应驱动目录下(e.g. drivers/net)添加自定义的功能模块代码

6.2.2 修改子Makefile

修改drivers/net目录下的子Makefile,添加相应驱动模块的编译选项

6.2.3 修改板级配置头文件

修改板级配置头文件include/configs/x210_sd.h,定义宏开关

6.2.4 重新编译uboot

执行到此步,我们可以生成autoconf.mk文件以验证该模块是否已被编译

可见该模块已被编译,接下来就可以在我们需要的源文件中调用farsight_net.c驱动中提供的函数。

说明:其实添加自已编写的驱动模块和添加U-boot中已有的驱动模块最大的区别就是要提供相应的驱动代码。其余修改板级配置头文件(添加自己的驱动还要修改相应驱动目录下的Makefile)并make生成autoconf.mk的过程都是一致的

S5PV210 Uboot开发与移植02:Uboot配置与编译相关推荐

  1. S5PV210 Uboot开发与移植01:Uboot概述

    目录 1. uboot概述 1.1 uboot的版本 1.1.1 官方版本 1.1.2 SoC厂商版本 1.1.3 开发板厂商版本 1.2 uboot功能框架 1.3 uboot生命周期 2. ubo ...

  2. S5PV210 Uboot开发与移植03:Uboot启动流程详解

    目录 1. start.S解析 1.1 uboot入口分析 1.2 头文件包含 1.2.1 config.h 1.2.2 version.h 1.2.3 asm/proc/domain.h 1.2.4 ...

  3. x210:uboot和系统移植扩展--uboot启动第一阶段

    从u-boot.lds中ENTRY所指定处可以看出,整个uboot程序的起始就是_start处. 不简单的头文件包含 (1)#include <config.h>.config.h是在in ...

  4. U-Boot 之四 构建过程(Kconfig 配置 + Kbuild 编译)详解

      在之前的博文 Linux 之八 完整嵌入式 Linux 环境介绍及搭建过程详解 中我们说了要一步步搭建整个嵌入式 Linux 运行环境,今天继续介绍 U-Boot 相关的内容.我所使用的硬件平台及 ...

  5. 十六.linux开发之Kernel移植——内核的配置和编译原理

    有道云笔记地址: 详情看这里链接,记录太多,就不一一排版了. http://note.youdao.com/noteshare?id=d25dbce79566963e3699574a74048154& ...

  6. Cocos2d-x项目开发时在Eclipse中配置环境编译C++

    最近在做cocos2d-x的项目开发,当然前期肯定是环境的配置工作,为了能方便的在Eclipse中编辑和编译C++部分的代码,则需要配置Eclipse的环境,之前几次犯了一些错误,导致每次打开C++的 ...

  7. x210:uboot和系统移植

    注:本文是对朱老师uboot和系统移植课程的备忘引导性笔记,主要是为了能够在学完后快速回忆起相关内容.本文主要记录了一些关键易忘性知识点并包含少量理解性内容,遵循尽量精简的原则,以尽量少的篇幅概括整个 ...

  8. Uboot UBI 的移植

    转载地址:http://blog.csdn.net/longfeey/article/details/5887007 作者 :longfeey 1.1         Uboot UBI 的移植 关于 ...

  9. [2021]Linux下C语言qrencode二维码生成库的基本使用和ARM开发板移植

    文章目录 一.前言 二.准备所用到的环境以及版本信息 1.Ubuntu和内核版本 2.gcc和g++版本 3.交叉编译gcc和g++版本 4.开发板信息 三.开发环境编译&安装qrencode ...

最新文章

  1. 激光雷达激烈竞争市场
  2. FPGA(5)数码管静态显示与动态显示
  3. Machine Learning-Introduction
  4. 2017.9.2 校内模拟赛
  5. linux中Cron定时任务系统命令详解
  6. 如何下载和安装SQL Server数据库实验助手(DEA v2.0)
  7. 开启Github之旅
  8. 七段式svpwm和5段式的区别_SVPWM实现概述
  9. Xshell官网下载地址
  10. 【机器学习|数学基础】Mathematics for Machine Learning系列之矩阵理论(15):矩阵的范数
  11. 知网哭穷赔不起1200亿,网友:收钱时咋不嫌多
  12. 华为员工能拿多少钱,揭秘一个真实的华为
  13. 将两张图片合并成一张图片
  14. Docker学习之三:docker镜像管理
  15. python 可视化 皮肤_为什么我不建议你轻易入Python的“坑”?
  16. mysql进阶教程pdf_Mysql基础到进阶精品视频教程附讲义文档 91课
  17. CAD7:构造线的使用 【TR剪掉多余的线】
  18. Pygame 官方文档 - pygame.cursors
  19. 如何做到数据分析报告(五)
  20. Elasticsearch from/size-浅分页查询-深分页 scroll-深分页search_after深度查询区别使用及应用场景

热门文章

  1. mysql 提交修改_MySQL客户端、服务器端工具、sql_mode、存储引擎修改、事务的提交和回滚、隔离级别...
  2. 单片机上电总是立即执行按键程序
  3. pandas 在某个列表中的值 筛选列_Pandas学习笔记(二)
  4. Linux中Docker部署Tomcat
  5. 用户变量和系统变量的区别_环境变量的用户变量与系统变量的区别
  6. 多目标进化优化 郑金华pdf_简化审批流程 金华首张以“告知承诺制”审批的医疗器械经营许可证发放...
  7. 转载 Assert断言知识
  8. python输出由1234组成的三位素数_编写程序,输出所有由 1 、 2 、 3 、 4 这 4 个数字组成的素数,并且在每个素数中每个数字只使用依次。_学小易找答案...
  9. iphone分辨率_QHD 分辨率有必要吗?三个理由告诉你:手机屏幕 FHD 就很好
  10. @Autowired 与@Resource的区别