一、uboot20 s5pv210移植—基础环境配置
在进行s5pv210的使用时,由于外设的初始化要求和空间大小,需要在IRAM中执行SPL代码进行一些外设的初始化,随后将u-boot加载到指定的DRAM中。因此,对于SPL的了解和学习十分有必要,而且SPL中的许多操作涉及到ARM相关功能和寄存器的操作,由此也展开对裸机程序的学习。可以通过下图来查看整个设备的启动流程。
从上图中可以看出,在IROM中的romcode执行完成后,会将Booting Device中的BL1(SPL)先load到IRAM中,因为IRAM不需要初始化,可以直接上电使用,则加载SPL后就可以执行,完成时钟和DRAM等外设的初始化后,就可以加载BL2(U-Boot)完成其他外设的初始化。为什么需要BL1?
由于在执行romcode时会从Booting Devices中读取BL1到IRAM中,所以romcode中肯定存在Booting Devices的驱动。
在编译u-boot时,可以编译出spl,那spl和u-boot的区别到底在哪里,这就需要我们分析一下u-boot中spl的编译过程
在编译u-boot时,在执行完make s5pv210_defconfig
而生成对应的配置文件后,则可以通过执行make
生成设备运行需要的bin文件。而执行make
命令时,肯定会去根目录的Makefile中执行。
all: .binman_stamp inputs
起始目标为all
,通过上述代码可以看出该目标依赖于inputs
,其生成规则如下:
inputs: $(INPUTS-y)
通过代码可以看出inputs
依赖于$(INPUTS-y)
,其中INPUTS-y
作为一个变量,里面包含多个内容,代码如下:
INPUTS-y += u-boot.srec u-boot.bin u-boot.sym System.map \
binary_size_check
INPUTS-$(CONFIG_SPL) += spl/u-boot-spl.bin
从上述代码中可以看出,要想在编译u-boot时生成spl,则需要将宏CONFIG_SPL
定义
而spl/u-boot-spl.bin的生成规则在根目录中进行了定义
spl/u-boot-spl.bin: spl/u-boot-spl
@:
$(SPL_SIZE_CHECK)
spl/u-boot-spl: tools prepare \
$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_SPL_OF_PLATDATA),dts/dt.dtb) \
$(if $(CONFIG_OF_SEPARATE)$(CONFIG_OF_EMBED)$(CONFIG_TPL_OF_PLATDATA),dts/dt.dtb)
$(Q)$(MAKE) obj=spl -f $(srctree)/scripts/Makefile.spl all
从上面的代码可以看出,spl/u-boot-spl.bin
依赖于spl/u-boot-spl
,而spl/u-boot-spl
在依赖全部满足的条件下,生成的规则则是执行scripts/Makefile.spl中的all目标。因此需要跳转到Makefile.spl
中去确认一下spl/u-boot-spl
的生成过程
查看Makefile.spl文件中的内容,all
目标的生成依赖于$(INPUTS-y)
。
all: $(INPUTS-y)
与根目录的操作方法如出一辙,需要确认INPUTS-y
变量中包含哪些内容,相关代码如下:
SPL_BIN := u-boot-spl
INPUTS-y += $(obj)/$(SPL_BIN).bin
ifdef CONFIG_SAMSUNG
INPUTS-y += $(obj)/$(BOARD)-spl.bin
endif
从代码中可以看出,INPUTS-y
中至少包含一个文件即spl/u-boot-spl.bin
,而如果定义了CONFIG_SAMSUNG
的话,则会多一个与board相关的spl/s5pv210-spl.bin
文件,因为s5pv210是samsung的开发板,则INPUTS-y
实际是包含这两个内容的。
根据代码中的层层推导,先确认spl/u-boot-spl.bin
的生成依赖关系
# spl/u-boot-spl.bin依赖spl/u-boot-spl-nodtb.bin
$(obj)/$(SPL_BIN).bin: $(obj)/$(SPL_BIN)-nodtb.bin FORCE
$(call if_changed,copy)
# spl/u-boot-spl-nodtb.bin依赖spl/u-boot-spl
$(obj)/$(SPL_BIN)-nodtb.bin: $(obj)/$(SPL_BIN) FORCE
$(call if_changed,objcopy)
# spl/u-boot-spl依赖多个目标
$(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
$(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
$(call if_changed,u-boot-spl)
从上述代码可以看出,为了生成spl/u-boot-spl.bin
文件,最终依赖于多个变量的内容和链接脚本。对依赖的内容依次分析:
$(u-boot-spl-platdata)
该变量在Makefile.spl中通过宏控制被赋值如下:
ifdef CONFIG_SPL_OF_PLATDATA
u-boot-spl-platdata := $(obj)/dts/dt-platdata.o
endif
这个宏如果没有定义的话,是不会对该变量赋值的,也就是说该变量为空。宏CONFIG_SPL_OF_PLATDATA
与dts相关,在spl中由于IRAM有限,不会开启dts相关的功能,则此宏也不会配置,从而u-boot-spl-platdata
为空
$(u-boot-spl-init)
head-y := $(addprefix $(obj)/,$(head-y))
u-boot-spl-init := $(head-y)
从上述代码中可以看出Makefile.spl
中的head-y
的值则是在先前head-y
的值前面添加前缀spl,而head-y
之前的值,则是在arch/arm/Makefile中进行的赋值,即head-y := arch/arm/cpu/armv7/start.o
。最终,在Makefile.spl文件中,spl/u-boot-spl.bin
的生成则是依赖于spl/arch/arm/cpu/armv7/start.o
$(u-boot-spl-main)
HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
libs-$(HAVE_VENDOR_COMMON_LIB) += board/$(VENDOR)/common/
libs-y += common/init/
libs-y += drivers/
libs-y += dts/
libs-y += fs/
libs-y := $(addprefix $(obj)/,$(libs-y))
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
u-boot-spl-main := $(libs-y)
从代码中可以看出,u-boot-spl-main
中包含多个built-in.o文件。至少包含以下内容
u-boot-spl-main := spl/board/samsung/common/built-in.o spl/common/init/built-in.o spl/drivers/built-in.o spl/dts/built-in.o spl/fs/built-in.o
$(obj)/u-boot-spl.lds
$(obj)/u-boot-spl.lds: $(LDSCRIPT) FORCE
$(call if_changed_dep,cpp_lds)
从代码中可以看出,lds文件依赖于变量LDSCRIPT
。代码内容如下:
# Linker Script
# First test whether there's a linker-script for the specific stage defined...
ifneq ($(CONFIG_$(SPL_TPL_)LDSCRIPT),)
# need to strip off double quotes
LDSCRIPT := $(addprefix $(srctree)/,$(CONFIG_$(SPL_TPL_)LDSCRIPT:"%"=%))
else
# ...then fall back to the generic SPL linker-script
ifneq ($(CONFIG_SPL_LDSCRIPT),)
# need to strip off double quotes
LDSCRIPT := $(addprefix $(srctree)/,$(CONFIG_SPL_LDSCRIPT:"%"=%))
endif
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/board/$(BOARDDIR)/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/$(CPUDIR)/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
LDSCRIPT := $(srctree)/arch/$(ARCH)/cpu/u-boot-spl.lds
endif
ifeq ($(wildcard $(LDSCRIPT)),)
$(error could not find linker script)
endif
分析以上代码,显示判断是否通过宏CONFIG_SPL_LDSCRIPT
指定了链接脚本,如果没有指定的话,则依次去如下位置寻找,直至找到:
最终,是将变量赋值为了arch/arm/cpu/u-boot-spl.lds
至此,生成spl/u-boot-spl
的依赖全部分析完成,查看spl/u-boot-spl
的生成规则
$(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
$(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
$(call if_changed,u-boot-spl)
可以确定$(call if_changed,u-boot-spl)
是执行cmd_u-boot-spl
,而该命令的内容如下:
# Rule to link u-boot-spl
# May be overridden by arch/$(ARCH)/config.mk
quiet_cmd_u-boot-spl ?= LD $@
cmd_u-boot-spl ?= (cd $(obj) && $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_$(@F)) \
$(patsubst $(obj)/%,%,$(u-boot-spl-init)) --start-group \
$(patsubst $(obj)/%,%,$(u-boot-spl-main)) \
$(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) \
--end-group \
$(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN))
大概的操作则是进入spl/目录,通过交叉编译工具链的ld命令,按照lds链接脚本,将u-boot-spl-init
、u-boot-spl-main
和u-boot-spl-platdata
链接到一起,生成u-boot-spl
文件。
从而,获取了s5pv210在IRAM中需要用到的spl的elf文件,获取elf文件,则bin文件就唾手可得了。
!!!上述的代码只是纸上谈兵,直接分析的代码,没有进行任何实际操作。这算是在移植前的自我疑惑解答,让自己大致了解spl.bin在u-boot中是怎么生成的。