首页 未命名正文

linux编程_u-boot设置和编译历程详解

云返利网 未命名 2020-05-26 09:07:38 15 0

备注:剖析的是OK210开发板自带的uboot_smdkv210,可能有些部分和其他版本不太一样,然则原理都类似。

编译u-boot的步骤

make forlinx_linux_config
make

首先天生设置文件,然后编译源码,依次看看这些下令都干了些什么事情

设置历程

#forlinx add
forlinx_linux_config :  unconfig
    @$(MKCONFIG) $(@:_config=) arm s5pc11x smdkc110 samsung s5pc110 linux
    @echo "TEXT_BASE = 0xcc800000" > $(obj)board/samsung/smdkc110/config.mk

消灭上一次设置的文件

此目的依赖unconfig目的,因此先挪用unconfig的下令,下令如下

unconfig:
    @rm -f $(obj)include/config.h $(obj)include/config.mk \
        $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp \
        $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep \
        $(obj)board/$(VENDOR)/$(BOARD)/config.mk

执行的操作主要是删除上一次设置天生的设置文件。

最先设置操作

在Makefile中以@开头的下令示意,在下令执行的时刻不在终端上打印信息。
$(MKCONFIG)变量在Makefile的101行有界说,如下:

MKCONFIG    := $(SRCTREE)/mkconfig
export MKCONFIG

$(@:_config=)这句话的意思是将 forlinx_linux_config的_config用空缺取代只剩下forlinx_linux,
其中$(srcfiles:xxx=ccc)是Makefile的规则,用等号后边的ccc替换srcfiles中等号前边的xxx,
$(@) = $@ 代表目的,即在下令行输入的make forlinx_linux_config中的forlinx_linux_config。
因此@$(MKCONFIG) $(@:_config=) arm s5pc11x smdkc110 samsung s5pc110 linux
的意思就是挪用u-boot根目录的mkconfig剧本并将 forlinx_linux arm s5pc11x smdkc110 samsung s5pc110 linux作为参数传递给剧本。

mkconfig文件

在文件的头部的注释已经交接了文件的作用和挪用的花样

# Script to create header files and links to configure
# U-Boot for a specific board.
#
# Parameters: Target Architecture CPU Board [VENDOR] [SOC]
#

$0 = mkconfig (剧本文件名)
$1 = Target (目的) forlinx_linux   
$2 = Architecture  (架构) arm 
$3 = CPU   (CPU型号)s5pc11x 
$4 = Board  (开发板名)smdkc110 
$5 = VENDOR (生产商)samsung 
$6 = SOC (芯片名)s5pc110 

最后一个linux是OK210的工程师自己添加的用于区别Android版本的内核和linux的内核,没有什么实质用途。(小我私家预测)

APPEND=no   # Default: Create new config file
BOARD_NAME=""   # Name to print in make output

while [ $# -gt 0 ] ; do
    case "$1" in
    --) shift ; break ;;
    -a) shift ; APPEND=yes ;;
    -n) shift ; BOARD_NAME="${1%%_config}" ; shift ;;
    *)  break ;;
    esac
done

接下来界说了两个变量为后边设置历程做准备,用途注释已经写的很清晰,APPEND=no是示意需要重新建立设置文件的标志。
再然后循环:若是参数个数大于零就执行循环,然后再循环里判断第一个参数(剧本可以有参数选项),很明显都不相符,以是直接跳出循环。

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"

[ $# -lt 4 ] && exit 1
[ $# -gt 7 ] && exit 1

echo "Configuring for ${BOARD_NAME} board..."

将BOARD_NAME赋值为forlinx_linux,然后判断参数个数,小于4大于7(一样平常情形为大于6应该照样OK210的工程师修改了)就直接退出剧本,放弃执行。

建立软毗邻

接下来建立许多链接文件,这些操作是mkconfig剧本的主要事情,主要建立的链接文件如下:

if [ "$SRCTREE" != "$OBJTREE" ] ; then
    mkdir -p ${OBJTREE}/include
    mkdir -p ${OBJTREE}/include2
    cd ${OBJTREE}/include2
    rm -f asm
    ln -s ${SRCTREE}/include/asm-$2 asm
    LNPREFIX="../../include2/asm/"
    cd ../include
    rm -rf asm-$2
    rm -f asm
    mkdir asm-$2
    ln -s asm-$2 asm
else
    cd ./include
    rm -f asm
    ln -s asm-$2 asm
fi

./include/asm --> asm-$2 (asm-arm)

# create link for s5pc11x SoC
if [ "$3" = "s5pc11x" ] ; then
        rm -f regs.h
        ln -s $6.h regs.h
        rm -f asm-$2/arch
        ln -s arch-$3 asm-$2/arch
fi

regs.h --> $6.h (s5pc110.h)
asm-$2/arch --> arch-$3(arch-s5pc11x)

u-boot支持许多种开发板,许多种类型的CPU,以是要有一种通用得设置方式来利便移植;
u-boot甚至linux内核都采用了这种方式:针对差别的处置器或者板子都有自己的头文件和文件夹,然则真正的编译历程却不直接使用,而是在设置阶段建立这些头文件或者文件夹的软毗邻,并命名为一种通用的名字。在编译的时刻通过这些软毗邻接见真正需要的文件。
例如,在u-boot的include目录下有一个asm的目录,此目录就是在设置完后天生的一个软毗邻,当设置的是arm架构时,此文件是asm-arm的软毗邻。

建立make时用到的包罗文件 config.mk

#
# Create include file for Make
#
echo "ARCH = $2" >  config.mk
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk

[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk

[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk

建立开发板特定的头文件 config.h

#
# Create board specific header file
#
if [ "$APPEND" = "yes" ]   # Append to existing config file
then
    echo >> config.h
else
    > config.h      # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h


#forlinx add 
if [ "$7" = "linux" ]
then
    echo "#define CONFIG_LINUX_FORLINX 1" >>config.h
else
    echo "#define CONFIG_ANDROID_FORLINX 1" >>config.h
fi

#echo "#include <configs/$1.h>" >>config.h
#forlinx change for linux and android 
echo "#include <configs/smdkv210single.h>" >>config.h

由于上边已经把APPEND设置为NO,以是执行> config.h 即建立config.h头文件,并向config.h中写入
/* Automatically generated - do not edit */
"#define CONFIG_LINUX_FORLINX 1
以及#include <configs/smdkv210single.h>
同样是OK210的工程师加入的
#include <configs/$1.h>#include <configs/forlinx_linux.h>
注重:建立软毗邻的操作全都是在u-boot根目录的include子目录中执行的。

设置剧本mkconfig竣事。

mkconfig剧本小结

一共建立了三个毗邻文件,
./include/asm --> asm-$2 (asm-arm)
regs.h --> $6.h (s5pc110.h)
asm-$2/arch --> arch-$3(asm-arm -> arch-s5pc11x)
以及include/config.mk和include/config.h,其中include/config.mk文件中记录着u-boot的版本信息,include/config.h中包罗了 configs/$1.h,此文件里记录着是许多许多以CONFIG_开头的宏,是开发板u-boot的主设置信息。

主Makefile

版本号相关

VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION =
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h

Makefile刚最先的时刻仍然是界说当前使用的u-boot的版本,此版本和linux内核版本类似都由多个字段组成,各字段意义如下:
VERSION : 主版本号
PATCHLEVEL :次版本号
SUBLEVEL : 修正版本号
EXTRAVERSION:扩展版本号 (可以自己界说,用于区别自己移植的版本号 )
U_BOOT_VERSION 就是以上几个字段的组合字符串。
VERSION_FILE 保留的是u-boot版本号的文件,其中obj变量在后边界说。version_autogenerated.h文件也在后边天生(此文件不是u-boot源码目录自己有的文件,是由设置历程自动天生的),其内容如下:
#define U_BOOT_VERSION "U-Boot 1.3.4"

HOSTARCH := $(shell uname -m | \
    sed -e s/i.86/i386/ \
        -e s/sun4u/sparc64/ \
        -e s/arm.*/arm/ \
        -e s/sa110/arm/ \
        -e s/powerpc/ppc/ \
        -e s/ppc64/ppc/ \
        -e s/macppc/ppc/)

HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
        sed -e 's/\(cygwin\).*/cygwin/')

export  HOSTARCH HOSTOS

这一段话是检测编译时主机的架构和操作系统,其中使用了sed工具举行了响应的处置,
sed -e s/i.86/i386/ 意思就是不管是i686\i386照样i586,都用i386替换。
tr '[:upper:]' '[:lower:]'的意思是将操作系统名字中可能存在的大写字母所有转换为小写字母。
笔者用的是i686的Linux操作系统,因此执行的结果是 HOSTARCH=i386, HOSTOS=linux,
最后挪用export导出为环境变量供其他地方使用。

静默编译

所谓静默编译就是在编译的时刻不打印任何信息(错误和忠告信息除外)。

# Allow for silent builds
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif

这段代码的意思是,在执行make时输入的参数中搜索’s’,若是有的话就给XECHO赋值为echo,否则就赋值为空,然后在其他地方用XECHO来打印信息,就实现了是否启用静默编译。
make -s就启用了静默编译。

指定目录编译

u-boot除了支持静默编译外还支持在差别目录举行编译,即将设置历程天生的文件以及编译发生的中心文件全都输出到一个指定的目录,从而制止污染源码目录。
从56-76的注释中可以看出有两种方式指定
1、在下令行通过make O=/tmp/build 指定输出目录为/tmp/build
2、指定BUILD_DIR=/tmp/build环境变量
注重:通过阅读根目录下的README文件,若是要在其他目录举行编译,在设置阶段和编译阶段都要指定输出的目录位置,如下:

1. Add O= to the make command line invocations:

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

2. Set environment variable BUILD_DIR to point to the desired location:

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

Makefile中的78-93行完成事情就是,若是指定了O参数,就判断O后边指定的目录存在不存在,若是不存在就建立,并把指定的路径赋值给BUILD_DIR变量 ——
然后就是给几个下边变量赋值

OBJTREE     := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))    //输出目录
SRCTREE     := $(CURDIR)                                                            //源码目录
TOPDIR      := $(SRCTREE)                                                                //顶层目录(源码根目录)
LNDIR       := $(OBJTREE)                                                                //链接目录
export  TOPDIR SRCTREE OBJTREE                                               //导出为环境变量

MKCONFIG    := $(SRCTREE)/mkconfig                                               //mkconfig设置剧本的路径
export MKCONFIG                                                                                   //导出为环境变量

然后是编译要用的$(obj) 和$(src)

# $(obj) and (src) are defined in config.mk but here in main Makefile
# we also need them before config.mk is included which is the case for
# some targets like unconfig, clean, clobber, distclean, etc.
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src

若是编译输出目录和源码目录不是通一个目录,就将源码目录的路径赋值给$(src),将输出的路径赋值给$(obj)。
否则就置空。

确定目的架构和交织编译工具

从124行最先一直到182行都是在确定要使用的交织编译工具。
其中在133行的时刻导入了一个设置文件

# load ARCH, BOARD, and CPU configuration
include $(obj)include/config.mk
export  ARCH CPU BOARD VENDOR SOC

$(obj)include/config.mk此文件在执行mkconfig剧本的时刻天生,里边保留着开发板以及CPU的型号和架构信息

ARCH = arm
CPU = s5pc11x
BOARD = smdkc110
VENDOR = samsung
SOC = s5pc110

然后再将这些信息导出为环境变量。

ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-linux-
endif
export  CROSS_COMPILE

再然后就是指定交织编译工具,并将CROSS_COMPILE导出为环境变量了。

此外
在185行导入了U-boot根目录下的config.mk文件

# load other configuration
include $(TOPDIR)/config.mk

此文件主要完成以下事情
1、界说交织编译工具,例如 CC=arm-linux-gcc, LD=arm-linux-ld等等。
2、导入设置文件
$(OBJTREE)/include/autoconf.mk
$(TOPDIR)/$(ARCH)_config.mk
$(TOPDIR)/cpu/$(CPU)/config.mk
$(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk

$(VENDOR)/$(BOARD)
$(TOPDIR)/board/$(BOARDDIR)/config.mk
3、编译选项相关的一大坨,一样平常不用管
4、make的自动推导规则

界说u-boot编译的目的

OBJS是编译时的目的
LIBS是依赖的库
此外另有GCC的库等等

ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) $(U_BOOT_ONENAND) $(obj)u-boot.dis
ifeq ($(ARCH),blackfin)
ALL += $(obj)u-boot.ldr

第一个目的all

all:  $(ALL)

【关于云返利网】

云返利网是阿里云、腾讯云、华为云产品推广返利平台,在各个品牌云产品官网优惠活动之外,云返利网还提供返利。您可以无门槛获得阿里云、华为云、腾讯云所有产品返利,在官网下单后就可以领取,无论是自己用、公司用还是帮客户采购,您个人都可以获得返利。云返利网的目标是让返利更多、更快、更简单!详情咨询13121395187(微信同号)