https://e.coding.net/weidongshan/01_all_series_quickstart.git
XIP启动方式 VS. 非XIP启动方式
上面是XIP(eXecute in place的方式),下面是非XIP的启动方式.
XIP方式的BootLoader直接存放在片内的ROM或FLASH中执行.优势是bootloader流程更加简单,问题是随着bootloader程序逐渐变大,大多数单板片内的ROM或flash不足以支撑完整的bootloader程序,所以使用非XIP的方式更为主流.
非XIP的启动方式需要把U-Boot从外设搬运到内存,负责搬运的小程序称为spl,通常是刷写在可以XIP的ROM或Flash设备,这里我们称之为BootRom.
spl的代码负责几个事情:
- 需要搬运的代码所在的设备要进行设备初始化,要有外设初始化代码代码
- DDR通常是搬运的目的地,所以DDR设备和相关设备初始化也是必须的
- U-boot从外设搬运到内存动作的代码
XIP和非XIP启动流程对比:
U-Boot的组成
- 通用的bootloader.bin主程序
- soc架构 如arm/x86
- soc厂家 如三星/nxp
- 芯片 nxp-> imx1ull/imx8
- 板卡厂家 米尔/100ask
- 型号 100ask-> pro/mini
- dtb文件 -> uboot引入了设备树,避免大规模的基本类似的源码文件
- u-boot = u-boot.bin + xxx.dtb
在u-boot目录下执行"tree . -d > 1.txt",可以得到目录的结构,精简如下:
> tree .
├── arch
│ ├── arm // 1. 架构相关
│ │ ├── cpu
│ │ │ ├── armv7
│ │ │ │ ├── mx6
│ │ ├── dts
│ │ │ └── include
│ │ │ └── dt-bindings -> ../../../../include/dt-bindings
│ │ ├── include
│ │ │ ├── asm
│ │ │ │ ├── arch-imx
│ │ │ │ ├── arch-imx8
│ │ │ │ ├── arch-imx8m
│ │ │ │ ├── imx-common
│ │ │ └── debug
│ │ ├── lib
│ │ ├── mach-rockchip
│ │ │ ├── rk3036
│ │ │ ├── rk3288
│ │ │ └── rk3399
│ │ ├── lib
├── board // 单板相关
│ ├── freescale
│ │ ├── common
│ │ │ └── p_corenet
│ │ ├── corenet_ds
│ │ ├── mx6ul_14x14_ddr3_arm2
│ │ ├── mx6ul_14x14_evk
│ │ ├── mx6ul_14x14_lpddr2_arm2
│ │ ├── mx6ull_ddr3_arm2
│ │ ├── mx6ullevk
├── cmd // 通用的命令
│ ├── fastboot
│ └── mvebu
├── common // 通用的
│ ├── eeprom
│ ├── init
│ └── spl
├── configs
├── disk
├── drivers // 各类驱动
├── fs // 文件系统
│ ├── cbfs
│ ├── cramfs
│ ├── ext4
│ ├── fat
│ ├── jffs2
│ ├── reiserfs
│ ├── sandbox
│ ├── ubifs
│ ├── yaffs2
│ └── zfs
├── include
├── lib // 库
├── net // 网络协议
研究U-Boot配置的基本手段和思想
- 对比查看简略版本和详细版本的make输出信息
make > echo_simple.log # 观察简略的关键信息
make mx6ull_14x14_evk_defconfig -p > echo_makerules.log # -p生成所有的make规则到文件
make mx6ull_14x14_evk_defconfig -p V=1 > echo.log # V=1详细的输出到文件
vi echo.log
:g/^#/d # 将echo.log中生成出来的注释全部删除,会节省很多代码
- 删除大法,拷贝要分析的makefile或源码文件,将所有不感兴趣或不知道干什么用的代码全部删除,得到一份干净简单简短的文件进行分析
u-boot配置文件生成过程
make mx6ull_14x14_evk_defconfig
HOSTCC scripts/basic/fixdep
HOSTCC scripts/kconfig/conf.o
YACC scripts/kconfig/zconf.tab.c
LEX scripts/kconfig/zconf.lex.c
HOSTCC scripts/kconfig/zconf.tab.o
HOSTLD scripts/kconfig/conf
# 上面可以看到生成了一些kconfig工具和文件
make -p mx6ull_14x14_evk_defconfig > echo_makerules.log
# echo_makerules.log
%_defconfig: scripts/kconfig/conf
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
mx6ull_14x14_evk_defconfig: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
# echo.log
make -f ./scripts/Makefile.build obj=scripts/kconfig mx6ull_14x14_evk_defconfig
scripts/kconfig/conf --defconfig=arch/../configs/mx6ull_14x14_evk_defconfig Kconfig
defconfig_file = "arch/../configs/mx6ull_14x14_evk_defconfig";
name = "Kconfig"
conf_parse(name); // 解析uboot根目录下的Kconfig文件
conf_read(defconfig_file); // 读配置文件
conf_set_all_new_symbols(def_default); // 设置new_symbols为默认值
conf_write(NULL); // 写到.config
执行过程:
- 制作工具:scripts/kconfig/conf
- 把默认配置信息写入文件".config"
生成文件:
- Kconfig:这是一个通用文件,里面规定了一些依赖,比如:
- 如果是ARM架构,就默认选中A、B、C配置
- 如果是RISC-V架构,就默认选中a、b、c配置
- defconfig_file:这是厂家提供的,里面定义了
- ARM架构
- 自己的一些配置项
- 怎么处理呢?
- 使用defconfig_file的内容去解析Kconfig,确定各个依赖的配置项
- 其他未涉及的配置项,给它们指定默认值
- 写入.config
2017版本:
2023版本:
0.
1. mx6ull defconfig的依赖目标内容:
2. script/basic目标内容: 生成fixdep程序,该程序用于解析
scripts/kconfig内容:
可以看到最后就是生成了conf工具并执行该工具
conf工具分析:
scripts/kconfig/conf.c
这个文件做什么用的呢? 源码也很复杂没有注释并不好分析.
简单的方法就是直接执行下这个程序.
就是生成.config配置文件. 但是我们发现生成出来的.config没有任何实际的东西, 分析下是为什么?
该工具用到getenv获取环境变量,环境变量的定义肯定是在Makefile.build进行的.
Kconfig配置
Kconfig基础在04_Kconfig介绍中,写得很好了.
Kconfig主要的作用是:
- 添加新模块后需要在就近的文件夹下的Kconfig中添加对应的config XXX,并且Makefile也需要添加obj-$(CONFIG_XXX) += xxx.o 或者 obj-y += xxx.o,前者只有Kconfig配置了才会编译,后者一定会被编译(只要是obj-y,就一定会被编译,而另一种写法则是需要通过menuconfig选择或最外层的Kconfig中添加才会被编译)
- 给menuconfig菜单提供基座,菜单根据Kconfig的结构进行生成
- 可以定义某个配置项的depend,这样源码的编译通过Kconfig,就不需要在代码中写一堆#ifdef …了,非常方便
U-Boot编译过程分析
remake的流程:
- 执行到-include test时,发现之前尚未有test相关的目标,故没有包含.
- 再往下执行,发现了test目标,所以此时要包含test,并重新进行remake操作
注: uboot/doc/README.kconfig是很好的介绍资料