? bootz 或 help bootz
前确保 uboot 中的环境变量 bootargs 内容如下:
设置bootdelay时间为5s.
新建环境变量也是用setenv。
设置变量为空表示删除掉该环境变量,重启该环境变量就不会存在了。
include/env_default.h定义了很多环境变量,如bootargs,bootdelay,bootcmd等:
由 于 没 有 定 义DEFAULT_ENV_INSTANCE_EMBEDDED和CONFIG_SYS_REDUNDAND_ENVIRONMENT,因此 uchar default_environment[]数组保存环境变量。
1.3.4.1 bootcmd展开
如CONFIG_BOOTCOMMAND等一系列宏都是定义在include/configs/mx6ull_alientek_emmc.h:
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:
①打印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 命令中的数字都是十六进制的
- 命令中的[.b .w .l]对应 byte、word 和 long,也就是分别以 1 个字节、2 个字节、4 个字节来显示内存值.
- address 就是要查看的内存起始地址.
- [# of objects]表示要查看的数据长度:
这个数据长度单位不是字节,而是跟你所选择的显示格式有关。比如你设置要查看的内存长度为20(十六进制为 0x14),如果显示格式为.b 的话那就表示 20 个字节;如果显示格式为.w 的话就表示 20 个 word,也就是 202=40 个字节;如果显示格式为.l 的话就表示 20 个 long,也就是204=80 个字节
写内存,写成功后地址不会自增。
0500e031 表示地址 0x 现在的数据,?后面就可以输入要修改后的数据 0x,输入完成以后按下回车,然后再输入‘q’即可退出。
退出后输入md.l查看。
写内存,写成功后地址会自增。
比如以.l 格式修改从地址 0x 开始的连续 3 个内存块(3*4=12个字节)的数据为 0X0.
输入md命令查看一下:
写一段连续的内存。
比如使用.l 格式将以 0X 为起始地址的 0x10 个内存块(0x10 * 4=64 字节)填充为 0X0A0A0A0A
数据拷贝命令,用于将 DRAM 中的数据从一段内存拷贝到另一段内存中,或者把 Nor Flash 中的数据拷贝到 DRAM 中。
我们使用.l 格式将 0x 处的地址拷贝到 0X 处,长度为 0x10 个内存块(0x10 * 4=64 个字节).
比较两段内存的数据是否相等。
比较 0x 和 0X 这两个地址数据是否相等,比较长度为 0x10 个内存块(16 * 4=64 个字节)
我们再随便挑两段内存比较一下,比如地址0x 和 0x,长度为 0X10.
可以看出,0x 处的数据和 0x 处的数据就不一样.
预先设置号网络相关环境变量:
DHCP 不单单是获取 IP 地址,其还会通过 TFTP 来启动 linux 内核,输入“? dhcp”即
可查看 dhcp 命令详细的信息:
nfs(Network File System)网络文件系统,通过网络将编译好的 linux 镜像和设备树文件下载
到 DRAM 中,然后就可以直接运行。
虚拟机Ubuntu先搭建好nfs服务,详见:nfs服务搭建
下载过程如图下:
下载完成以后查看 0x 地址处的数据,使用命令 md.b 来查看前 0x100 个字节的数据。
我们再用UE打开编译出的zImage,对比一下说明 nfs 命令下载到的zImage 是正确的。
tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中。tftp服务搭建参考:tftp服务搭建
mmc相关命令:
当前选中的 MMC 设备是EMMC,版本为 5.0,容量为 7.1GiB(EMMC为 8GB),速度为 Hz=52MHz,8 位宽的总线。还有一个与 mmc info 命令相同功能的命令:mmcinfo,“mmc”和“info”之间没有空格。
mmc rescan 命令用于扫描当前开发板上所有的 MMC 设备,包括 EMMC 和 SD 卡。
查看当前开发板一共有几个 MMC 设备.
可以看出当前开发板有两个 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。
切换到sd这个mmc后,输入mmc info命令既可以查看sd信息:
可以看到当前 SD 卡为 3.0 版本的,容量为 14.8GiB(16GB 的 SD 卡),4 位宽的总线。
查看mmc分区
读mmc设备中的数据。addr 是数据读取到 DRAM 中的地址,blk 是要读取的块起始地址(十六进制),一个块是 512字节,这里的块和扇区是一个意思,在 MMC 设备中我们通常说扇区,cnt 是要读取的块数量(十六进制)。比如从 EMMC 的第 1536(0x600)个块开始,读取 16(0x10)个块的数据到 DRAM 的0X 地址处
这里我们还看不出来读取是否正确,通过 md.b 命令查看 0x 处的数据就行了,查看 16*512=8192(0x2000)个字节的数据。
可以看出,u-boot.imx 大小为 字节,/512=742,所以我们要向 SD 卡中写入742 个块,如果有小数的话就要加 1 个块。使用命令“mmc write”从 SD 卡分区 0 第 2 个块(扇区)开始烧写,一共烧写 742(0x2E6)个块
烧写成功,重启开发板(从 SD 卡启动),重启以后再输入 version 来查看版本号:
这样就给mmc0也就是sd卡烧录了uboot, 同理要烧录emmc也是同理,切到mmc1即可:
注意:千万不要写 SD 卡或者 EMMC 的前两个块(扇区),里面保存着分区表!
擦除 MMC 设备的指定块, blk 为要擦除的起始块,cnt 是要擦除的数量。
于查询指定 MMC 设备分区的文件系统信息,interface 表示接口,比如 mmc,dev 是查询的设备号,part 是要查询的分区。比如我们要查询 EMMC 分区 1 的文件系统信息:
上图显示mmc1也就是emmc设备的分区1的文件系统为fat32格式。
查询设备分区的目录和文件信息。interface 是要查询的接口,比如 mmc,dev 是要查询的设备号,part 是要查询的分区,directory是要查询的目录。
查看 MMC 设备某个分区的文件系统格式.正点原子 EMMC 核心板上的 EMMC 默认有 3 个分区, 分区 0 格式未知,因为分区 0 存放的 uboot,并且分区 0 没有格式化,所以文件系统格式未知。分区 1 的格式为 fat,分区 1 用于存放 linux 镜像和设备树。分区 2 的格式为 ext4,用于存放 Linux 的根文件系统(rootfs)。
225ms 内读取了 个字节的数据,速度为 28.8MiB/s,速度是非常快的,因为这是从 EMMC 里面读取的,而 EMMC 是 8 位的,速度肯定会很快的。
将 DRAM 中的数据写入到 MMC 设备。
uboot 默认没有使能 fatwrite 命令,需要修改板子配置头文件,比如 mx6ullevk.h、
mx6ull_alientek_emmc.h 等,需要开启宏:
interface 为接口,比如 mmc,dev 是设备号,part 是分区,addr 是要写入的数据在 DRAM中的起始地址,filename 是写入的数据文件名字,bytes 表示要写入多少字节的数据。
比如我们通过nfs or tftp命令下载镜像到DRAM后,通过fatwrite去烧写image:
zImage 大小为 (0X6788f8)个字节(注意,由于开发板系统在不断的更新中,因此zImage 大小不是固定的,一切以实际大小为准),接下来使用命令 fatwrite 将其写入到 EMMC 的分区 1 中,文件名字为 zImage:
完成以后使用“fatls”命令查看一下 EMMC 分区 1 里面的文件:
输入“? nand”即可查看NAND 相关命令:
打印 NAND Flash 信息:
用于切换 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:
设置设备树起始地址:
查看设备树头部信息:
解析出dts内容:
addr 是 Linux 镜像文件在 DRAM 中的位置,initrd 是 initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘-’代替即可,fdt 就是设备树文件在 DRAM 中的地址.
换一张启动方式:从mmc1也就是emmc启动:
同理,如果想从emmc启动linux,设置bootcmd如下:
跳到指定的地址处执行, addr表示DRAM地址
run 命令用于运行环境变量中定义的命令,比如可以通过“run bootcmd”来运行 bootcmd 中的启动命令:
设置了3个环境变量,可以run mybootemmc或者run mybootnand或者run mybootnet来分别从emmc启动,从nand启动,从网络启动。
start 是要测试的 DRAM 开始地址,end 是结束地址,比如我们测试 0X~0X这段内存,输入“mtest ”
可以看出,测试范围为 0X~0X,已经测试了 486 次,如果要结束测试就按下键盘上的“Ctrl+C”键。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/3021.html