Uboot 顶层 Makefile 分析 及 启动分析流程总结

1、在阅读 uboot 源码之前,肯定是要先看一下顶层 Makefile,分析 gcc 版本代码的时候一定是

先从 顶层 Makefile 开始的,然后再是 子 Makefile ,这样通过 层层分析 Makefile 即可了解整个工
程的 组织结构
版本号
MAKEFLAGS 变量
make 是支持递归调用的,也就是 在Makefile中使用“make”命令来执行其他的 Makefile
文件,一般都是子目录中的 Makefile 文件。假如在当前目录下存在一个“subdir”子目录,这个
子目录中又有其对应的 Makefile 文件,那么这个工程在编译的时候其主目录中的 Makefile 就可
以调用子目录中的 Makefile,以此来完成所有子目录的编译
$(MAKE) -C subdir
一般大项目里面所有的源代码都不会放 到同一个目录中,各个功能模块的源代码都是分开的,各自存放在各自的目录中。
主目录的 Makefile 可以使用如下 代码来编译这个子目录:
$(MAKE) 就是调用“ make ”命令, -C 指定子目录。有时候我们需要向子 make 传递变量,
这个时候使用“ export ”来导出要传递给子 make 的变量即可,如果不希望哪个变量传递给子
make 的话就使用“ unexport ”来声明不导出
MAKEFLAGS += - rR -- include - dir = $ ( CURDIR )
make 过程 
配置好 uboot 以后就可以直接 make 编译了,因为没有指明目标,所以会使用默认目标,主
Makefile 中的默认目标如下:
uboot.bin -> uboot.nodtb.bin->u-boot-> u-boot_init u-boot-main u-boot_init
u-boot-init := $(head-y) 
head-y := arch/arm/cpu/$(CPU)/start.o ​​​​​​​
在顶层 Makefile 中被定义为 uboot 所有子目录下 build-in.o 的集合.
libs-y := $(patsubst %/, %/built-in.o, $(libs-y))
相当于将 libs-y 改为所有子目录中 built-in.o 文件.的集合。那么 u
boot-main 就等于所有子目录中 built-in.o 的集合.
终极总结: 这个规则就相当于将以 u-boot.lds 为链接脚本,将 arch/arm/cpu/armv7/start.o 和各个子目录 下的 built-in.o 链接在一起生成 u-boot
uboot 的顶层 Makefile 就分析到这里,重
点是“ make xxx_defconfig ”和“ make ”这两个命令的执行流程:
make xxx_defconfig 用于配置 uboot ,这个命令最主要的目的就是生成 .config 文件。
make :用于编译 uboot ,这个命令的主要工作就是生成二进制的 u-boot.bin 文件和其他的一
些与 uboot 有关的文件,比如 u-boot.imx 等等。
_main 中会调用 board_init_f 函数, board_init_f 函数主要有两个工作:
①、初始化一系列外设,比如串口、定时器,或者打印一些消息等。
②、初始化 gd 的各个成员变量, uboot 会将自己重定位到 DRAM 最后面的地址区域,也就
是将自己拷贝到 DRAM 最后面的内存区域中。这么做的目的是给 Linux 腾出空间,防止 Linux
kernel 覆盖掉 uboot ,将 DRAM 前面的区域完整的空出来。在拷贝之前肯定要给 uboot 各部分
分配好内存位置和大小,比如 gd 应该存放到哪个位置, malloc 内存池应该存放到哪个位置等
等。这些信息都保存在 gd 的成员变量中,因此要对 gd 的这些成员变量做初始化。最终形成一
个完整的内存“分配图”,在后面重定位 uboot 的时候就会用到这个内存“分配图”。
board_f.c   common/board_f.c 中  的 init_sequence_f
第 2 行,setup_mon_len 函数设置 gd 的 mon_len 成员变量,此处为__bss_end -_start,也就
是整个代码的长度。0X878A8E74-0x87800000=0XA8E74,这个就是代码长度。
第 3 行,initf_malloc 函数初始化 gd 中跟 malloc 有关的成员变量,比如 malloc_limit,此函
数会设置 gd->malloc_limit = CONFIG_SYS_MALLOC_F_LEN=0X400。malloc_limit 表示 malloc
内存池大小。 ​​​​​​​
2 行, initr_trace 函数,如果定义了宏 CONFIG_TRACE 的话就会调用函数 trace_init
初始化和调试跟踪有关的内容。
3 行, initr_reloc 函数用于设置 gd->flags ,标记重定位完成。
4 行, initr_caches 函数用于初始化 cache ,使能 cache
5 行, initr_reloc_global_data 函数,初始化重定位后 gd 的一些成员变量。
6 行, initr_barrier 函数, I.MX6ULL 未用到。
7 行, initr_malloc 函数,初始化 malloc
8 行, initr_console_record 函数,初始化控制台相关的内容, I.MX6ULL 未用到,空函数。
9 行, bootstage_relocate 函数,启动状态重定位。
10 行, initr_bootstage 函数,初始化 bootstage 什么的。
11 行, board_init 函数,板级初始化,包括 74XX 芯片, I2C FEC USB QSPI 等。
这里执行的是 mx6ull_alientek_emmc.c 文件中的 board_init 函数。
12 行, stdio_init_tables 函数, stdio 相关初始化。
第 13 行,initr_serial 函数,初始化串口。
14 行, initr_announce 函数,与调试有关,通知已经在 RAM 中运行。
18 行, power_init_board 函数,初始化电源芯片,正点原子的 I.MX6ULL 开发板没有用
到。
19 行, initr_flash 函数,对于 I.MX6ULL 而言,没有定义宏 CONFIG_SYS_NO_FLASH
的话函数 initr_flash 才有效。但是 mx6_common.h 中定义了宏 CONFIG_SYS_NO_FLASH ,所以
此函数无效。
21 行, initr_nand 函数,初始化 NAND ,如果使用 NAND 版本核心板的话就会初始化
NAND
22 行, initr_mmc 函数,初始化 EMMC ,如果使用 EMMC 版本核心板的话就会初始化
EMMC ,串口输出如图 32.2.8.1 所示信息:
32.2.8.1 EMMC 信息输出
从图 32.2.8.1 可以看出,此时有两个 EMCM 设备, FSL_SDHC:0 FSL_SDHC:1
23 行, initr_env 函数,初始化环境变量。
25 行, initr_secondary_cpu 函数,初始化其他 CPU 核, I.MX6ULL 只有一个核,因此此
函数没用。​​​​​​​
第 27 行,stdio_add_devices 函数,各种输入输出设备的初始化,如 LCD driver,I.MX6ULL
使用 drv_video_init 函数初始化 LCD。会输出如图 32.2.8.2 所示信息:
图 32.2.8.2 LCD 信息
28 行, initr_jumptable 函数,初始化跳转表。
29 行 , console_init_r 函 数 , 控 制 台 初 始 化 , 初 始 化 完 成 以 后 此 函 数 会 调 用
stdio_print_current_devices 函数来打印出当前的控制台设备,如图 32.2.8.3 所示:
32.2.8.3 控制台信息
第 31 行,interrupt_init 函数,初始化中断。
第 32 行,initr_enable_interrupts 函数,使能中断。
第 33 行,initr_ethaddr 函数,初始化网络地址,也就是获取 MAC 地址。读取环境变量
“ethaddr”的值。
34 行, board_late_init 函数,板子后续初始化,此函数定义在文件 mx6ull_alientek_emmc.c
中,如果环境变量存储在 EMMC 或者 SD 卡中的话此函数会调用 board_late_mmc_env_init 函数
初始化 EMMC/SD 。会切换到正在时候用的 emmc 设备,代码如图 32.2.8.4 所示:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幽风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值