Z-Turn-Lite Board Linux开发-u-boot开篇
Z-Turn-Lite Board 光盘中提供的软件资源:
FSBL
(该段转载至http://www.openhw.org/module/forum/thread-657600-1-1.html)
在zynq上运行程序的时候,加载过程中肯定需要用到一个文件,那就是fsbl,fsbl的全称为first stage boot loader,从字面上就能够看出这是zynq启动第一阶段的加载程序,经过了fsbl这一阶段,后面系统才能够运行裸奔程序或者是引导操作系统的u-boot。启动过程如下图:(在上图中,Boot Rom是直接固化在zynq硬件中的,开发者无法更改,fsbl.elf可以在Xilinx的SDK中进行修改。)
FSBL代码分析
创建fsbl工程步骤详见Z-Turn Lite Board入门指导手册9.1节(54页)产生Boot Loader(fsbl)
打开fsbl_bsp->ps7_cortexa9_0->libsrc->standalone_v6_2->src->asm_vectors.S
用途:This file contains the initial vector table for the Cortex A9 processor
#include "xil_errata.h" ;引入头文件xil_errata.h
#define __ARM_NEON__ 1 ;定义__ARM_NEON__为1
声明代码段,位于地址0处。上电后,cpu自动执行地址0处指令,跳转到_boot标签处。
.org 0 .text .globl _vector_table .section .vectors _vector_table:B _bootB UndefinedB SVCHandlerB PrefetchAbortHandlerB DataAbortHandlerNOP /* Placeholder for address exception vector*/B IRQHandlerB FIQHandler
后面代码定义的是中断处理服务子程序,在此不进行解析。详情见XXX,等段时间来填坑。
跳转到boot.S(The boot code performs minimum configuration which is required for an application to run starting from processor’s reset state.) _boot代码会对系统做初始化,当它执行完后,会跳转到C语言版本后续启动代码。详细初始化细节以后在填坑。
b _start /* jump to C startup code */and r0, r0, r0 /* no op */ .Ldone: b .Ldone /* Paranoia: we should never get here */
_start标号位于xil-crt0.S中,仍然对系统进行设置,第一句话就是跳转到__cpu_init去执行cpu初始化。
_start:bl __cpu_init /* Initialize the CPU first (BSP provides this) */mov r0, #0
__cpu_init在cpu_init.S文件(This file contains CPU specific initialization. Invoked from main CRT)中,详细内容如下:
.text .global __cpu_init .align 2 __cpu_init: /* Clear cp15 regs with unknown reset values */mov r0, #0x0mcr p15, 0, r0, c5, c0, 0 /* DFSR */mcr p15, 0, r0, c5, c0, 1 /* IFSR */mcr p15, 0, r0, c6, c0, 0 /* DFAR */mcr p15, 0, r0, c6, c0, 2 /* IFAR */mcr p15, 0, r0, c9, c13, 2 /* PMXEVCNTR */mcr p15, 0, r0, c13, c0, 2 /* TPIDRURW */mcr p15, 0, r0, c13, c0, 3 /* TPIDRURO */ /* Reset and start Cycle Counter */mov r2, #0x80000000 /* clear overflow */mcr p15, 0, r2, c9, c12, 3mov r2, #0xd /* D, C, E */mcr p15, 0, r2, c9, c12, 0mov r2, #0x80000000 /* enable cycle counter */mcr p15, 0, r2, c9, c12, 1bx lr .end
在_start的末尾,BSP终于完成了自己的工作,PS将跳转到main函数开始执行。如下:
/* make sure argc and argv are valid */mov r0, #0mov r1, #0/* Let her rip */bl main
终于系统进入了FSBL阶段。我们打开fsbl—>src文件夹,然后打开main.c文件(The main file for the First Stage Boot Loader (FSBL).):
main函数首先执行的是ps7_init()函数,ps7_init函数其实执行了mio,pll,clock,ddr和某些外设的初始化。
/** PCW initialization for MIO,PLL,CLK and DDR*/Status = ps7_init();if (Status != FSBL_PS7_INIT_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"PS7_INIT_FAIL : %s\r\n",getPS7MessageInfo(Status));OutputStatus(PS7_INIT_FAIL);/** Calling FsblHookFallback instead of Fallback* since, devcfg driver is not yet initialized*/FsblHookFallback();}
接下来的一些初始化不详细表述,但是把函数注释列出:
- Unlock SLCR for SLCR register write
- Flush the Caches
- Disable Data Cache
- Register the Exception handlers
- Print the FSBL Banner
- DDR Read/write test, PCAP initialization and Get the Silicon Version
- Check if WDT Reset has occurred or not and Initialize the Watchdog Timer
- Get PCAP controller settings
- Check for AES source key
- Store FSBL run state in Reboot Status Register
- Read bootmode register and BOOT MODE initialization
FSBL将根据启动状态寄存器判断是采用的哪种启动模式。有四种启动模式,分别是QSPI,NOR,JTAG,SD卡等模式。每种模式都有一段独立的代码,举个例子,我们看SD卡模式的执行代码:
/** SD BOOT MODE */ #if defined(XPAR_PS7_SD_0_S_AXI_BASEADDR) || defined(XPAR_XSDPS_0_BASEADDR if (BootModeRegister == SD_MODE) {fsbl_printf(DEBUG_GENERAL,"Boot mode is SD\r\n");/** SD initialization returns file open error or success*/Status = InitSD("BOOT.BIN");if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"SD_INIT_FAIL\r\n");OutputStatus(SD_INIT_FAIL);FsblFallback();}MoveImage = SDAccess;fsbl_printf(DEBUG_INFO,"SD Init Done \r\n");} else
系统先对SD卡初始化,并且要求SD卡中必须要有BOOT.BIN文件。如果没有,那么从SD卡启动板子就会失败。这也是为什么我们生成启动镜像必须命名为BOOT.BIN的原因。
暂时先粗浅地分析到这里,以后再分析。https://blog.csdn.net/asmartkiller/article/details/84072643
U-Boot中的二级程序加载器(secondary program loader,即SPL)的分析,以后会单独拿出来分析分析。
https://www.cnblogs.com/windtail/p/8302470.html
u-boot代码分析
VERSION = 2013
PATCHLEVEL = 10
SUBLEVEL =
EXTRAVERSION =
u-boot版本号为2013.10,相应版本可以去https://github.com/Xilinx/u-boot-xlnx下载。
u-boot由下面文件夹构成,其中每个文件夹都实现一个对应的功能:
- api: 相关的api函数,如输出字符函数等。
- arch: 与特定CPU架构相关的目录。在该目录下,u-boot所支持的不同CPU架构都有一个单独的子目录对应。典型地,arch文件夹下名字为arm的子目录就是Zynq-7000 Soc内置CPU架构目录。
- board: 和开发板相关的目录。每类开发板都以一个子目录出现在当前目录中,比如/board/Xilinx/zynq子目录存放与该开发板相关文件。
- common: 实现uboot命令行下所支持的命令。在该目录下,每一条命令对应一个独立的文件。
- disk: 提供对磁盘的支持。
- doc: 文档目录
- drivers: 在该目录下保存着u-boot所支持的设备驱动程序。典型地,各种网卡、支持CFI的Flash存储器、串口和USB等
- api: 相关的api函数,如输出字符函数等。
- dts:
- examples:
- fs: 对于Ubuntu所支持的文件系统,在该目录下都有一个文件夹与之相对应。典型地,u-boot现在支持cramfs、jffs2和ext4等文件系统。
- include: 该目录中保存着u-boot所使用的头文件,对各种硬件平台支持的汇编文件、系统的配置文件及对文件系统支持的文件。该目录下configs目录有与开发板相关的配置头文件,如zynq_common.h、zynq_zturn.h等与开发板相关的配置文件。
- lib: 该目录中保存着与体系结构相关的库文件。
- Licenses:
- nand_spl:
- net: 该目录下保存着与网络协议栈相关的代码。典型地,BOOTP协议、TFTP协议、RARP协议和NFS文件系统的实现。
- post:
- spl:
- test:
- tools: 该目录下保存着用于生成u-boot的工具,包括mkimage、crc、Makefile、boards.cfg配置文件。
CREDITS和CHANGELOG文件保存了各个模块贡献者的名字,CHANGELOG不在源码在,需要通过make CHANGELOG来生成。
该段代码在Makefile文件中,CHANGELOG通过git log命令生成。
.PHONY : CHANGELOG
CHANGELOG:git log --no-merges U-Boot-1_1_5.. | \unexpand -a | sed -e 's/\s\s*$$//' > $@
boards.cfg保存的是支持的芯片架构、开发板和维护者。boards.cfg file lists board maintainers.
CPU域的格式:cpu[:spl_cpu] 在SPL编译过程中,spl_cpu指定了make变量CPU会被设置为该值。
options域格式:<board config name>[:comma separated config options] 每个option也有格式(值默认为1): option[=value] 。比如FOO:HAS_BAR,BAZ=64,表示的是include/configs/FOO.h将被使用,其中会添加预定义#define CONFIG_HAS_BAR 1和#define CONFIG_BAZ 64
脚本tools/reformat.py可用于将boards.cfg中的记录格式化。可以在shell中这样执行脚本tools/reformat.py -i -d ‘-’ -s 8 <boards.cfg >boards0.cfg && mv boards0.cfg boards.cfg
也可以直接从vim中调用
:%!tools/reformat.py -i -d ‘-’ -s 8
README文件说明了使用u-boot的过程。在软件配置部分有两类配置变量:
- Configuration _OPTIONS_ 这是由用户选择并且以CONFIG_开头的
- Configuration _SETTINGS_ 这是依赖于硬件并且不应该随意干涉。它们通常以CONFIG_SYS_开头的
对于支持的开发板都有可使用的默认配置变量,只需输入 make <board_name>_config
比如:对于TQM823L类型
cd u-boot
make TQM823L_config
所有配置依赖于板级和CPU的类型。所有信息都存放在配置文件include/configs/<board_name>.h中。比如我们使用的开发板所带的u-boot中就有include/configs/zynq_zturn.h文件。
还有其他选项需要配置,比如(详细参考README文件):
CPU类型:比如 CONFIG_MPC85XX
开发板类型:比如CONFIG_MPC8540ADS等等
U-Boot已经在很多本地环境和交叉编译环境中测试过了。推荐使用ELDK工具链http://www.denx.de/wiki/DULG/ELDK 。如果使用交叉编译,需要在shell中设置环境变量CROSS_COMPILE。比如:
CROSS_COMPILE=ppc_4xx-
export CROSS_COMPILE
通过make NAME_config配置,输入make all进行编译,编译会输出如下格式的U-Boot镜像。
- “u-boot.bin” is a raw binary image
- “u-boot” is an image in ELF binary format
- “u-boot.srec” is in Motorola S-Record format
可以通过如下方式在外部文件目录编译U-Boot。
- Add O= to the make command line invocations:
make O=/tmp/build distclean
make O=/tmp/build NAME_config
make O=/tmp/build all - Set environment variable BUILD_DIR to point to the desired location:
export BUILD_DIR=/tmp/build
make distclean
make NAME_config
make all
使用命令行O=会覆盖BUILD_DIR环境变量。
如果所使用的系统板没有支持,你需要通过如下方式移植U-Boot:
- Add a new configuration option for your board to the toplevel “boards.cfg” file, using the existing entries as examples. Follow the instructions there to keep the boards in order.
- Create a new directory to hold your board specific code. Add any files you need. In your board directory, you will need at least the “Makefile”, a “<board>.c”, “flash.c” and “u-boot.lds”.
- Create a new configuration file “include/configs/<board>.h” for your board
- If you’re porting U-Boot to a new CPU, then also create a new directory to hold your CPU specific code. Add any files you need.
- Run “make <board>_config” with your new name.
- Type “make”, and you should get a working “u-boot.srec” file to be installed on your target system.
- Debug and solve any problems that might arise.
开发板所给U-Boot中的boards.cfg中的记录:
第二步中创建的板载相关代码
第三步中创建的板载配置
“MAKEALL” 脚本会为所有支持的系统配置和编译U-Boot。当然需要向该脚本设置编译变量。
下面表格包含了启动过程中镜像的位置,Image不是环境变量名,其他都是。File Name给出TFTP服务器上文件的名字。RAM Address给出了镜像在RAM中的加载地址。Flash Location给出了NOR加载地址或NAND偏移地址。
Image | File Name | RAM Address | Flash Location |
---|---|---|---|
u-boot | u-boot | u-boot_addr_r | u-boot_addr |
Linux kernel | bootfile | kernel_addr_r | kernel_addr |
device tree blob | fdtfile | fdt_addr_r | fdt_addr |
ramdisk | ramdiskfile | ramdisk_addr_r | ramdisk_addr |
手册上给的编译教程:
编译U-Boot成功后,还会在它的tools子目录下生成一些工具,比如mkimage等。将它们复制到/usr/local/bin目录下,以后就可以直接使用它们了,比如编译内核时,会使用mkimage来生成U-Boot格式的内核映像文件uImage。
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \sed -e 's/\(cygwin\).*/cygwin/') #宿主机系统
$(shell command) shell函数的参数会被扩展(就像所有其他的参数)并且传递给subshell来执行。然后make会读取command的标准输出,并将之返回成函数的值。输出中所出现的一系列换行符号会被缩减成单一空格符号,任何接在后面的换行符号都会被删除。标准错误以及任何程序的结束状态都不会被返回。
# Allow for silent builds 允许静默编译
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo #如果MAKEFLAGS没有设置s
else
XECHO = : #在shell中,冒号是一个no-op命令,它总是返回真值,所以可以用来取代true
endif
$(findstring string…,text) 此函数会搜索string。如果该字符串被找到,此函数就会返回string;否则,它会返回空值。MAKEFLAGS是标准make变量(可以通过make --print-data-base输出的信息查找到该变量的值 )。
U-boot编译支持将输出文件产生到外部目录中。支持两种方法指定外部目录:
- 在make命令行上加上O=,例如make O=/tmp/build all。
- 设置环境变量BUILD_DIR指向目的目录。例如export BUILD_DIR=/tmp/build然后make。
第二种方法也可以和MAKEALL脚本一起使用,例如export BUILD_DIR=/tmp/build然后执行./MAKEALL。
命令O=覆盖了BUILD_DIR环境变量。由于变量可以从命令行中得到,所以使用如下代码来实现覆盖:
ifdef O
ifeq ("$(origin O)", "command line")
BUILD_DIR := $(O)
endif
endif
$(origin variable) origin函数将会返回描述变量来自何处的字符串。这个变量可以协助你决定如何使用一个变量的值。举例来说,如果一个变量来自环境,或许你会想要忽略该变量的值;如果该变量来自命令行,你就不会这么做。如果变量O来自命令行,则将BUILD_DIR设置为O所指定的路径。
如果BUILD_DIR不为空,也就是定义了外部输出目录,则saved-output和BUILD_DIR指定的路径相同。
ifneq ($(BUILD_DIR),)
saved-output := $(BUILD_DIR)
尝试创建BUILD_DIR指定的目录,并检测是否创建成功
# Attempt to create a output directory.
$(shell [ -d ${BUILD_DIR} ] || mkdir -p ${BUILD_DIR})# Verify if it was successful.
BUILD_DIR := $(shell cd $(BUILD_DIR) && /bin/pwd)
$(if $(BUILD_DIR),,$(error output directory "$(saved-output)" does not exist))
endif # ifneq ($(BUILD_DIR),)
$(if condition,then-part,else-part) if函数会根据条件表达式的求值结果,从两个宏中选一个出来,进行扩展的动作。如果condition扩展之后包含任何字符(即使是空格),那么它的求值结果为真,于是会对then-part进行扩展的动作;否则,如果condition扩展之后空无一物,那么它的求值结果为假,于是会对else-part进行扩展的动作。
$(error test) error函数可用来输出“无可挽回的”错误信息。在此函数输出信息之后,make将会以2这个结束状态终止允许。输出中包含当前makefile的名称、当前的行号以及消息正文。
OBJTREE := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
SPLTREE := $(OBJTREE)/spl
TPLTREE := $(OBJTREE)/tpl
SRCTREE := $(CURDIR)
TOPDIR := $(SRCTREE)
LNDIR := $(OBJTREE)
export TOPDIR SRCTREE OBJTREE SPLTREE TPLTREE
如果BUILD_DIR不为空,则OBJTREE和BUILD_DIR所指路径相同,如果为空,OBJTREE则为当前路径CURDIR,该变量是标准make变量。
SPLTREE路径是OBJTREE下sp1子目录,TPLTREE路径是OBJTREE下tp1子目录。SRCTREE和TOPDIR是当前目录路径。LNDIR和OBJTREE相同。
按照手册的编译命令,OBJTREE和SRCTREE以及LNDIR都是<WOKRDIR>/Bootloader/u-boot-xlnx路径。
如果OBJTREE和SRCTREE路径不相同,则REMOTE_BUILD变量值设为1。
ifneq ($(OBJTREE),$(SRCTREE))
REMOTE_BUILD := 1
export REMOTE_BUILD
endif
$(obj)和$(src)定义在config.mk文件中,但是在引入config.mk文件之前我们需要这两个变量。
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
export obj src
如果OBJTREE和SRCTREE不同,那么将这两个变量分别赋值,如果相同就不赋值。
使用make C=1来使能对重复编译的文件的检查。通过调用源代码检查器(默认sparse)。这部分不是太明白。
ifdef C
ifeq ("$(origin C)", "command line")
CHECKSRC := $(C)
endif
endif
ifndef CHECKSRCCHECKSRC = 0
endif
export CHECKSRC
配置文件在目录树下面:
MKCONFIG := $(SRCTREE)/mkconfig
export MKCONFIG
子目录:工具目录和例子目录
SUBDIR_TOOLS = tools
SUBDIR_EXAMPLES = examples/standalone examples/api
SUBDIRS = $(SUBDIR_TOOLS)
SUBDIRS代表所有子目录
.PHONY : $(SUBDIRS) $(VERSION_FILE) $(TIMESTAMP_FILE)
.PHONY这个特殊工作目标用来声明它的必要条件并不代表一个实际的文件,而且应该被视为尚未更新。
$(wildcard pattern…) wildcard函数的参数是一份模式列表,它会对列表中的每个模式进行扩展的动作。如果被扩展的模式找不到相符的文件,则会返回空字符串。wildcard的另一个用法,就是在条件语句中测试文件是否存在。
ifeq ($(obj)include/config.mk,$(wildcard $(obj)include/config.mk))
在引入config.mk之前,引入autoconf.mk文件。所有配置选项可以为所有上层编译文件所使用。We need the dummy all: target to prevent the
dependency target in autoconf.mk.dep from being the default.
all:
sinclude $(obj)include/autoconf.mk.dep
sinclude $(obj)include/autoconf.mkifndef CONFIG_SANDBOX
SUBDIRS += $(SUBDIR_EXAMPLES)
endif# load ARCH, BOARD, and CPU configuration 加载ARCH,BOARD和CPU配置
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
# set default to nothing for native builds
ifeq ($(HOSTARCH),$(ARCH))
CROSS_COMPILE ?=
endif
# load other configuration 加载其他配置
include $(TOPDIR)/config.mk
如果make没有找到引入文件,而且没有找到可用来创建该引入文件的规则,make将会汇报错误信息并且结束执行。如果想让make忽略无法加载的引入文件,可以为include指令前置一个破折号。为了兼容于其他版本的make,GNU make为-include提供了sinclude这个别名。
# Targets which don't build the source code
NON_BUILD_TARGETS = backup clean clobber distclean mkproper tidy unconfig
不会编译源码的工作目标有:backup、clean、clobber、distclean mkproper、tidy、unconfig。
只有真正编译时做板级检查
# Only do the generic board check when actually building, not configuring
ifeq ($(filter $(NON_BUILD_TARGETS),$(MAKECMDGOALS)),)
ifeq ($(findstring _config,$(MAKECMDGOALS)),)
$(CHECK_GENERIC_BOARD)
endif
endif
链接器选择:如果指明了LDSCRIPT或CONFIG_SYS_LDSCRIPT,直接使用。
LDSCRIPT_MAKEFILE_DIR = $(dir $(LDSCRIPT))
ifndef LDSCRIPT#LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debugifdef CONFIG_SYS_LDSCRIPT# need to strip off double quotesLDSCRIPT := $(subst ",,$(CONFIG_SYS_LDSCRIPT))endif
如果没有指明就寻找,主要逻辑就是CONFIG_NAND_U_BOOT是y的话,就先找$(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds如果没有就找$(TOPDIR)/$(CPUDIR)/u-boot-nand.lds。如果还是没有或者CONFIG_NAND_U_BOOT不是y的话就找$(TOPDIR)/board/$(BOARDDIR)/u-boot.lds。没有再找LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot.lds。若还是没有,就找$(TOPDIR)/arch/$(ARCH)/cpu/u-boot.lds。若还是没有该链接脚本,就报错,并退出执行。
ifndef LDSCRIPTifeq ($(CONFIG_NAND_U_BOOT),y)LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.ldsifeq ($(wildcard $(LDSCRIPT)),)LDSCRIPT := $(TOPDIR)/$(CPUDIR)/u-boot-nand.ldsendifendif...
OBJS = $(CPUDIR)/start.o
OBJS := $(addprefix $(obj),$(OBJS))
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard board/$(VENDOR)/common/Makefile),y,n)
$(addsuffix suffix,name…) addsuffix函数会将你所指定的suffix附加到name中所包含的每个单词后面。
添加GCC库
ifdef USE_PRIVATE_LIBGCC
ifeq ("$(USE_PRIVATE_LIBGCC)", "yes")
PLATFORM_LIBGCC = $(OBJTREE)/arch/$(ARCH)/lib/libgcc.o
else
PLATFORM_LIBGCC = -L $(USE_PRIVATE_LIBGCC) -lgcc
endif
else
PLATFORM_LIBGCC := -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
endif
PLATFORM_LIBS += $(PLATFORM_LIBGCC)
export PLATFORM_LIBS
# Always append ALL so that arch config.mk's can add custom ones
ALL-y += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
ALL-$(CONFIG_NAND_U_BOOT) += $(obj)u-boot-nand.bin
ALL-$(CONFIG_ONENAND_U_BOOT) += $(obj)u-boot-onenand.bin
ALL-$(CONFIG_SPL) += $(obj)spl/u-boot-spl.bin
ALL-$(CONFIG_SPL_FRAMEWORK) += $(obj)u-boot.img
ALL-$(CONFIG_TPL) += $(obj)tpl/u-boot-tpl.bin
ALL-$(CONFIG_OF_SEPARATE) += $(obj)u-boot.dtb $(obj)u-boot-dtb.bin
ifneq ($(CONFIG_SPL_TARGET),)
ALL-$(CONFIG_SPL) += $(obj)$(subst ",,$(CONFIG_SPL_TARGET))
endif
接下来就是一些规则,一些变量的详细的解析,以后再说:
$(OBJS): depend$(MAKE) -C $(CPUDIR) $(if $(REMOTE_BUILD),$@,$(notdir $@))
对于OBJS中的每个成员,都将进入$(CPUDIR目录(使用–directory即-C选项的目的是要让make在读取maefile之前先切换到相应的工作目标目录)编译它们。
得到ELF格式的U-Boot:
$(obj)u-boot: depend \$(SUBDIR_TOOLS) $(OBJS) $(LIBBOARD) $(LIBS) $(LDSCRIPT) $(obj)u-boot.lds$(GEN_UBOOT)
其中u-boot.lds指定了汇编各个段放置的地址。
all: $(ALL-y) $(SUBDIR_EXAMPLES)
工作目标all的必要条件是变量ALL-y和SUBDIR_EXAMPLES。
%_config:: unconfig@$(MKCONFIG) -A $(@:_config=)
命令中的@表示不要输出命令。$(MKCONFIG)就是根目录下的mkconfig文件。$(@:_config)的结果就是将$(@)工作目标中的_config去掉。
make zynq_zturn_config实际上就是执行如下命令:./mkconfig -A zynq_zturn
mkconfig文件分析:
用于创建头文件和用于为了配置指定开发板的U-Boot的链接。参数如下:
Parameters: Target Architecture CPU Board [VENDOR] [SOC]
if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then# Automatic modeline=`awk '($0 !~ /^#/ && $7 ~ /^'"$2"'$/) { print $1, $2, $3, $4, $5, $6, $7, $8 }' boards.cfg`if [ -z "$line" ] ; thenecho "make: *** No rule to make target \`$2_config'. Stop." >&2exit 1fiset ${line}# add default board name if needed[ $# = 3 ] && set ${line} ${1}fi
如果参数为两个且$1为-A,就为自动模式。awk对boards.cfg按照如下脚本命令进行
($0 !~ /^#/ && $7 ~ /^'"$2"'$/) { print $1, $2, $3, $4, $5, $6, $7, $8 }
即$0不匹配以#开头且$7匹配mkconfig脚本输入参数S2(在本例中指代zynq_zturn)的行,并打印该行中部分列:Active arm armv7 zynq xilinx zynq zynq_zturn -
该部分也就是从配置文件boards.cfg中读取记录。
mkconfig脚本行37到48在这里没有做任何操作,由于条件不符合
/# Strip all options and/or _config suffixes 剥离所有的选项和/或_config后缀
CONFIG_NAME="${7%_config}"
[ "${BOARD_NAME}" ] || BOARD_NAME="${7%_config}"
创建指向架构相关头文件的链接
cd ./include
rm -f asm
ln -s ../arch/${arch}/include/asm asm
进入include目录,删除asm文件(这是上次配置时建立的链接文件),然后再次建立asm文件,并令链接向…/arch/${arch}/include/asm
rm -f asm/arch也就是删除…/arch/${arch}/include/asm/arch文件
if [ -z "${soc}" ] ; thenln -s ${LNPREFIX}arch-${cpu} asm/arch
elseln -s ${LNPREFIX}arch-${soc} asm/arch
fiif [ "${arch}" = "arm" ] ; thenrm -f asm/procln -s ${LNPREFIX}proc-armv asm/procfi
如果soc为空,将asm/arch链接到{soc}为空,将asm/arch链接到soc为空,将asm/arch链接到{LNPREFIX}arch-cpu,否则链接到{cpu},否则链接到cpu,否则链接到{LNPREFIX}arch-${soc}。从上面代码可知如果源码目录和输出目录在相同路径下时,LNPREFIX是未定义的。
创建顶层Makefile包含的文件include/config.mk
( echo "ARCH = ${arch}"if [ ! -z "$spl_cpu" ] ; thenecho 'ifeq ($(CONFIG_SPL_BUILD),y)'echo "CPU = ${spl_cpu}"echo "else"echo "CPU = ${cpu}"echo "endif"elseecho "CPU = ${cpu}"fiecho "BOARD = ${board}"[ "${vendor}" ] && echo "VENDOR = ${vendor}"[ "${soc}" ] && echo "SOC = ${soc}"exit 0 ) > config.mk
创建开发板相关的头文件include/config.h
if [ "$APPEND" = "yes" ] # Append to existing config file
thenecho >> config.h
else> config.h # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.hfor i in ${TARGETS} ; doi="`echo ${i} | sed '/=/ {s/=/ /;q; } ; { s/$/ 1/; }'`"echo "#define CONFIG_${i}" >>config.h ;
doneecho "#define CONFIG_SYS_ARCH \"${arch}\"" >> config.h
echo "#define CONFIG_SYS_CPU \"${cpu}\"" >> config.h
echo "#define CONFIG_SYS_BOARD \"${board}\"" >> config.h[ "${vendor}" ] && echo "#define CONFIG_SYS_VENDOR \"${vendor}\"" >> config.h
[ "${soc}" ] && echo "#define CONFIG_SYS_SOC \"${soc}\"" >> config.hcat << EOF >> config.h
#define CONFIG_BOARDDIR board/$BOARDDIR
#include <config_cmd_defaults.h>
#include <config_defaults.h>
#include <configs/${CONFIG_NAME}.h>
#include <asm/config.h>
#include <config_fallbacks.h>
#include <config_uncmd_spl.h>
EOF
cat << EOF >> config.h即是在该行到EOF标志处的行追加到config.h
Z-Turn-Lite Board Linux开发-u-boot开篇相关推荐
- S5PV210 | S5PV210上进行Linux开发
S5PV210 | S5PV210上进行Linux开发 准备工作 开发板: 交叉编译工具链: S5PV210 | 安装交叉编译工具链(toolchain) 项目代码: https://gitee.co ...
- 把废弃的Kindle改装成自己的Linux开发平台
原文地址:Turning an old Amazon Kindle into a eink development platform 译者 & 校正:HelloGitHub-小鱼干 & ...
- Linux 开发环境工具 下载网址大全
Linux 开发环境工具 下载网址大全 package: download from: 软件集成开发环境(代码编辑.浏览.编译.调试) Emacs http:// ...
- Linux 开发环境工具 下载网址大全 --转
Linux 开发环境工具 下载网址大全 --转 ARM综合2010-08-04 22:46:17阅读329评论0字号:大中小订阅 软件集成开发环境(代码编辑.浏览.编译.调试) Emacs http: ...
- linux开发环境工具
linux开发环境工具 package: download from: 软件集成开发环境(代码编辑.浏览.编译.调试) Emacs http://www.gnu.o ...
- Zynq-7000系列之linux开发学习笔记:编译Linux内核和制作设备树(六)
开发板:Zynq7030数据采集板 PC平台:Ubuntu-18.04 + MobaXterm 开发环境:Xilinx Vivado + SDK -18.3 交叉编译工具:arm-linux-gnue ...
- Arndale Octa Board Exynos5420开发板之系统(Linaro Ubuntu)内核移植
必须仔细看,请注意看::::这边文章讲述的内核移植是针对Arndale Octa Board Exynos5420开发板的可用系统之一(Linaro Ubuntu)而言的,请注意并不是针对Arndal ...
- <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动
<Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移 ...
- 嵌入式设备开发专题《tiny4412开发,嵌入式linux开发环境搭建》
嵌入式linux开发基础: 1.系统组成: 嵌入式linux系统的组成包括三部分:bootloader程序.linux内核.根文件系统 bootloader程序:系统上电后首先要执行的程序,主要功能是 ...
最新文章
- DAY74-Django框架(五)
- 使用 ASP+ DataGrid 控件来创建主视图/详细资料视图
- Java多线程练习--取钱
- JNI线程、Linux常用命令、权限、防火墙配置
- 列表框QListWidget 类
- 人工智能:第九章 Agent (艾真体)
- JAVA记事本的图形用户界面应用程序含过滤
- javascript 原生得到document.Element的方法
- 通过Windows远程桌面连接将远程文件传输至本地
- 排列图 - QCC小组活动推行知识系列介绍(三)
- 任务型聊天机器人和闲聊类机器人的关键技术
- 文字转语音 两种方法:TextToSpeech、科大讯飞
- PHP实现用户登录注册(详细教程)
- 专业计算机术语中英文对照(二)
- 北京大学计算机学院复试名单2020,学院2020年全日制硕士研究生招生考试复试名单公示...
- CTF解题记录-Misc-当铺秘密
- 教你用python制作猜数游戏
- 自学Java怎样入门
- Airflow Python工作流引擎的重要概念介绍
- Spring boot将项目的静态资源提取到项目外面的文件夹