文章目录
1.U-boot启动流程:最终会调用arch/arm/lib/crt0.S文件中的_main函数
# recipes-bsp/u-boot/u-boot-bird_2020.04.bb: 引用了u-boot-common.inc, 如下变量重新赋值
LICENSE = "GPLv2+"
LIC_FILES_CHKSUM = "file://Licenses/gpl-2.0.txt;md5=b234ee4d69f5fce4486a80fdaf4a4263"
SRCBRANCH = "master"
UBOOT_SRC ?= "git:${BSPDIR}/bird-imx-uboot;protocol=file" # 指向本地fsl-release-yocto/bird-imx-uboot路径
SRC_URI = "${UBOOT_SRC};branch=${SRCBRANCH}"
SRCREV = "${AUTOREV}" # 通过bird-imx-uboot下使用git log查看(commit id),也可以将SRCREV设置为SRCREV="${AUTOREV}"使用代码分支下的最新版本
将生成的u-boot.bin文件烧写到SD卡中,设置imx6ull从SD卡启动(芯片boot mode引脚做好,看手册),当imx6ull上电后,芯片内部的boot rom程序将SD卡中的u-boot.imx文件(u-boot.bin转换为u-boot.imx需要相应的转换)拷贝到链接地址处,就可以开始运行U-Boot。
./imxdownload(nxp官网工具) u-boot.bin /dev/sdb1 # 在Ubuntu中使用ls /dev/sd*确定插入的SD卡设备。 烧写完成后,将SD卡插入嵌入式Linux板卡,配置从SD卡启动的方式,断电复位板卡即可
1.1 board_init_f函数:_main中会调用board_init_f()函数,该函数位于common/board_f.c中,主要用来初始化DDR,定时器,完成代码拷贝等
initcall_run_list函数来运行初始化序列init_sequence_f里的一系列函数,只要init_sequence_f所定义的其中一个函数出错,U-Boot启动就会停止,initcall_run_list函数位于include/initcall.h中,其实就是一个循环。在init_sequence_f里定义了一系列的初始化函数如display_options、display_text_info、print_cpuinfo、show_board_info等用于在U-Boot启动时输出一些启动信息至控制台。
在U-Boot的配置文件(例如:mx6ull_14x14_evk_deconfig)中定义CONFIG_OF_CONTROL=y时,将采用设备树的方式来提供驱动数据,如下fdtdec_setup()函数位于/lib/fdtdec.c中通过设置全局变量gd->fdt_blob的值,设置设备树的存放地址为u-boot的末尾(通过对比编译生成的u-boot.bin和u-boot-nodtb.bin也可以看到在u-boot.bin的末尾增加了设备树文件)。
1.2 board_init_r函数:board_init_f中并没有初始化完所有的外设,还需要通过board_init_r来完成
在board_init_r函数中同样通过调用initcall_run_list函数来执行初始化序列init_sequence_r,在board_init_r函数的最后会调用run_main_loop函数,run_main_loop会进入一个main_loop死循环,在main_loop函数里会根据是否按下回车键进入uboot命令模式。还是在倒计时结束之后,通过执行环境变量bootcmd里的命令,bootcmd里面保存着默认的启动命令用于启动Linux内核。
U-Boot的环境变量是用来存常用的参数变量,U-Boot会使用这些参数变量进行配置。启动过程中将env从静态存储器中读出放到RAM中,之后在U-Boot下对env的操作(如printenv、editenv、setenv)都是对RAM中env的操作,只有在执行saveenv时才会将RAM中的env重新写入静态存储器(nand flash、nor flash、eeprom、mmc)。
// include/environment.h中定义了env_t
# define ENV_SIZE ((CONFIG_ENV_SIZE - ENV_HEADER_SIZE) & ~(16 - 1)) // CONFIG_ENV_SIZE是环境变量的总长度,在如/include/configs/mx6ullevk.h配置文件中定义
typedef struct environment_s {
uint32_t crc; /* CRC32 over data bytes */
// 头4个Byte是环境变量CRC校验码,后面剩余的控制全部用来存储环境变量。CRC校验码是U-Boot在saveenv时计算出来,然后写入对应的静态存储器,所以在第一次启动U-Boot时crc校验会出错,因为U-Boot从静态存储器读入的数据是随机没有意义的,执行U-Boot后重启uboot,crc校验就正确了。
unsigned char data[ENV_SIZE]; /* Environment data */
} env_t
static int initr_env(void) // 初始化环境变量函数
{
if (should_load_env()) // 总是返回1
env_relocate(