一. UBoot 详解
1.1 概念
Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段 bootl oader 程序。这段 bootloader 程序会先初始化 DDR 等外设,然后将 Linux 内核从 flash(NAND, NOR FLASH,SD,MMC 等) 拷贝到 DDR 中,最后启动 Linux 内核。
bootloader 最主要的工作就是启动 Linux 内核,bootloader 和 Linux 内核的关系就跟 PC 上的 BIOS 和 Windows 的关系一样,bootloader 就相当于 BIOS。
uboot是bootloader的一种,主要作用是在内核加载前对硬件设备初始化,并为内核的
运行提供引导功能
1.2 IMX6ULL 核心板资源
1.2.1 核心板
IMX6ULL 的核心板资源
主控芯片,采用BGA封装
24MHz晶振
32.768KHz,RTC使用,日历等等,这个时钟不变
8 GB EMMC,flash (ROM),永久保存数据
512M DDR3L,(RAM),运存,断电数据丢失
1.2.2 主控芯片内部
在主控芯片内部,还有:
ROM:96 KB,存放第一阶段启动代码(固化代码,不可改),运行完此代码之后再根据拨码开关的选择到指定位置去运行(SD卡等)
OCRAM:128 KB,也叫 IRAM

1.3 IMX6ULL 启动流程
iMX6ULL 必须用 SPL + U‑Boot 组合,因为片内 RAM 只有 128KB,装不下完整
U‑Boot,必须分两阶段
SPL(Secondary Program Loader):第二阶段程序加载

二. U-Boot 与内核文件的制作
2.1 U-Boot 的制作
基本流程:
1、解压uboot压缩包,并进入uboot源码目录
tar -zxvf uboot.tar.gz
cd uboot
2、uboot图形界面是基于ncurses库编写的,所以需要先安装该库
sudo apt-get install libncurses5-dev
3、编译uboot源码
distclean 的作用:目的是清除工程,将源码恢复到原始状态,类似复位
CROSS_COMPILE:设置交叉编译工具链
V=0:控制编译输出的详细程度, 0表示启动静默/精简输出模式, 1表示完整的编译命令,便于调试
第二句的作用:生成 .config 配置文件,文件中指定了哪些需要编译,原来的.c很多,只需要编译ARM架构下面的imx6u的.c即可
最后一句的作用:使用16核来编译uboot
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig
make V=0 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
4、生成的文件
生成的文件主要位于 uboot 顶层目录:u-boot.imx,u-boot.lds,u-boot.map等
注意:其中 u-boot.bin 就是编译出来的 uboot 二进制文件。uboot 是个裸机程序,因此需要在其前面加上头部(IVT、DCD 等数据)才能在 IMX6ULL 上执行,u-boot.imx 文件就是添加头部以后的 u-boot.bin,u-boot.imx 就是最终要烧写到开发板中的 uboot 镜像文件
2.2 内核文件的制作
基本流程:
1、先安装必要的工具
sudo apt-get install lzop
2、把linux内核复制到虚拟机,解压操作
tar -zxvf linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek.tar.gz
ls
3、编译的命令
具体思路和 U-Boot 文件的制作一样:先清理工程,再生成配置文件,最后编译即可
cd linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig #内核地图,驱动,模块和c文件的关系
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
4、生成结果
结果文件主要有2个:
内核镜像文件: arch/arm/boot/zImage
设备树文件: arch/arm/boot/dts/imx6ull-alientek-emmc.dtb文件
还有相关的驱动文件 *.ko
5、将编译好的两个文件拷贝到tftp管理目录下
cp arch/arm/boot/zImage ~/tftpboot/ -rf
cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~/tftpboot/ -rf
6、重新启动开发板,每次从Ubuntu管理目录下载最新版本的内核和设备树文件
三. U-Boot 启动详解
总共三个阶段
3.1 阶段一 (Boot ROM 阶段)
这一步不属于 U‑Boot,但必须先做,才能启动 U‑Boot。
这一步的作用:
1、检测启动模式(SD 卡、 EMMC、 NAND、 QSPI)。 sd/emmc设备没有完全初始化,内部程序写死,只会读取前面一部分内容根据拨码开关有关,决定了启动方式,为了第二阶段到指定的启动设备上去加载U-Boot
2、初始化最基础的时钟 arm_pll 396M, system_PLL 528M
3、读取启动设备的第一个镜像(SPL),从片上的 Rom 中
4、把 SPL 加载到片内 RAM(运存)(OCRAM 0x00900000)
5、跳转到 SPL 执行

3.2 阶段二 U‑Boot SPL(第一阶段 U‑Boot)
SPL = Secondary Program Loader,第二阶段程序加载器
SPL:加载UBoot的前4K
运行位置:片内 RAM(OCRAM)
核心使命:初始化 DDR,然后加载完整 U‑Boot

SPL 完成的详细工作:u-boot.imx = IVT+BOOTData+DCD
1、关闭看门狗,防止芯片自动复位。
2、设置 CPU 主频 / 系统时钟:iMX6ULL 通常设为 792MHz,初始化 PLL 锁相环。
3、初始化 IOMUXC 引脚复用:配置 DDR 引脚、启动设备引脚。
4、初始化 DDR 控制器 + DDR 校准:没有 DDR,后面的 U‑Boot 和 Linux 都无法运行。
5、初始化 NAND/SD/EMMC/QSPI,完全初始化 sd/emmc控制器:为了读取完整 U‑Boot 镜像。
6、从 Flash/SD卡中读取完整 U‑Boot 到 DDR,加载地址:DDR=0x87800000
7、跳转到 DDR 中的 U‑Boot 执行,SPL 使命结束
3.3 阶段三 U‑Boot 主程序(第二阶段,真正的 U‑Boot)
运行位置: DDR 0x87800000
所做的工作:
1.加载 Linux 内核和设备树到内存
加载 zImage 到:0x80800000;加载 dtb 到 0x83000000
2.读取环境变量,解析启动命令
3.传递启动参数给内核
4.启动 Linux 内核
3.4 整体所完成的工作
1.初始化DDR(最关键) bootrom
2.初始化时钟(CPU主频、总线时钟) bootrom
3.初始化启动设备(SD/EMMC/NAND) bootrom+
4.加载 Linux 内核和设备树到内存
加载 zImage 到:0x80800000;加载 dtb 到 0x83000000
5.传递启动参数给内核
6.启动 Linux 内核
四. 解释IVT、BOOTData与DCD
4.1 IVT (Image Vector Table,镜像向量表)
4.1.1 什么是 IVT
可以把它理解为一个“地址簿”或“导航地图”。位于启动设备的特定偏移位置(例如SD卡/EMMC是从1KB偏移处开始)。BootROM启动后,会首先在固定位置找到这个地址簿。
4.1.2 作用
为BootROM提供引导所需的所有关键信息的地址。
4.1.3 关键字段
IVT内部包含了多个32位的地址指针,主要包括:

简单来说,BootROM通过读取IVT,才知道去哪里找真正的用户程序(entry),如何去配置硬件(dcd)以及程序有多大(boot_data)
4.2 DCD (Device Configuration Data,设备配置数据)

4.3 IVT、 DCD与Boot Data的协作关系


五. U-Boot 阶段常用命令
5.1 环境变量操作命令

eg:
env default -a #uboot 变量回复默认
saveenv# 保存变量
reset#重启uboot
setenv ipaddr 192.168.1.50 # 设置开发板ip地址
setenv ethaddr 00:04:9f:04:d2:35#设置开发板网卡mac地址
setenv gatewayip 192.168.1.1 #设置开发板网关
setenv netmask 255.255.255.0#设置开发板子网掩码
setenv serverip 192.168.1.100#设置pc段的ip地址
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.100:/home/linux/nfs/rootfs,v3,proto=tcp rw ip=192.168.1.50:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off' #设置根文件系统的位置
setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 – 83000000' #设置 下载zImage ,dtb
saveenv #保存变量
reset#重启uboot
详解:
1、setenv bootargs 'console=ttymxc0,115200 root=/dev/nfsnfsroot=192.168.1.100:/home/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.50:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
注意:bootargs保存着uboot传递给Linux内核的参数,
作用:设置根文件系统位置,从nfs网络中启动Linux系统
启动参数
console:表示控制台
ttymxc0:表示发到串口0,波特率:115200
网络文件来自192.168.1.100
可读可写
2、setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ullalientekemmc.dtb;bootz 80800000 – 83000000'
注意:bootcmd保存着uboot默认命令, uboot倒计时结束以后就会执行bootcmd中的命
令
作用:设置下载zImage,dtb;从网络中下载内核、设备树、启动
启动命令
倒计时结束,走这条命令
去PC机下载文件
内核放在80800000这个地址
设备树放在83000000这个地址
bootz:启动; -:表示不使用文件系统,上面一条指令已经配置过了
5.2 网络命令

5.3 boot命令

六. Linux 启动总流程
1、bootROM阶段:
a. IMX6U平台在芯片0x0地址处接了96k bootROM,里面是厂商固化的启动代码,上
电启动后触发复位异常。
b. 根据用户设置的启动方式,将EMMC或SD卡存储器的前4k代码拷贝到SRAM中执行,
其中包括(IVT镜像入口地址: 0X877FF400 (0x8780 0000 -3k) 、 DCD:
DDR基础初始化代码、 BootData:镜像加载地址及大小)。
c. 根据BootData将SPL加载到OCRAM中。 (on-chip ram)
2、SPL阶段:
a. 在OCRAM中运行SPL代码。
b. 对DDR做深度初始化。
c. 将完整的uboot拷贝到87800000地址
d. 重新定位链接地址 (board_init_f -> relocate_code,relocate_vectors)
3、uboot阶段:
a. 重新设置异常向量表,执行reset复位异常
b. 运行uboot完成对硬件设备初始化(网卡,串口,屏幕等外设)
c. 与用户交互,执行bootcmd加载内核
4、内核阶段:
a. 运行内核代码
5、文件系统阶段:
a. 执行init进程
b. 启动配置文件/etc/inittab
c. 运行/etc/init.d/rcS脚本
d. 挂载/etc/fatab文件
e. 启动终端
网硕互联帮助中心




评论前必须登录!
注册