一、UBOOT简介
U-boot全称 Universal Boot Loader,是遵循GPL条款的开放源码项目,uboot 是一个裸机代码,可以看作是一个裸机综合例程,执行启动内核的功能。
补充:GPL条款(GNU General Public License,GNU通用公共许可证)是一种自由软件许可证,而GNU代表“GNU's Not Unix”,是开源的操作系统项目,大多数GNU系统使用开源的Linux内核,GPL条款保证了开源内核的自由性,使用GPL条款后,
-
源代码公开:在分发软件时必须提供源代码,或者提供方便获取源代码的方式。
-
修改后仍使用GPL:对软件进行修改后,必须使用相同的GPL许可证分发。
-
保留版权和许可证:必须在分发软件时保留原始版权声明和GPL许可证条款。
由上可知,UBOOT是通用的引导程序,对系统架构没有要求,因为适用,所以流行。
二、UBOOT源码结构
重点包括:
系统架构、CPU、board、各个开发板的配置文件XXX-defconfig、makefile
三、Uboot支持多种启动方式
项目中知道的有 SPI Flash/eMMC/Nvme/SD/Hard Disk/U-Disk/net,要用到的内核映像在哪,就是决定怎么启动。
四、UBOOT启动流程
uBoot 启动过程一般包括以下几个主要步骤:
-
硬件初始化:uBoot 首先会执行一系列的硬件初始化操作,包括对处理器、内存、外设等硬件组件进行初始化配置,以便系统能够正常运行。
-
加载引导程序:uBoot 会从存储介质(如闪存、SD 卡、网络等)中加载引导程序。这个引导程序通常是一个二进制文件,负责进一步引导系统。
-
设置启动参数:uBoot 会设置操作系统启动所需的参数,如内核镜像地址、启动参数、根文件系统的位置等。这些参数通常通过环境变量进行配置。
-
加载内核镜像:uBoot 会从指定位置加载 Linux 内核镜像到内存中。内核镜像是 Linux 操作系统的核心组件,它包含了操作系统的核心功能和驱动程序。
-
启动内核:一旦内核镜像被加载到内存中,uBoot 会将控制权转交给内核,让内核开始执行。此时,操作系统开始初始化并运行。
-
启动根文件系统:内核启动后,它会挂载根文件系统,根据 uBoot 配置的参数找到根文件系统所在的位置,并加载进内存。根文件系统包含了操作系统的文件和目录结构,是操作系统的基础。
五、UBOOT命令使用
信息查询指令
进入 uboot 的命令行模式以后输入“help”或者“?”,然后按下回车即可查看当前 uboot 所支持的命令,如图 所示:
输入“help(或?) 命令名”既可以查看命令的详细用法
环境变量操作命令
环境变量的操作涉及到两个命令:setenv 和 saveenv,命令 setenv 用于设置或者修改环境变量的值。命令 saveenv 用于保存修改后的环境变量,一般环境变量是存放在外部 flash 中的,uboot 启动的时候会将环境变量从 flash 读取到 DRAM 中。所以使用命令 setenv 修改的是 DRAM中的环境变量值,修改以后要使用 saveenv 命令将修改后的环境变量保存到 flash 中,否则的话uboot 下一次重启会继续使用以前的环境变量值。
有时候我们修改的环境变量值可能会有空格,比如 bootcmd、bootargs 等,这个时候环境变量值就得用单引号括起来,比如下面修改环境变量 bootargs 的值:
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv
上面命令设置 bootargs 的值为“console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw”,其中“console=ttymxc0,115200”、“root=/dev/mmcblk1p2”、“rootwait”和“rw”相当于四组“值”,这四组“值”之间用空格隔开,所以需要使用单引号‘’将其括起来,表示这四组“值”都属于环境变量 bootargs。
网络操作命令
uboot 是支持网络的,我们在移植 uboot 的时候一般都要调通网络功能,因为在移植 linux kernel 的时候需要使用到 uboot 的网络功能做调试。
1、ping 命令
开发板的网络能否使用,是否可以和服务器(Ubuntu 主机)进行通信,通过 ping 命令就可以验证,直接 ping 服务器的 IP 地址即可。
注意!只能在 uboot 中 ping 其他的机器,其他机器不能 ping uboot,因为 uboot 没有对 ping
命令做处理,如果用其他的机器 ping uboot 的话会失败!
补充:
Ping命令是一种网络诊断工具,用于测试主机之间的连通性。它的实现原理基于ICMP(Internet Control Message Protocol,Internet控制消息协议)。
以下是Ping命令的实现原理:
-
发送ICMP Echo请求:Ping命令向目标主机发送一个ICMP Echo请求。ICMP Echo请求的作用是请求目标主机返回一个ICMP Echo Reply响应。
-
接收ICMP Echo Reply响应:目标主机收到ICMP Echo请求后,如果目标主机正常工作并且网络连接正常,它将会返回一个ICMP Echo Reply响应。ICMP Echo Reply中包含了原始请求的数据,以便发送主机可以确认响应是否与请求匹配。
-
计算往返时间(Round-Trip Time,RTT):发送主机接收到ICMP Echo Reply响应后,它会计算往返时间(RTT),即从发送请求到接收响应的时间。RTT通常用于衡量网络延迟。
-
显示结果:Ping命令将收到的ICMP Echo Reply响应和计算得到的往返时间显示给用户。这些信息可以用来判断网络连接的质量和稳定性。
需要注意的是,Ping命令通常需要在发送主机和目标主机之间存在双向的网络连接,并且目标主机需要正确地响应ICMP Echo请求。如果目标主机的网络连接出现故障或者目标主机配置了防火墙,可能会导致Ping命令无法正常工作。
2、nfs 命令
nfs(Network File System)网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源,比如我们将 linux 镜像和设备树文件放到 Ubuntu 中,然后在 uboot 中使用 nfs 命令将 Ubuntu 中 的 linux 镜像和设备树下载到开发板的 DRAM 中。
这样做的目的是为了方便调试 linux 镜像和设备树,也就是网络调试,通过网络调试是 Linux 开发中最常用的调试方法。原因是嵌入式 linux开发不像单片机开发,可以直接通过 JLINK 或 STLink 等仿真器将代码直接烧写到单片机内部的 flash 中,嵌入式 Linux 通常是烧写到 EMMC、NAND Flash、SPI Flash 等外置 flash 中,但是嵌入式 Linux 开发也没有 MDK,IAR 这样的 IDE,更没有烧写算法,因此不可能通过点击一个“download”按钮就将固件烧写到外部 flash 中。虽然半导体厂商一般都会提供一个烧写固件的软件,但是这个软件使用起来比较复杂,这个烧写软件一般用于量产的。其远没有 MDK、IAR的一键下载方便,在 Linux 内核调试阶段,如果用这个烧写软件的话将会非常浪费时间,而这个时候网络调试的优势就显现出来了,可以通过网络将编译好的 linux 镜像和设备树文件下载到 DRAM 中,然后就可以直接运行。
在使用 之前需要开启 Ubuntu 主机的 NFS 服务,并且要新建一个 NFS 使用的目录,以后所有要通过NFS 访问的文件都需要放到这个 NFS 目录中。
nfs 80800000 192.168.1.253:/home/zuozhongkai/linux/nfs/zImage
命 令 中 的 “ 80800000 ”表示 zImage 保 存在DRAM中的地址 ,“192.168.1.253:/home/zuozhongkai/linux/nfs/zImage”表示 zImage 在 192.168.1.253 这个主机中, 路径为/home/zuozhongkai/linux/nfs/zImage。
3、tftp 命令
tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中,只是 tftp 命令使用的 TFTP 协议,Ubuntu 主机作为 TFTP 服务器。因此需要在 Ubuntu 上搭建 TFTP 服务器
和nfs命令相比,都是开启服务之后,创建文件夹存放映像文件,但和nfs 命令的区别在于,tftp 命令不需要输入文件在 Ubuntu 中的完整路径,只需要输入文件名即可
tftp 80800000 zImage
EMMC和SD卡操作
如果 EMMC 里面烧写了 Linux 系统的话,EMMC 是有 3 个分区的,第 0 个分区存放 uboot,第 1 个分区存放Linux 镜像文件和设备树,第 2 个分区存放根文件系统。
BOOT 操作命令
uboot 的本质工作是引导 Linux,所以 uboot 肯定有相关的 boot(引导)命令来启动 Linux。常用的跟 boot 有关的命令有:bootz、bootm 和 boot。
1、bootz命令
bootz 命令用于启动 zImage 镜像文件,
bootz [addr [initrd[:size]] [fdt]]
addr 是 Linux 镜像文件在 DRAM 中的位置,initrd 是 initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘-’代替即可,fdt 就是设备树文件在 DRAM 中的地址。
2、bootm 命令
bootm 和 bootz 功能类似,但是 bootm 用于启动 uImage 镜像文件。
补充:
zImage:更轻便
- zImage是Linux内核的一种压缩格式。它是一种轻量级的内核映像文件,通常用于嵌入式系统或者对启动速度有较高要求的场景。
- 在编译内核时,可以选择生成zImage格式的内核映像文件。这个文件通常命名为"zImage",并且是一个压缩过的内核镜像。
uImage:更灵活更扩展
- uImage是一种带有头部和校验和的Linux内核映像文件格式,用于各种体系结构。
- 与zImage/bzImage/vmlinuz相比,uImage提供了更多的元数据,如内核命令行参数、内核的加载地址等。
3、boot 命令
boot 命令也是用来启动 Linux 系统的,只是 boot 会读取环境变量 bootcmd 来启动 Linux 系统,bootcmd 是一个很重要的环境变量!其名字分为“boot”和“cmd”,也就是“引导”和“命令”,说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。比如我们要想使用 tftp 命令从网络启动 Linux 那么就可以设置 bootcmd 为“tftp80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000”,然后使用 saveenv 将 bootcmd 保存起来。然后直接输入 boot 命令即可从网络启动Linux 系统。
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb;
bootz 80800000 - 83000000'
saveenv
boot
boot命令是在设置好环境变量bootcmd基础上执行的,boot命令会读取bootcmd参数启动Linux。
参考链接:全网最全面最易懂的U-Boot解读_uboot-CSDN博客