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。

  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
    使用命令行O=会覆盖BUILD_DIR环境变量。

如果所使用的系统板没有支持,你需要通过如下方式移植U-Boot:

  1. 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.
  2. 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”.
  3. Create a new configuration file “include/configs/<board>.h” for your board
  4. 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.
  5. Run “make <board>_config” with your new name.
  6. Type “make”, and you should get a working “u-boot.srec” file to be installed on your target system.
  7. 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开篇相关推荐

  1. S5PV210 | S5PV210上进行Linux开发

    S5PV210 | S5PV210上进行Linux开发 准备工作 开发板: 交叉编译工具链: S5PV210 | 安装交叉编译工具链(toolchain) 项目代码: https://gitee.co ...

  2. 把废弃的Kindle改装成自己的Linux开发平台

    原文地址:Turning an old Amazon Kindle into a eink development platform 译者 & 校正:HelloGitHub-小鱼干 & ...

  3. Linux 开发环境工具 下载网址大全

    Linux 开发环境工具 下载网址大全  package:        download from: 软件集成开发环境(代码编辑.浏览.编译.调试) Emacs            http:// ...

  4. Linux 开发环境工具 下载网址大全 --转

    Linux 开发环境工具 下载网址大全 --转 ARM综合2010-08-04 22:46:17阅读329评论0字号:大中小订阅 软件集成开发环境(代码编辑.浏览.编译.调试) Emacs http: ...

  5. linux开发环境工具

    linux开发环境工具 package:        download from: 软件集成开发环境(代码编辑.浏览.编译.调试) Emacs            http://www.gnu.o ...

  6. Zynq-7000系列之linux开发学习笔记:编译Linux内核和制作设备树(六)

    开发板:Zynq7030数据采集板 PC平台:Ubuntu-18.04 + MobaXterm 开发环境:Xilinx Vivado + SDK -18.3 交叉编译工具:arm-linux-gnue ...

  7. Arndale Octa Board Exynos5420开发板之系统(Linaro Ubuntu)内核移植

    必须仔细看,请注意看::::这边文章讲述的内核移植是针对Arndale Octa Board Exynos5420开发板的可用系统之一(Linaro Ubuntu)而言的,请注意并不是针对Arndal ...

  8. <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动

    <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移 ...

  9. 嵌入式设备开发专题《tiny4412开发,嵌入式linux开发环境搭建》

    嵌入式linux开发基础: 1.系统组成: 嵌入式linux系统的组成包括三部分:bootloader程序.linux内核.根文件系统 bootloader程序:系统上电后首先要执行的程序,主要功能是 ...

最新文章

  1. DAY74-Django框架(五)
  2. 使用 ASP+ DataGrid 控件来创建主视图/详细资料视图
  3. Java多线程练习--取钱
  4. JNI线程、Linux常用命令、权限、防火墙配置
  5. 列表框QListWidget 类
  6. 人工智能:第九章 Agent (艾真体)
  7. JAVA记事本的图形用户界面应用程序含过滤
  8. javascript 原生得到document.Element的方法
  9. 通过Windows远程桌面连接将远程文件传输至本地
  10. 排列图 - QCC小组活动推行知识系列介绍(三)
  11. 任务型聊天机器人和闲聊类机器人的关键技术
  12. 文字转语音 两种方法:TextToSpeech、科大讯飞
  13. PHP实现用户登录注册(详细教程)
  14. 专业计算机术语中英文对照(二)
  15. 北京大学计算机学院复试名单2020,学院2020年全日制硕士研究生招生考试复试名单公示...
  16. CTF解题记录-Misc-当铺秘密
  17. 教你用python制作猜数游戏
  18. 自学Java怎样入门
  19. Airflow Python工作流引擎的重要概念介绍
  20. Spring boot将项目的静态资源提取到项目外面的文件夹

热门文章

  1. 恢复微信撤回的图片(不容root,极其简单)
  2. dss nginx 403 forbidden
  3. 迷宫 做的第一个搜索题
  4. 利用photoshop cs5新增功能之“智能填充
  5. Echarts 柱状图上方显示值
  6. 技术期刊 · 路尘终见泰山平 | 微前端及插件化架构在 Wix 的实践;编辑器架构的第二路径;业务中的前端组件化体系……
  7. 【BZOJ2002】【HNOI2010】弹飞绵羊(LCT)
  8. americdan-life
  9. Python 之 异常值/离群值的处理
  10. 使用order by 按照指定顺序排序或自定义顺序排序