u-boot 移植新手入门实践
v2.0
2018-10-11
bug
前 言
笔者所使用的开发板是基于 Exynos4412,因此本书的所有移植示例源码仅适用于基于
此款芯片的开发板,但整个移植的过程分析并不仅限于此系列芯片,可供各位新手同学移植
u-boot 提供参考。此文档意在为那些想移植 u-boot,但却无从下手的新手同学提供移植分析
思路;希望通过此能够帮助各位新手同学提供举一反三的思路,实现 u-boot 的移植。
前 3 章为认知篇,重点在于讲解如何将 Samsung 提供的 u-boot 和 Kernel 移植至我们自
己的开发板;通过实践+源代码分析的形式,对 u-boot 和 Kernel 启动过程有个初步的认识,
在这一部分并不会深入的去分析,采用一笔带过的讲解方式。
后 3 章为入门篇,通过对前面 3 章的实践,对 u-boot 和 Kernel 的启动过程已有了初步
的了解,在接下的这 3 章中,将对 u-boot 移植过程进行细讲。同时为了能更好的理解整个
u-boot 的移植过程,此部分的 u-boot 将不在使用 Samsung 提供的,而是从 u-boot 官网中选
择一个适当的版本进行移植。
可能有些童鞋会认为笔者将此书分成如此有重叠的两部份是在重复劳动或者凑字数。对
于第一部分的 u-boot 是为对 u-boot 没有任何概念的童鞋提供的营养早餐,避免由于初识
u-boot 移植需一下接收太多的知识而举步难进,因此我们需要快感的来学习这些知识,徐徐
渐进的去学习。
I
目 录
前 言 ............................................................................................................................................... I
1 u-boot 启动流程分析 .................................................................................................................... 1
1.1 u-boot 启动入口 ................................................................................................................. 1
1.1.1 u-boot 源码 .............................................................................................................. 1
1.1.2 u-boot 链接脚本 ...................................................................................................... 1
1.1.2.1 顶层 Makefile ........................................................................................... 1
1.1.2.2 mkconfig ................................................................................................... 4
1.1.2.3 config.mk ................................................................................................. 4
1.1.2.4 lib_arm/config.mk ................................................................................. 5
1.1.2.5 链接脚本 cpu/arm_cortexa9/u-boot.lds ............................................ 5
1.1.3 删除 u-boot 文件 .................................................................................................... 6
1.2 u-boot 启动第一阶段(汇编) .............................................................................................. 7
1.2.1 标签 _start ............................................................................................................. 7
1.2.2 标签 reset .............................................................................................................. 8
1.2.3 标签 cache_init ...................................................................................................... 9
1.2.4 标签 lowlevel_init .................................................................................................. 9
1.2.5 标签 mem_ctrl_asm_init: DDR 初始化 ................................................................. 9
1.2.6 标签 uart_asm_init: 串口初始化 ........................................................................ 10
1.2.7 u-boot 重定位 ........................................................................................................ 11
1.3 u-boot 启动第二阶段(C) .................................................................................................. 12
1.3.1 函数 start_armboot:C 语言入口 .......................................................................... 12
1.3.2 指针数组 init_sequence:初始化和显示信息相关函数为元素 .......................... 12
1.3.3 函数 display_banner:显示 u-boot 版本号等 ....................................................... 13
1.3.4 函数 print_cpuinfo:显示 CPU 配置相关信息—时钟等 ....................................... 13
1.3.5 函数 checkboard:显示板子名称 .......................................................................... 13
1.3.6 函数 dram_init:DRAM 初始化............................................................................. 14
1.3.7 函数 display_dram_config:显示内存大小 .......................................................... 14
1.3.8 函数 main_loop:命令解析控制台 ....................................................................... 15
1.3.9 函数 run_command:命令解析 ............................................................................ 15
1.3.10 执行 bootm 命令:bootm 命令执行函数 ........................................................... 16
1.3.11 函数 do_bootm_linux:传参内核并启动 ............................................................ 17
1.4 小结 ................................................................................................................................. 17
2 Samsung u-boot 移植 .................................................................................................................. 18
2.1 创建 itop4412 编译配置 ................................................................................................ 18
2.1.1 Makefile 添加 itop4412 编译规则 ....................................................................... 18
2.1.2 build_uboot.sh 修改编译脚本 ............................................................................. 18
2.2 移植 itop4412 u-boot ...................................................................................................... 19
2.2.1 修改显示信息 ....................................................................................................... 19
2.2.2 适配电源和 MMC ................................................................................................. 19
2.2.3 DDR3 移植 .............................................................................................................. 20
II
2.2.3.1 DDR3 初始化 ............................................................................................ 20
2.2.3.2 虚拟地址映射 ......................................................................................... 21
2.2.3.3 移植 DDR3 实践 ....................................................................................... 22
2.2.4 eMMC 初始化失败: unrecognised EXT_CSD structure version 7 .......................... 28
2.3 u-boot 启动内核 ............................................................................................................... 29
2.4 小结 ................................................................................................................................. 31
附录 ................................................................................................................................................ 32
a.配套视频地址 ...................................................................................................................... 32
III
1 u-boot 启动流程分析
1.1 u-boot 启动入口
1.1.1 u-boot 源码
u-boot 源码可以通过两种路径获取:
第一种方式:从 u-boot 官方网站中下载,但通过这种途径获得的 u-boot 与我们使用的
板子的适配度可能比较低,因此会增加移植难度。对于新手不建议以这种 u-boot 为基础入
手移植;因为以这种 u-boot 移植,需要对 u-boot 整体架构和 SOC 的配置比较熟悉,不然会
觉很难入手。
第二种方式:使用 Samsung 针对这款 SOC 的 demo 板移植过的 u-boot,可以找开发板
厂家获取。基于这样的 u-boot 再去移植到我们自己的开发板,这样就很大的降低了移植难
度,同时也能让我们体验一把移植 u-boot 成功的乐趣。使用这种 u-boot 之所以能降低移植
难度,更适合新手作为入门实践,是由于我们的开发板与 demo 板使用一样的 SOC,或者可
以理解为我们的开发板是基于 Samsung 的 demo 板做了扩展,因此两者之间存在异同之处,
而我们只需要针对差异之处移植。
在入门篇 u-boot 移植中,使用的就是 Samsung 基于 Exynos4412 demo 板做过移植的
u-boot。课程的移植源码和资料将共享到 github 仓库(github.com/bugshiyanshi/buglab4412),
有需要的同鞋可以通过该仓库获取。
1.1.2 u-boot 链接脚本
分析 u-boot 启动时需要明确从哪里开始分析,也就是说要先确定 u-boot 的启动入口‘函
数’;如何确定启动入口‘函数’?在这里需要通过 u-boot 链接脚本来确定。
根据 Makefile 来确定 u-boot 的链接脚本
1.1.2.1 顶层 Makefile
HOSTARCH
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/)
HOSTARCH := $(shell uname -m | \
定义编译主机的架构,‘sed -e s/i.86/i386/’将 i.86 替换成
i386
HOSTOS
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
定义编译主机的操作系统类型
sed -e 's/\(cygwin\).*/cygwin/')
1
BUILD_DIR
:= $(SRCTREE)/mkconfig
:= $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))
:= $(CURDIR)
:= $(SRCTREE)
:= $(OBJTREE)
ifneq ($(BUILD_DIR),)
saved-output := $(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),)
BUILD_DIR: 编译输出目录
如果‘$(BUILD_DIR)’表示的目录不存在,则创建并且赋值
为当前目录的路径
OBJTREE
SRCTREE
TOPDIR
LNDIR
export
TOPDIR SRCTREE OBJTREE
MKCONFIG
export MKCONFIG
……
ifneq ($(OBJTREE),$(SRCTREE))
obj := $(OBJTREE)/
src := $(SRCTREE)/
else
obj :=
src :=
endif
‘OBJTREE:=$(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))’:如
果‘$(BUILD_DIR)’不为空,则 OBJTREE=$(BUILD_DIR),否
则 OBJTREE=$(CURDIR)。
$(CURDIR):为当前路径的目录
$(SRCTREE):源码目录,这里指 u-boot 顶层目录
因此,这几个变量最后的值为:
OBJTREE
SRCTREE
TOPDIR
这里$(BUILD_DIR) = $(CURDIR) = $(SRCTREE)都是为 u-boot 的
顶层目录故:
obj :=
src :=
:= $(BUILD_DIR)
:= $(CURDIR)
:= $(SRCTREE)
2
MKCONFIG=./ mkconfig
include/config.mk
文件存在
ifeq($(obj)include/config.mk,$(wildcard$(obj)include/config.m
k))
环境变量:ARCH
CPU BOARD
VENDOR SOC
CROSS_COMPILE
include/config.mk
编译生成目标
include/config.
mk 文件不存在
unconfig:
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
包 含 include/config.mk 文 件 ,并 将全 局 变量 ARCH CPU
BOARD VENDOR SOC 设置为环境变量
ifeq ($(ARCH),arm)
CROSS_COMPILE = arm-none-linux-gnueabi-
endif
CROSS_COMPILE : 指定编译器
arm-none-linux-gnueabi- : 编译工具的前缀
include $(TOPDIR)/config.mk
包含 config.mk 配置文件
ALL += $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map
$(U_BOOT_NAND) $(U_BOOT_ONENAND)
all:
$(ALL)
tags
ctags etags
cscope
$(TIMESTAMP_FILE)
tools,$(SUBDIRS))
###################################################
else # !config.mk
all $(obj)u-boot.hex $(obj)u-boot.srec $(obj)u-boot.bin \
$(obj)u-boot.img $(obj)u-boot.dis $(obj)u-boot \
$(filter-out
$(VERSION_FILE) gdbtools \
updater env depend dep
$(obj)System.map:
@echo "System not configured - see README" >&2
@ exit 1
config.mk 不存在,停止编译
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
%: %_config
%: %_config: 当执行 make xxx_config 会匹配到此通配符,执
行$(MAKE)。
$(MAKE): make
$(MAKE)
配置目标编译参数
tc4_android_config:
@$(MKCONFIG) $(@:_config=) arm arm_cortexa9 smdkc210
samsung s5pc210
unconfig
$(MKCONFIG) = ./mkconfig
3
unconfig
$(@:_config=):表示 xxx_config 并将_config 替换为’ ’,替换后
$(@:_config=) = xxx 表达式即为:
tc4_android_config:
./mkconfig tc4_android arm arm_cortexa9 smdkc210 samsung
s5pc210
mkconfig 后面几个参数说明:
第一个参数: 目标板型号
第二个参数: CPU 架构
第三个参数: CPU 型号
第四个参数: 开发板名称
第五个参数: 生成厂家
第六个参数: SOC
1.1.2.2 mkconfig
mkconfig
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
根据传递进来的参数来生成 include/config.mk 文件,接着执行 make
命令,并最终生成 u-boot 镜像文件,如果未执行‘make xxx_config’
命令,在执行 make 命令后显示一下错误信息,并停止编译:
System not configured - see README
这是因为找不到 include/config.mk 文件导致的,详情查看 Makefile 中
判断 include/config.mk 是否存在部分
1.1.2.3 config.mk
110 行
sinclude $(OBJTREE)/include/autoconf.mk
ifdef ARCH # ARCH = arm
sinclude $(TOPDIR)/lib_$(ARCH)/config.mk
endif
ifdef CPU # CPU = arm_cortexa9
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk
endif
ifdef SOC # SOC = s5pc210
sinclude $(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk
endif
将 ARCH、CPU、SOC 替换后的路径为:
sinclude lib_arm/config.mk
sinclude cpu/arm_cortexa9/config.mk
sinclude cpu/arm_cortexa9/s5pc210/config.mk
4