一、uboot 主Makefile分析1
1、uboot version 确定(Makefile 的 24-29 行)
(1) uboot 的版本号分 3 个级别:
VERSION:主板本号
PATCHLEVEL:次版本号
SUBLEVEL:再次版本号
EXTRAVERSION : 另外附加的版本信息
这4个用 .
分隔开,共同构成了最终的版本号。
(2) Makefile 中版本号最终生成了一个变量 U_BOOT_VERSION
,这个变量记录了 Makefile 中配置的版本号。
(3) include/version_autogenerated.h
文件是编译过程中自动生成的一个文件,所以源目录中没有,但是编译过后的 uboot 中就有了。它里面的内容是一个宏定义,宏定义的值内容就是我们在 Makefile 中配置的 uboot 的版本号。
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# cat include/version_autogenerated.h
#define U_BOOT_VERSION "U-Boot 1.3.4"
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot#
(4) 验证方法:自己修改主 Makefile 中几个 Version 有关的变量,然后重新编译 uboot,然后烧录到 SD 卡中,从 SD 卡启动,然后去看启动时 uboot 打印出来的版本信息,看看变化是不是和自己的分析一致。
2、HOSTARCH 和 HOSTOS
(1) 直接在 shell 中执行 uname -m
得到 i686,得到的值其实就是你当前执行这个命令的电脑的 CPU 的版本号。
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# uname -m
i686
于是,Makefile 会把 i686 替换为 i386。
(2) shell 中的 |
叫做管道,管道的作用就是把管道前面一个运算式的输出作为后面一个的输入再去做处理,最终的输出才是我们整个式子的输出。
(3) HOSTARCH
这个名字:HOST 是主机,就是当前在做开发用的这台电脑就叫主机;ARCH 是architecture (架构)的缩写,表示 CPU 的架构。所以 HOSTARCH
就表示主机的 CPU 的架构。
(4) 这两个环境变量是主机的操作系统和主机的CPU架构,得出后保存备用,后面自然会用到。
二、uboot 主Makefile分析2
1、静默编译(50-54行)
(1) 平时默认编译时,命令行会打印出来很多编译信息。但是有时候我们不希望看到这些编译信息,就后台编译即可。这就叫静默编译。
(2) 使用方法就是编译时 make -s
,-s
会作为 MAKEFLAGS 传给 Makefile,在 50-54 行这段代码作用下 XECHO 变量就会被变成空(默认等于 echo ),于是实现了静默编译。
ifeq (,$(findstring s,$(MAKEFLAGS)))
的理解:
,
前面为空,表示空字符串。$(findstring s,$(MAKEFLAGS))
查找 Makefile 的选项参数,如果没有s(表示 slient)
,则该语句$(findstring s,$(MAKEFLAGS))
结果为空字符串。
2、2 种编译方法(原地编译和单独输出文件夹编译)
(1) 编译复杂项目,Makefile 提供 2 种编译管理方法。默认情况下是当前文件夹中的 .c 文件,编译出来的 .o 文件会放在同一文件夹下。这种方式叫原地编译。原地编译的好处就是处理起来简单。
(2) 原地编译有一些坏处:第一,污染了源文件目录。第二的缺陷就是一套源代码只能按照一种配置和编译方法进行处理,无法同时维护 2 个或 2 个以上的配置编译方式。
(3) 为了解决以上 2 种缺陷,uboot 支持单独输出文件夹方式的编译(linux kernel 也支持,而且uboot 的这种技术就是从 linux kernel 学习来的)。基本思路就是在编译时另外指定一个输出目录,将来所有的编译生成的 .o 文件或生成的其他文件全部丢到那个输出目录下去。源代码目录不做任何污染,这样输出目录就承载了本次配置编译的所有结果。
(4) 具体用法:默认的就是原地编译。如果需要指定具体的输出目录编译则有 2 种方式来指定输出目录。(具体参考 Makefile 56-76 行注释内容)
第一种:make O=输出目录
make O=/tmp/build all
第二种:export BUILD_DIR=输出目录 然后再 make
export BUILD_DIR=/tmp/build
make
如果两个都指定了(既有 BUILD_DIR 环境变量存在,又有 O=xx),则 O=xx 具有更高优先级,听他的。
Command line 'O=' setting overrides BUILD_DIR environent variable.
(5) 两种编译的实现代码在 Makefile 的78-123 行。
3、编译方法实践
实践发现,九鼎官方移植的 uboot 貌似有一些错误。。。
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# cat mk
#!/bin/sh
make distclean
make x210_sd_config
make -j4
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# make distclean
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# make x210_sd_config O=/mytmp_output
Configuring for x210_sd board...
/bin/sh: 1: cannot create /mytmp_output/board/samsung/x210/config.mk: Directory nonexistent
make: *** [x210_sd_config] Error 2
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# make O=mytmp_output distclean
rm -rf /home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/*
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# make O=mytmp_output x210_sd_config
Configuring for x210_sd board...
/bin/sh: 1: cannot create /home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/board/samsung/x210/config.mk: Directory nonexistent
make: *** [x210_sd_config] Error 2
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# mkdir -p mytmp_output/board/samsung/x210
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot#
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# make O=mytmp_output x210_sd_config
Generating /home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/include/autoconf.mk.dep
Generating /home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/include/autoconf.mk
Configuring for x210_sd board...
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot#
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# make O=mytmp_output -j8 -s
start.S:33: fatal error: regs.h: No such file or directory
compilation terminated.
nand_cp.c:44: fatal error: regs.h: No such file or directory
compilation terminated.
/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/include2/asm/hardware.h:16: fatal error: asm/arch/hardware.h: No such file or directory
compilation terminated.
usb_ohci.c:45: fatal error: regs.h: No such file or directory
compilation terminated.
interrupts.c:40: fatal error: regs.h: No such file or directory
compilation terminated.
cpu.c:36: fatal error: regs.h: No such file or directory
compilation terminated.
usbd-otg-hs.c:30: fatal error: regs.h: No such file or directory
compilation terminated.
start.S:33: fatal error: regs.h: No such file or directory
compilation terminated.
make[1]: *** [start.o] Error 1
make: *** [/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/cpu/s5pc11x/libs5pc11x.a] Error 2
make: *** Waiting for unfinished jobs....
/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/include2/asm/hardware.h:16: fatal error: asm/arch/hardware.h: No such file or directory
compilation terminated.
setup_hsmmc.c:2: fatal error: regs.h: No such file or directory
compilation terminated.
/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/include2/asm/hardware.h:16: fatal error: asm/arch/hardware.h: No such file or directory
compilation terminated.
/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/include/fastboot.h:66: fatal error: asm/arch/hardware.h: No such file or directory
compilation terminated.
start.S:33: fatal error: regs.h: No such file or directory
compilation terminated.
make[1]: *** [/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/cpu/s5pc11x/start.o] Error 1
make: *** [/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/cpu/s5pc11x/start.o] Error 2
/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/include2/asm/hardware.h:16: fatal error: asm/arch/hardware.h: No such file or directory
compilation terminated.
/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/include2/asm/hardware.h:16: fatal error: asm/arch/hardware.h: No such file or directory
compilation terminated.
make[1]: *** No rule to make target `.depend', needed by `all'. Stop.
make: *** [/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot/mytmp_output/cpu/s5pc11x/s5pc110/libs5pc110.a] Error 2
bmp_logo.c: In function ‘main’:
bmp_logo.c:71:8: warning: ignoring return value of ‘fread’, declared with attribute warn_unused_result [-Wunused-result]
fread (&data_offset, sizeof (uint16_t), 1, fp);
^
bmp_logo.c:73:8: warning: ignoring return value of ‘fread’, declared with attribute warn_unused_result [-Wunused-result]
fread (&b->width, sizeof (uint16_t), 1, fp);
^
bmp_logo.c:75:8: warning: ignoring return value of ‘fread’, declared with attribute warn_unused_result [-Wunused-result]
fread (&b->height, sizeof (uint16_t), 1, fp);
^
bmp_logo.c:77:8: warning: ignoring return value of ‘fread’, declared with attribute warn_unused_result [-Wunused-result]
fread (&n_colors, sizeof (uint16_t), 1, fp);
^
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot#
三、uboot 主Makefile分析3
1、OBJTREE、SRCTREE、TOPDIR
(1) OBJTREE:理解为:目标 Directory Tree。编译出的 .o 文件存放的目录的根目录。在默认编译下,OBJTREE 等于当前目录;在 O=xx 编译下,OBJTREE 就等于我们设置的那个输出目录。
(2) SRCTREE: 源码目录,其实就是源代码的根目录,也就是当前目录。
总结:在默认编译下,OBJTREE 和 SRCTREE 相等;在 O=xx 这种编译下,OBJTREE 和 SRCTREE 不相等。Makefile 中定义这两个变量,其实就是为了记录编译后的 .o 文件往哪里放,就是为了实现 O=xx 的这种编译方式的。
2、MKCONFIG(Makefile 的 101 行)
(1) Makefile 中定义的一个变量(在这里定义,在后面使用),它的值就是我们源码根目录下面的 mkconfig
。这个 mkconfig
是一个脚本,这个脚本就是 uboot 配置阶段的配置脚本。后面要用至少 3 节课详细讲这个配置脚本的工作。
3、include $(obj)include/config.mk(133 行)
(1) include/config.mk
不是源码自带的(你在没有编译过的源码目录下是找不到这个文件的),要在配置过程(make x210_sd_config
)中才会生成这个文件。因此这个文件的值和我们配置过程有关,是由配置过程根据我们的配置自动生成的。
(2) 我们 X210 在 iNand 情况下配置生成的 config.mk 内容为:
ARCH = arm
CPU = s5pc11x
BOARD = x210
VENDOR = samsung
SOC = s5pc110
(3) 我们在下一行(134行)export 导出了这 5 个变量作为环境变量。所以这两行加起来其实就是为当前 makefile 定义了 5 个环境变量而已。之所以不直接给出这 5 个环境变量的值,是因为我们希望这 5 个值是可以被人很容易的、集中的配置的。
(4) 这里的配置值来自于 2589 行那里的配置项。如果我们要更改这里的某个配置值要到 2589 行那里调用 MKCONFIG 脚本传参时的参数。
4、ARCH CROSS_COMPILE
(1) 接下来有 2 个很重要的环境变量。一个是 ARCH
,上面导出的,值来自于我们的配置过程,它的值会影响后面的 CROSS_COMPILE
环境变量的值。ARCH 的意义是定义当前编译的目标 CPU 的架构。
(2) CROSS_COMPILE
是定义交叉编译工具链的前缀的。定义这些前缀是为了在后面用(用前缀加上后缀来定义编译过程中用到的各种工具链中的工具)。我们把前缀和后缀分开还有一个原因就是:在不同 CPU 架构上的交叉编译工具链,只是前缀不一样,后缀都是一样的。因此定义时把前缀和后缀分开,只需要在定义前缀时区分各种架构即可实现可移植性。
(3) CROSS_COMPILE
在 136-182 行来确定。CROSS_COMPILE 是被 ARCH 所确定的,只要配置了ARCH=arm
,那么我们就只能在 ARM 的那个分支去设置 CROSS_COMPILE
的值。这个设置值只要能保证找到那个交叉编译工具链即可,不一定非得是全路径的,相对路径也可以。(如果已经将工具链导出到环境变量,并且设置了符号链接,这样 CROSS_COMPILE = arm-linux-
就可以)
(4)实际运用时,我们可以在 Makefile 中去更改设置 CROSS_COMPILE
的值,也可以在编译时用 make CROSS_COMPILE=xxxx
来设置,而且编译时传参的方法可以覆盖 Makefile 里面的设置。
四、uboot 主Makefile分析4
1、$(TOPDIR)/config.mk(主 Makefile 的 185 行)
2、编译工具定义(config.mk 94-107行)
3、包含开发板配置项目(config.mk, 112行)
(1) autoconfig.mk
文件不是源码提供的,是配置过程自动生成的。
(2) 这个文件的作用就是用来指导整个 uboot 的编译过程。这个文件的内容其实就是很多 CONFIG_
开头的宏(可以理解为变量),这些宏/变量会影响我们 uboot 编译过程的走向(原理就是条件编译)。在 uboot 代码中有很多地方使用条件编译进行编写,这个条件编译是用来实现可移植性的。(可以说 uboot 的源代码在很大程度来说是拼凑起来的,同一个代码包含了各种不同开发板的适用代码,用条件编译进行区别。)
(3) 这个文件不是凭空产生的,配置过程也是需要原材料来产生这个文件的。原材料在源码目录的 inlcude/configs/xxx.h
头文件。(X210 开发板中为 include/configs/x210_sd.h
)。这个 h 头文件里面全都是宏定义,这些宏定义就是我们对当前开发板的移植。每一个开发板的移植都对应这个目录下的一个头文件,这个头文件里每一个宏定义都很重要,这些配置的宏定义就是我们移植 uboot 的关键所在。
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# ls include/configs/
x210_nand.h x210_sd.h
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot# cat include/configs/x210_sd.h | more
/*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
* Gary Jennejohn <gj@denx.de>
* David Mueller <d.mueller@elsoft.ch>
*
* Configuation settings for the SAMSUNG SMDK6400(mDirac-III) board.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#ifndef __CONFIG_H
#define __CONFIG_H
//#define FPGA_SMDKC110
//定义CONFIG_CHECK_X210CV3,则为工装检测模式,不定义,为正常启动模式
//#define CONFIG_CHECK_X210CV3
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_MPAD 1 //lxg added
#define CONFIG_S5PC110 1 /* in a SAMSUNG S3C6410 SoC */
#define CONFIG_S5PC11X 1 /* in a SAMSUNG S3C64XX Family */
#define CONFIG_X210 1
#define CONFIG_MCP_SINGLE 1
#define CONFIG_EVT1 1 /* EVT1 */
//#define CONFIG_SMDKV210_REV02 1 /* Rev 0.2 and PMIC Type is MAX8998 */
#define CONFIG_FASTBOOT 1
//#define CONFIG_FUSED 1 /* Fused chip */
//#define CONFIG_SECURE_BOOT 1 /* secure booting */
#define CONFIG_SW_WORKAROUND 1 /* Software around */
#if defined(CONFIG_SW_WORKAROUND)
#define CONFIG_CHECK_MPLL_LOCK 1 /* Check MPLL is locked */
#endif
#if defined(CONFIG_SECURE_BOOT)
#define CONFIG_SECURE_KERNEL_BASE 0x20008000
#define CONFIG_SECURE_KERNEL_SIZE 0x00271000
#define CONFIG_SECURE_ROOTFS_BASE 0x30A00000
#define CONFIG_SECURE_ROOTFS_SIZE 0x0013D000
#endif
#define BOOT_ONENAND 0x1
#define BOOT_NAND 0x2
#define BOOT_MMCSD 0x3
#define BOOT_NOR 0x4
#define BOOT_SEC_DEV 0x5
#define AT070TN92 1
#define VGA_800X600 2
#define VGA_1024X768 3
#define TRULY043 4
#define VGA_1440X900 5
#define VGA_1280X1024 6
#define DISP_MODE AT070TN92
//#define DISP_MODE TRULY043
//#define DISP_MODE VGA_800X600
//#define DISP_MODE VGA_1024X768
//#define DISP_MODE VGA_1440X900
//#define DISP_MODE VGA_1280X1024
/* skip to load BL2 */
//#define FAST_BOOT 1
#define MEMORY_BASE_ADDRESS 0x30000000
//#define MEMORY_BASE_ADDRESS 0x20000000
#define MEMORY_BASE_ADDRESS2 0x40000000
/* input clock of PLL */
#define CONFIG_SYS_CLK_FREQ 24000000 /* the SMDK6400 has 24MHz input clock */
#define CONFIG_ENABLE_MMU
#ifdef CONFIG_ENABLE_MMU
#define virt_to_phys(x) virt_to_phy_smdkc110(x)
#else
#define virt_to_phys(x) (x)
#endif
#define CONFIG_MEMORY_UPPER_CODE
#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
#define CONFIG_INCLUDE_TEST
#define CONFIG_ZIMAGE_BOOT
#define CONFIG_IMAGE_BOOT
#define BOARD_LATE_INIT
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_CMDLINE_TAG
#define CONFIG_INITRD_TAG
/*
* Architecture magic and machine type
*/
#define MACH_TYPE 2456
#define UBOOT_MAGIC (0x43090000 | MACH_TYPE)
/* Power Management is enabled */
#define CONFIG_PM
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_DISPLAY_BOARDINFO
root@ubuntu:/home/aston/workspace/uboot_bsp/uboot_jiuding/uboot#
五、uboot 主Makefile分析5
1、链接脚本(config.mk 142-149 行)
(1) 如果定义了 CONFIG_NAND_U_BOOT
宏,则链接脚本叫 u-boot-nand.lds ,如果未定义这个宏则链接脚本叫 u-boot.lds
。
(2) 从字面意思分析,即可知:CONFIG_NAND_U_BOOT
是在 Nand 版本情况下才使用的,我们使用的 X210 都是 iNand 版本的,因此这个宏没有的。
(3) 实际在 board\samsung\x210
目录下有 u-boot.lds
,这个就是链接脚本。我们在分析 uboot 的编译链接过程时就要考虑这个链接脚本。
2、TEXT_BASE(config.mk 156-158行)
(1) Makefile 中在配置 X210 开发板时,在 board/samsung/x210
目录下生成了一个文件 config.mk
,其中的内容就是:TEXT_BASE = 0xc3e00000
相当于定义了一个变量。
(2) TEXT_BASE
是将来我们整个 uboot 链接时指定的链接地址。因为 uboot 中启用了虚拟地址映射,因此这个 C3E00000 地址就等于 0x23E00000
(也可能是 33E00000 具体地址要取决于 uboot 中做的虚拟地址映射关系)。
(3) 回顾裸机中讲的链接地址的问题,再想想 dnw 方式先下载 x210_usb.bin 然后再下载 uboot.bin 时为什么第二个地址是 23E00000 .
3、自动推导规则(config.mk 239-256行)
(1) 我们在讲 Makefile 时提到过自动推导规则,具体理解可以参考《跟我一起学Makefile》
六、uboot 主Makefile分析6
(1) 291 行出现了整个主 Makefile 中第一个目标 all(也就是默认目标,我们直接在 uboot 根目录下 make 其实就等于 make all,就等于 make 这个目标)
(2) 目标中有一些比较重要的。譬如:u-boot 是最终编译链接生成的 elf 格式的可执行文件。
(3) unconfig 字面意思来理解就是未配置。这个符号用来做为我们各个开发板配置目标的依赖。目标是当我们已经配置过一个开发板后再次去配置时还可以配置。
(4) 我们配置开发板时使用:make x210_sd_config
,因此分析 x210_sd_config 肯定是主 Makefile 中的一个目标。
七、uboot 配置过程详解1
1. mkconfig 脚本的 6 个参数
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$(@:_config=) arm s5pc11x x210 samsung s5pc110
x210_sd_config
里的 _config
部分用空替换,得到:x210_sd
,这就是第一个参数,所以:
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
所以,$# = 6
2. 第 23 行
其实就是看 BOARD_NAME 变量是否有值,如果有值就维持不变;如果无值就给他赋值为 $1
,实际分析结果:BOARD_NAME=x210_sd
。
3. 第25行
如果 $# 小于 4,则 exit 1(mkconfig 脚本返回 1)
4. 第26行
如果 $# 大于6,则也返回 1.
所以:mkconfig 脚本传参只能是 4、5、6,如果大于 6 或者小于 4 都不行。
5. 第33行到第118行
都是在创建符号链接。为什么要创建符号链接?这些符号链接文件的存在就是整个配置过程的核心,这些符号链接文件(文件夹)的主要作用是给头文件包含(#include “xxx”)等过程提供指向性连接。根本目的是让uboot 具有可移植性。
uboot 可移植性的实现原理:在 uboot 中有很多彼此平行的代码,各自属于各自不同的架构/CPU/开发板,我们在具体到一个开发板的编译时,用符号链接( ln
命令) 的方式提供一个具体的名字的文件夹供编译时使用。这样就可以在配置的过程中通过不同的配置使用不同的文件,就可以正确的包含正确的文件。
6. 创建的符号链接
第一个:在 include 目录下创建 asm
文件,指向 asm-arm
。(46-48行)
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
第二个:在 inlcude/asm-arm
下创建一个 arch
文件,指向 include/arch-s5pc110
。
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
第三个:在 include 目录下创建 regs.h
文件,指向 include/s5pc110.h
; 删除上面第二个符号链接。
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
第四个:在 inlcude/asm-arm
下创建一个 arch
文件,指向 include/asm-arm/arch-s5pc11x
。
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
第五个:在 include/asm-arm
下创建一个 proc
文件,指向 include/asm-arm/proc-armv
.
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
总结:一共创建了 4 个符号链接。这 4 个符号链接将来在写代码过程中,头文件包含时非常有用。譬如一个头文件包含可能是:#include <asm/xx.h>
include/asm -> asm-arm
include/regs.h -> s5pc110.h
include/asm-arm/arch -> arch-s5pc11x
include/asm-arm/proc -> proc-armv
八、uboot 配置过程详解2
1. 创建 include/config.mk 文件(mkconfig文件 123-129 行)
2. 创建 include/config.mk
创建 include/config.mk
文件是为了让主 Makefile 在第 133 行去包含的(详解见第三节 uboot 《主Makefile分析 3》 的第 3 点 include $(obj)include/config.mk(133 行))。
3. 思考: uboot 的配置和编译过程的配合
编译的时候需要 ARCH=arm、CPU=xx 等这些变量来指导编译,配置的时候就是为编译阶段提供这些变量。那为什么不在 Makefile 中直接定义这些变量去使用,而要在 mkconfig 脚本中创建 config.mk 文件然后又在Makefile 中 include 这些文件呢?
4. 理解这些脚本时,时刻要注意自己当前所处的路径。
5. 创建(默认情况)/追加(make -a时追加)include/config.h 文件(mkconfig 文件的 134-141 行)。
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
6.
# Parameters:
# Target Architecture CPU Board [VENDOR] [SOC]
$1: x210_sd $2: arm $3: s5pc11x $4: x210 $5: samsumg $6: s5pc110
这个文件里面的内容就一行 #include <configs/x210_sd.h>
,这个头文件是我们移植 x210 开发板时,对开发板的宏定义配置文件。这个文件是我们移植 x210 时最主要的文件。
7.
x210_sd.h
文件会被用来生成一个 autoconfig.mk
文件,这个文件会被主 Makefile 引入,指导整个编译过程(详情查看第四节《uboot 主Makefile分析4》第 3 点 包含开发板配置项目(config.mk, 112行))。这里面的这些宏定义会影响我们对 uboot
中大部分 .c 文件中一些条件编译的选择。从而实现最终的可移植性。
注意:uboot 的整个配置过程,很多文件之间是有关联的(有时候这个文件是在那个文件中创建出来的;有时候这个文件被那个文件包含进去;有时候这个文件是由那个文件的内容生成的决定的)。
注意:uboot 中配置和编译过程,所有的文件或者全局变量都是字符串形式的(不是指的 C 语言字符串的概念,指的是都是字符组成的序列)。这意味着我们整个 uboot 的配置过程都是字符串匹配的,所以一定要细节,注意大小写,要注意不要输错字符,因为一旦错一个最后会出现一些莫名其妙的错误,很难排查,这个是 uboot 移植过程中新手来说最难的地方。
总结:
涉及到的文件路径:
uboot/Makefile
uboot/mkconfig
uboot/include/config.h
uboot/include/config.mk
九、uboot 的链接脚本
详情参考第五节 uboot 主Makefile分析5。
(1) uboot 的链接脚本,和我们之前裸机中的链接脚本并没有本质区别,只是复杂度高一些,文件多一些,使用到的技巧多一些。
(2) ENTRY(_start)
用来指定整个程序的入口地址。所谓入口地址就是整个程序的开头地址,可以认为就是整个程序的第一句指令。有点像 C 语言中的 main。
(3) 之前在裸机中告诉大家,指定程序的链接地址有 2 种方法:一种是在 Makefile 中 ld 的 flags 用 -Ttext 0x20000000
来指定;第二种是在链接脚本的 SECTIONS 开头用 .=0x20000000
来指定。两种都可以实现相同效果。其实,这两种技巧是可以共同配合使用的,也就是说既在链接脚本中指定,也在 ld flags 中用 -Ttext
来指定。两个都指定以后以 -Ttext
指定的为准。
(4) uboot 的最终链接起始地址,就是在 Makefile 中用 -Ttext
来指定的,具体参见第五节《uboot 主Makefile分析5》第 2点 TEXT_BASE,注意 TEXT_BASE 变量。最终来源是 Makefile 中配置对应的命令中,在 make xxx_config
时得到的。
(5) 在代码段中注意文件排列的顺序。指定必须放在前面部分的那些文件就是那些必须安排在前 16KB 内的文件,这些文件中的函数在前 16KB 会被调用。在后面第二部分( 16KB 之后)中调用的程序,前后顺序就无所谓了。
(6)链接脚本中除了 .text .data .rodata .bss
段等编译工具自带的段之外,编译工具还允许我们自定义段。譬如 uboot 中的 .u_boot_cmd
段就是自定义段。自定义段很重要。
源自朱有鹏老师.