当前位置:网站首页 > 技术博客 > 正文

uboot文件结构



image

? bootz 或 help bootz
image

image

image
image
前确保 uboot 中的环境变量 bootargs 内容如下:

 

image

设置bootdelay时间为5s.

 

image

 

新建环境变量也是用setenv。

 

设置变量为空表示删除掉该环境变量,重启该环境变量就不会存在了。

include/env_default.h定义了很多环境变量,如bootargs,bootdelay,bootcmd等:
image
由 于 没 有 定 义DEFAULT_ENV_INSTANCE_EMBEDDED和CONFIG_SYS_REDUNDAND_ENVIRONMENT,因此 uchar default_environment[]数组保存环境变量。

1.3.4.1 bootcmd展开

如CONFIG_BOOTCOMMAND等一系列宏都是定义在include/configs/mx6ull_alientek_emmc.h:
image
uboot 使用了类似 shell 脚本语言的方式来编写的,首先run findfdt, findfdt 是用来查找开发板对应的设备树文件(.dtb),IMX6ULL EVK 的设备树文件为 imx6ull-14x14-evk.dtb,findfdt 内容如下:

 

那么run findfdt就等同于执行setenv fdt_file imx6ull-14x14-evk.dtb。设置fdt_file环境变量等于imx6ull-14x14-evk.dtb。
mmc dev ${mmcdev}用于切换 mmc 设备,mmcdev 为 1,因此这行代码就是:mmc dev 1,也就是切换到 EMMC 上。
先执行 mmc dev ${mmcdev}切换到 EMMC 上,然后使用命令 mmc rescan 扫描看有没有 SD 卡或者 EMMC 存在,如果没有的话就直接跳到else,执行 run netboot,netboot也是一个自定义的环境变量,这个变量是从网络启动 Linux 的。
扫描到EMMC后,run loadbootscript:

其中 mmcdev=1,mmcpart=1,loadaddr=0x,script= boot.scr,因此展开以后就是:

loadbootscript 就是从 mmc1 的分区 1 中读取文件 boot.src 到 DRAM 的 0X 处。但是 mmc1 的分区 1 中没有 boot.src 这个文件,可以使用命令“ls mmc 1:1”查看一下 mmc1 分区1 中的所有文件,看看有没有 boot.src 这个文件。再展开bootscript:

 

由于boot.src 文件不存在,所以 bootscript 也就不会运行。就运行环境变量 loadimage:

loadimage展开:

fatload就是从 mmc1 的分区中读取 zImage 到内存的 0X 处,而 mmc1的分区 1 中存在 zImage。
loadimage执行完,执行mmcboot环境变量,run mmcboot:
image
①打印Booting from mmc ...
②运行环境变量 mmcargs,mmcargs 用来设置 bootargs,后面分析 bootargs 的时候在学习。
③判断boot_fdt是否为yes或者try,根据uboot输出的环境变量信息可知boot_fdt=try。因此执行loadfdt。
④执行loadfdt环境变量,如下:

展开以后就是:

因此 loadfdt 的作用就是从 mmc1 的分区 1 中读取 imx6ull-14x14-evk.dtb 文件并放到 0x处。
⑤loadfdt加载dtb成功后,调用命令 bootz 启动 linux:

展开:

总结一下bootcmd展开:

 

我们可以将bootcmd环境变量进行简化:

 

1.3.4.2 bootargs展开

bootargs 保存着 uboot 传递给 Linux 内核的参数。从emmc启动时,bootargs 环境变量是由 mmcargs 设置的:

其中:

mmcargs展开以后就是:

可以看出环境变量 mmcargs 就是设置 bootargs 的值为“console= ttymxc0, root= /dev/mmcblk1p2 rootwait rw”。
①console=ttymxc0, 综合起来就是设置 ttymxc0(也就是串口 1)作为 Linux 的终端,并且串口波特率设置为 。
②root=/dev/mmcblk1p2 用于指明根文件系统存放在mmcblk1 设备的分区 2 中。在 I.MX6U-ALPHA 开发板中/dev/mmcblk1 表示 EMMC,而/dev/mmcblk1p2 表示EMMC 的分区 2。
③root 后面有“rootwait rw”,rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话mmc 设备还没初始化完成就挂载根文件系统会出错的。rw 表示根文件系统是可以读写的,不加rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。

1.3.4.3 bootdlelay

uboot命令行倒计时

 

注意:uboot 命令中的数字都是十六进制的

  1. 命令中的[.b .w .l]对应 byte、word 和 long,也就是分别以 1 个字节、2 个字节、4 个字节来显示内存值.
  2. address 就是要查看的内存起始地址.
  3. [# of objects]表示要查看的数据长度:

这个数据长度单位不是字节,而是跟你所选择的显示格式有关。比如你设置要查看的内存长度为20(十六进制为 0x14),如果显示格式为.b 的话那就表示 20 个字节;如果显示格式为.w 的话就表示 20 个 word,也就是 202=40 个字节;如果显示格式为.l 的话就表示 20 个 long,也就是204=80 个字节

 

image

写内存,写成功后地址不会自增。

 

image
0500e031 表示地址 0x 现在的数据,?后面就可以输入要修改后的数据 0x,输入完成以后按下回车,然后再输入‘q’即可退出。
退出后输入md.l查看。
image

写内存,写成功后地址会自增。
比如以.l 格式修改从地址 0x 开始的连续 3 个内存块(3*4=12个字节)的数据为 0X0.
image
输入md命令查看一下:
image

写一段连续的内存。

 

比如使用.l 格式将以 0X 为起始地址的 0x10 个内存块(0x10 * 4=64 字节)填充为 0X0A0A0A0A

 

image

数据拷贝命令,用于将 DRAM 中的数据从一段内存拷贝到另一段内存中,或者把 Nor Flash 中的数据拷贝到 DRAM 中。

 

我们使用.l 格式将 0x 处的地址拷贝到 0X 处,长度为 0x10 个内存块(0x10 * 4=64 个字节).

 

image

比较两段内存的数据是否相等。

 

比较 0x 和 0X 这两个地址数据是否相等,比较长度为 0x10 个内存块(16 * 4=64 个字节)

 

image
我们再随便挑两段内存比较一下,比如地址0x 和 0x,长度为 0X10.
image
可以看出,0x 处的数据和 0x 处的数据就不一样.

环境变量 描述 ipaddr 开发板 ip 地址,可以不设置,使用 dhcp 命令来从路由器获取 IP 地址 ethaddr 开发板的 MAC 地址,一定要设置 gatewayip 网关地址 netmask 子网掩码 serverip 服务器 IP 地址,也就是 Ubuntu 主机 IP 地址,用于调试代码

预先设置号网络相关环境变量:

 
 

image

image
DHCP 不单单是获取 IP 地址,其还会通过 TFTP 来启动 linux 内核,输入“? dhcp”即
可查看 dhcp 命令详细的信息:
image

nfs(Network File System)网络文件系统,通过网络将编译好的 linux 镜像和设备树文件下载
到 DRAM 中,然后就可以直接运行。
虚拟机Ubuntu先搭建好nfs服务,详见:nfs服务搭建

 
 

下载过程如图下:
image

下载完成以后查看 0x 地址处的数据,使用命令 md.b 来查看前 0x100 个字节的数据。
image
我们再用UE打开编译出的zImage,对比一下说明 nfs 命令下载到的zImage 是正确的。
image

tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中。tftp服务搭建参考:tftp服务搭建

 
 

image

image

mmc相关命令:

命令 描述 mmc info 输出 MMC 设备信息 mmc read 读取 MMC 中的数据 mmc wirte 向 MMC 设备写入数据 mmc rescan 扫描 MMC 设备 mmc part 列出 MMC 设备的分区 mmc dev 切换 MMC 设备 mmc list 列出当前有效的所有 MMC 设备 mmc hwpartition 设置 MMC 设备的分区 mmc bootbus…… 设置指定 MMC 设备的 BOOT_BUS_WIDTH 域的值 mmc bootpart…… 设置指定 MMC 设备的 boot 和 RPMB 分区的大小 mmc partconf…… 设置指定 MMC 设备的 PARTITION_CONFG 域的值 mmc rst 复位 MMC 设备 mmc setdsr 设置 DSR 寄存器的值

image

当前选中的 MMC 设备是EMMC,版本为 5.0,容量为 7.1GiB(EMMC为 8GB),速度为 Hz=52MHz,8 位宽的总线。还有一个与 mmc info 命令相同功能的命令:mmcinfo,“mmc”和“info”之间没有空格。

mmc rescan 命令用于扫描当前开发板上所有的 MMC 设备,包括 EMMC 和 SD 卡。

查看当前开发板一共有几个 MMC 设备.
image

可以看出当前开发板有两个 MMC 设备:FSL_SDHC:0 和 FSL_SDHC:1 (eMMC),这是因为我现在用的是 EMMC 版本的核心板,加上 SD 卡一共有两个 MMC 设备,FSL_SDHC:0 是 SD卡,FSL_SDHC:1(eMMC)是 EMMC。默认会将 EMMC 设置为当前 MMC 设备,这就是为什么输入“mmc info”查询到的是 EMMC 设备信息,而不是 SD 卡。要想查看 SD 卡信息,就要使用命令“mmc dev”来将 SD 卡设置为当前的 MMC 设备。

选择切换当前emmc设备。

 

[dev]用来设置要切换的 MMC 设备号,[part]是分区号。如果不写分区号的话默认为分区 0。

 

image
切换到sd这个mmc后,输入mmc info命令既可以查看sd信息:
image

可以看到当前 SD 卡为 3.0 版本的,容量为 14.8GiB(16GB 的 SD 卡),4 位宽的总线。

image

查看mmc分区

 

image

 

image

 

读mmc设备中的数据。addr 是数据读取到 DRAM 中的地址,blk 是要读取的块起始地址(十六进制),一个块是 512字节,这里的块和扇区是一个意思,在 MMC 设备中我们通常说扇区,cnt 是要读取的块数量(十六进制)。比如从 EMMC 的第 1536(0x600)个块开始,读取 16(0x10)个块的数据到 DRAM 的0X 地址处

 

image
这里我们还看不出来读取是否正确,通过 md.b 命令查看 0x 处的数据就行了,查看 16*512=8192(0x2000)个字节的数据。
image

 
 

image
可以看出,u-boot.imx 大小为 字节,/512=742,所以我们要向 SD 卡中写入742 个块,如果有小数的话就要加 1 个块。使用命令“mmc write”从 SD 卡分区 0 第 2 个块(扇区)开始烧写,一共烧写 742(0x2E6)个块

 

image

烧写成功,重启开发板(从 SD 卡启动),重启以后再输入 version 来查看版本号:
image
这样就给mmc0也就是sd卡烧录了uboot, 同理要烧录emmc也是同理,切到mmc1即可:

 

注意:千万不要写 SD 卡或者 EMMC 的前两个块(扇区),里面保存着分区表!

 

擦除 MMC 设备的指定块, blk 为要擦除的起始块,cnt 是要擦除的数量。

 

于查询指定 MMC 设备分区的文件系统信息,interface 表示接口,比如 mmc,dev 是查询的设备号,part 是要查询的分区。比如我们要查询 EMMC 分区 1 的文件系统信息:

 

image
上图显示mmc1也就是emmc设备的分区1的文件系统为fat32格式。

 

查询设备分区的目录和文件信息。interface 是要查询的接口,比如 mmc,dev 是要查询的设备号,part 是要查询的分区,directory是要查询的目录。

 

image

 

查看 MMC 设备某个分区的文件系统格式.正点原子 EMMC 核心板上的 EMMC 默认有 3 个分区, 分区 0 格式未知,因为分区 0 存放的 uboot,并且分区 0 没有格式化,所以文件系统格式未知。分区 1 的格式为 fat,分区 1 用于存放 linux 镜像和设备树。分区 2 的格式为 ext4,用于存放 Linux 的根文件系统(rootfs)。

 

image

 
 

image

225ms 内读取了 个字节的数据,速度为 28.8MiB/s,速度是非常快的,因为这是从 EMMC 里面读取的,而 EMMC 是 8 位的,速度肯定会很快的。

将 DRAM 中的数据写入到 MMC 设备。
uboot 默认没有使能 fatwrite 命令,需要修改板子配置头文件,比如 mx6ullevk.h、
mx6ull_alientek_emmc.h 等,需要开启宏:

 

image

 

interface 为接口,比如 mmc,dev 是设备号,part 是分区,addr 是要写入的数据在 DRAM中的起始地址,filename 是写入的数据文件名字,bytes 表示要写入多少字节的数据。

比如我们通过nfs or tftp命令下载镜像到DRAM后,通过fatwrite去烧写image:
image
zImage 大小为 (0X6788f8)个字节(注意,由于开发板系统在不断的更新中,因此zImage 大小不是固定的,一切以实际大小为准),接下来使用命令 fatwrite 将其写入到 EMMC 的分区 1 中,文件名字为 zImage:

 

image

完成以后使用“fatls”命令查看一下 EMMC 分区 1 里面的文件:
image

 

image

输入“? nand”即可查看NAND 相关命令:
image

打印 NAND Flash 信息:
image

用于切换 NAND Flash,如果你的板子支持多片 NAND 的话就可以使用此命令来设置当前所使用的 NAND。

nand erase 命令用于擦除 NAND Flash,NAND Flash 的特性(位翻转,只能由1变成0,而不能由0变成1)决定了在向 NAND Flash 写数据之前一定要先对要写入的区域进行擦除.

 
 

addr 是要写入的数据首地址,off 是 NAND 中的目的地址,size 是要写入的数据大小。

编译出来 NAND版本的 kernel 和 dtb 文件,在烧写之前要先对 NAND 进行分区,也就是规划好 uboot、linux kernel、设备树和根文件系统的存储区域,I.MX6U-ALPHA 开发板出厂系统 NAND 分区如下:

 

一共有六个分区,第一个分区存放 uboot,地址范围为 0x0~0x3FFFFF(共 4MB);第二个分区存放 env(环境变量),地址范围为 0x~0x(共 128KB);第三个分区存放 logo(启动图标),地址范围为 0x~0x51FFFF(共 1MB);第四个分区存放 dtb(设备树),地址范围为0x~0x61FFFF(共 1MB);第五个分区存放 kernel(也就是 linux kernel),地址范围为0x~0xE1FFFF(共 8MB);剩下的所有存储空间全部作为最后一个分区,存放 rootfs(根文件系统)。

 

这里我们擦除了 8MB 的空间,因为一般 zImage 就是 6,7MB 左右,8MB 肯定够了,如果不够的话就再多擦除一点就行了。同理烧录dtb:

 
 
 

image

设置设备树起始地址:

 

查看设备树头部信息:

 

image

解析出dts内容:
image

 

addr 是 Linux 镜像文件在 DRAM 中的位置,initrd 是 initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘-’代替即可,fdt 就是设备树文件在 DRAM 中的地址.

 

image
换一张启动方式:从mmc1也就是emmc启动:

 

image

 
 
 

image

同理,如果想从emmc启动linux,设置bootcmd如下:

 

image

 

跳到指定的地址处执行, addr表示DRAM地址

 

image

run 命令用于运行环境变量中定义的命令,比如可以通过“run bootcmd”来运行 bootcmd 中的启动命令:

 

设置了3个环境变量,可以run mybootemmc或者run mybootnand或者run mybootnet来分别从emmc启动,从nand启动,从网络启动。

 

start 是要测试的 DRAM 开始地址,end 是结束地址,比如我们测试 0X~0X这段内存,输入“mtest ”
image
可以看出,测试范围为 0X~0X,已经测试了 486 次,如果要结束测试就按下键盘上的“Ctrl+C”键。

版权声明


相关文章:

  • dos文件转换成pdf2024-11-27 07:30:00
  • 跳表数据结构与算法2024-11-27 07:30:00
  • 重载乘法运算符的函数原型声明2024-11-27 07:30:00
  • 红黑树的概念2024-11-27 07:30:00
  • opengl教学视频2024-11-27 07:30:00
  • 什么是序列化与反序列化2024-11-27 07:30:00
  • 运算符=重载2024-11-27 07:30:00
  • tftp工具下载2024-11-27 07:30:00
  • formdataparam2024-11-27 07:30:00
  • 内置声卡精调2024-11-27 07:30:00