1.1 help或者?#
1.1.1 help+具体命令#
? bootz 或 help bootz
1.2 信息查询#
1.2.1 bdinfo#
1.2.2 printenv#
前确保 uboot 中的环境变量 bootargs 内容如下:console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw
1 | cp arch/arm/boot/zImage /home/zuozhongkai/linux/tftpboot/ -f |
1.2.3 version#
1.3 环境变量#
1.3.1 setenv设定环境变量#
设置bootdelay
时间为5s.
1 | setenv bootdelay 5 |
1 | setenv author zuozhongkai |
新建环境变量也是用setenv。
1.3.2 saveenv保存环境变量#
1.3.3 setenv删除环境变量#
1 | setenv author |
设置变量为空表示删除掉该环境变量,重启该环境变量就不会存在了。
1.3.4 环境变量原理#
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
内容如下:
1 | "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
:
loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
其中 mmcdev=1,mmcpart=1,loadaddr=0x80800000,script= boot.scr,因此展开以后就是:
loadbootscript=fatload mmc 1:1 0x80800000 boot.scr;
loadbootscript 就是从 mmc1 的分区 1 中读取文件 boot.src 到 DRAM 的 0X80800000 处。但是 mmc1 的分区 1 中没有 boot.src 这个文件,可以使用命令ls mmc 1:1
查看一下 mmc1 分区1 中的所有文件,看看有没有 boot.src 这个文件。再展开bootscript:
1 | bootscript=echo Running bootscript from mmc ...; |
由于boot.src 文件不存在,所以 bootscript 也就不会运行。就运行环境变量 loadimage:loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
loadimage展开:loadimage=fatload mmc 1:1 0x80800000 zImage
fatload就是从 mmc1 的分区中读取 zImage 到内存的 0X80800000 处,而 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=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
展开以后就是:loadfdt=fatload mmc 1:1 0x83000000 imx6ull-14x14-evk.dtb
因此 loadfdt 的作用就是从 mmc1 的分区 1 中读取 imx6ull-14x14-evk.dtb 文件并放到 0x83000000处。
⑤loadfdt加载dtb成功后,调用命令 bootz 启动 linux:
bootz ${loadaddr} - ${fdt_addr};
展开:
bootz 0x80800000 - 0x83000000 (注意‘-’前后要有空格)
总结一下bootcmd展开:
1 | mmc dev 1 //切换到 EMMC |
我们可以将bootcmd环境变量进行简化:
1 | #define CONFIG_BOOTCOMMAND \ |
或者:setenv bootcmd 'mmc dev 1; fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ullalientek-emmc.dtb; bootz 80800000 - 83000000;'
1.3.4.2 bootargs展开#
bootargs 保存着 uboot 传递给 Linux 内核的参数。从emmc启动时,bootargs 环境变量是由 mmcargs 设置的:mmcargs=setenv bootargs console=${console},${baudrate} root=${mmcroot}
其中:console=ttymxc0,baudrate=115200,mmcroot=/dev/mmcblk1p2 rootwait rw
mmcargs展开以后就是:mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw
可以看出环境变量 mmcargs 就是设置 bootargs 的值为console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw
。
①console=ttymxc0,115200
综合起来就是设置 ttymxc0(也就是串口 1)作为 Linux 的终端,并且串口波特率设置为 115200。
②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命令行倒计时
1.4 内存操作#
1.4.1 md#
md[.b, .w, .l] address [# of objects]
注意:uboot 命令中的数字都是十六进制的
- 命令中的
[.b .w .l]对应 byte、word 和 long
,也就是分别以 1 个字节、2 个字节、4 个字节来显示内存值. - address 就是要查看的内存起始地址.
[# of objects]
表示要查看的数据长度:
这个数据长度单位不是字节,而是跟你所选择的显示格式有关。比如你设置要查看的内存长度为20(十六进制为 0x14),如果显示格式为.b 的话那就表示 20 个字节;如果显示格式为.w 的话就表示 20 个 word,也就是 20*2=40 个字节
;如果显示格式为.l 的话就表示 20 个 long,也就是20*4=80
个字节
1 | md.b 80000000 10 //读16字节 |
1.4.2 nm命令#
写内存,写成功后地址不会自增。
1 | nm [.b, .w, .l] address |
0500e031 表示地址 0x80000000 现在的数据,?
后面就可以输入要修改后的数据 0x12345678,输入完成以后按下回车,然后再输入‘q’即可退出。
退出后输入md.l查看。
1.4.3 mm命令#
写内存,写成功后地址会自增。
比如以.l 格式修改从地址 0x80000000 开始的连续 3 个内存块(3*4=12个字节)
的数据为 0X05050505.
输入md命令查看一下:
1.4.4 mw命令#
写一段连续的内存。
1 | mw [.b, .w, .l] address value [count] |
比如使用.l 格式将以 0X80000000 为起始地址的 0x10 个内存块(0x10 * 4=64 字节)
填充为 0X0A0A0A0A
1 | mw.l 80000000 0A0A0A0A 10 |
1.4.5 cp命令#
数据拷贝命令,用于将 DRAM 中的数据从一段内存拷贝到另一段内存中,或者把 Nor Flash 中的数据拷贝到 DRAM 中。
cp [.b, .w, .l] source target count
我们使用.l 格式将 0x80000000 处的地址拷贝到 0X80000100 处,长度为 0x10 个内存块(0x10 * 4=64 个字节).
cp.l 80000000 80000100 10
1.4.6 cmp命令#
比较两段内存的数据是否相等。
cmp [.b, .w, .l] addr1 addr2 count
比较 0x80000000 和 0X80000100 这两个地址数据是否相等,比较长度为 0x10 个内存块(16 * 4=64 个字节)
cmp.l 80000000 80000100 10
我们再随便挑两段内存比较一下,比如地址0x80002000 和 0x800003000,长度为 0X10.
可以看出,0x80002000 处的数据和 0x80003000 处的数据就不一样.
1.5 网络操作命令#
环境变量 | 描述 |
---|---|
ipaddr | 开发板 ip 地址,可以不设置,使用 dhcp 命令来从路由器获取 IP 地址 |
ethaddr | 开发板的 MAC 地址,一定要设置 |
gatewayip | 网关地址 |
netmask | 子网掩码 |
serverip | 服务器 IP 地址,也就是 Ubuntu 主机 IP 地址,用于调试代码 |
预先设置号网络相关环境变量:
setenv ipaddr 192.168.1.50
setenv ethaddr b8:ae:1d:01:00:00
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.253
saveenv
1.5.1 ping命令#
ping 192.168.1.100
1.5.2 dhcp命令(自动ip获取)#
dhcp 用于从路由器获取 IP 地址,前提得开发板连接到路由器上的,如果开发板是和电脑
直连的,那么 dhcp 命令就会失效。直接输入 dhcp 命令即可通过路由器获取到 IP 地址。
DHCP 不单单是获取 IP 地址,其还会通过 TFTP 来启动 linux 内核,输入? dhcp
即
可查看 dhcp 命令详细的信息:
1.5.3 nfs命令#
nfs(Network File System)网络文件系统,通过网络将编译好的 linux 镜像和设备树文件下载
到 DRAM 中,然后就可以直接运行。
虚拟机Ubuntu先搭建好nfs服务,详见:nfs服务搭建 linux搭建nfs服务 | Hexo (fuzidage.github.io)
1 | nfs [loadAddress] [[hostIPaddr:]bootfilename] |
loadAddress 是要保存的 DRAM 地址,[[hostIPaddr:]bootfilename]
是要下载的文件地址,
我们将正点原子官方编译出来的 Linux 镜像文件 zImage 下载到开发板 DRAM 的 0x80800000这个地址处。
1 | nfs 80800000 192.168.1.253:/home/zuozhongkai/linux/nfs/zImage |
下载过程如图下:
下载完成以后查看 0x80800000 地址处的数据,使用命令 md.b 来查看前 0x100 个字节的数据。
我们再用UE打开编译出的zImage,对比一下说明 nfs 命令下载到的zImage 是正确的。
1.5.4 tftp命令#
tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中。tftp服务搭建参考:tftp服务搭建 linux搭建tftp和ftp服务 | Hexo (fuzidage.github.io)
tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
loadAddress 是文 件在 DRAM 中的 存放 地址 ,[[hostIPaddr:]bootfilename]
是要从 Ubuntu 中下载的文件。但是和 nfs 命令的区别在于,tftp 命令不需要输入文件在 Ubuntu 中的完整路径,只需要输入文件名即可。比如我们现在将 tftpboot 文件夹里面的 zImage 文件下载到开发板 DRAM 的 0X80800000 地址处。
1 | tftp 80800000 zImage |
1.6 emmc和sd卡指令#
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 寄存器的值 |
1.6.1 mmc info#
当前选中的 MMC 设备是EMMC,版本为 5.0,容量为 7.1GiB(EMMC为 8GB),速度为 52000000Hz=52MHz,8 位宽的总线。还有一个与 mmc info 命令相同功能的命令:mmcinfo,“mmc”和“info”之间没有空格。
1.6.2 mmc rescan#
mmc rescan 命令用于扫描当前开发板上所有的 MMC 设备,包括 EMMC 和 SD 卡。
1.6.3 mmc list#
查看当前开发板一共有几个 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 设备。
1.6.4 mmc dev#
选择切换当前emmc设备。
mmc dev [dev] [part]
[dev]用来设置要切换的 MMC 设备号,[part]是分区号。如果不写分区号的话默认为分区 0。
1 | mmc dev 0 //切换到 SD 卡,0 为 SD 卡,1 为 eMMC |
切换到sd这个mmc后,输入mmc info命令既可以查看sd信息:
可以看到当前 SD 卡为 3.0 版本的,容量为 14.8GiB(16GB 的 SD 卡),4 位宽的总线。
1.6.5 mmc part#
查看mmc分区
1 | mmc dev 1 //切换到 EMMC |
切到核心板的emmc后,mmc part
显示分区信息,此时 EMMC 有两个分区,第一个分区起始扇区为 20480,长度为 262144 个扇区;第二个分区起始扇区为 282624,长度为 14594048 个扇区。
如果 EMMC 里面烧写了 Linux 系统的话,EMMC 是有 3 个分区的,第 0 个分区存放 uboot,第 1 个分区存放Linux 镜像文件和设备树,第 2 个分区存放根文件系统。但是在上图中只有两个分区,那是因为第 0 个分区没有格式化,所以识别不出来,实际上第 0 个分区是存在的。一个新的 SD卡默认只有一个分区,那就是分区 0,所以前面讲解的 uboot 烧写到 SD 卡,其实就是将 u-boot.bin烧写到了 SD 卡的分区 0 里面.
1 | mmc dev 1 2 //将 EMMC 的分区 2 设置为当前 MMC 设备 |
1.6.6 mmc read#
1 | mmc read addr blk# cnt |
读mmc设备中的数据。addr 是数据读取到 DRAM 中的地址,blk 是要读取的块起始地址(十六进制),一个块是 512字节,这里的块和扇区是一个意思,在 MMC 设备中我们通常说扇区,cnt 是要读取的块数量(十六进制)。比如从 EMMC 的第 1536(0x600)个块开始,读取 16(0x10)个块的数据到 DRAM 的0X80800000 地址处
1 | mmc dev 1 0 //切换到 MMC 分区 0 |
这里我们还看不出来读取是否正确,通过 md.b 命令查看 0x80800000 处的数据就行了,查看 16*512=8192(0x2000)
个字节的数据。
可以看到baudrate=115200.board_name=EVK.board_rev=14X14
等字样,
这个就是 uboot 中的环境变量。EMMC 核心板 uboot 环境变量的存储起始地址就是1536*512=786432
。
1.6.7 mmc write#
1 | mmc write addr blk# cnt |
从DRAM写数据到mmc设备。
比如通过 nfs 或者 tftp 命令将新的 u-boot.bin 下载到开发板的 DRAM 中,然后再使用命令mmc write
将其写入到 MMC设备中。
1 | mmc dev 0 //切换到 SD 卡 |
可以看出,u-boot.imx 大小为 379904 字节,379904/512=742
,所以我们要向 SD 卡中写入742 个块,如果有小数的话就要加 1 个块。使用命令mmc write
从 SD 卡分区 0 第 2 个块(扇区)开始烧写,一共烧写 742(0x2E6)个块
1 | mmc dev 0 0 |
烧写成功,重启开发板(从 SD 卡启动),重启以后再输入 version 来查看版本号:
这样就给mmc0也就是sd卡烧录了uboot, 同理要烧录emmc也是同理,切到mmc1即可:
1 | mmc dev 1 0 //切换到 EMMC 分区 0 |
注意:千万不要写 SD 卡或者 EMMC 的前两个块(扇区),里面保存着分区表!
1.6.7 mmc erase#
1 | mmc erase blk# cnt |
擦除 MMC 设备的指定块, blk 为要擦除的起始块,cnt 是要擦除的数量。
1.7 文件操作命令(fat文件系统)#
1.7.1 fatinfo#
fatinfo <interface> [<dev[:part]>]
于查询指定 MMC 设备分区的文件系统信息,interface 表示接口,比如 mmc,dev 是查询的设备号,part 是要查询的分区。比如我们要查询 EMMC 分区 1 的文件系统信息:
1 | fatinfo mmc 1:1 |
上图显示mmc1也就是emmc设备的分区1的文件系统为fat32格式。
1.7.1 fatls#
fatls <interface> [<dev[:part]>] [directory]
查询设备分区的目录和文件信息。interface 是要查询的接口,比如 mmc,dev 是要查询的设备号,part 是要查询的分区,directory是要查询的目录。
1 | fatls mmc 1:1 //查询 mmc1设备(EMMC 设备)中分区 1 中的所有的目录和文件 |
1.7.3 fstype#
fstype <interface> <dev>:<part>
查看 MMC 设备某个分区的文件系统格式.正点原子 EMMC 核心板上的 EMMC 默认有 3 个分区, 分区 0 格式未知,因为分区 0 存放的 uboot,并且分区 0 没有格式化,所以文件系统格式未知。分区 1 的格式为 fat,分区 1 用于存放 linux 镜像和设备树。分区 2 的格式为 ext4,用于存放 Linux 的根文件系统(rootfs)。
1 | fstype mmc 1:0 |
1.7.4 fatload#
fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]
将指定的文件读取到 DRAM.
interface 为接口,比如 mmc,dev 是设备号,part 是分区,addr 是保存在 DRAM 中的起始地址,filename 是要读取的文件名字。bytes 表示读取多少字节的数据,如果 bytes 为 0 或者省略的话表示读取整个文件。pos 是要读的文件相对于文件首地址的偏移,如果为 0 或者省略的话表示从文件首地址开始读取.
fatload mmc 1:1 80800000 zImage //将 EMMC 分区 1 中的 zImage 文件读取到 DRAM 中的0X80800000 地址处
225ms 内读取了 6785272 个字节的数据,速度为 28.8MiB/s,速度是非常快的,因为这是从 EMMC 里面读取的,而 EMMC 是 8 位的,速度肯定会很快的。
1.7.5 fatwrite#
将 DRAM 中的数据写入到 MMC 设备。
uboot 默认没有使能 fatwrite
命令,需要修改板子配置头文件,比如 mx6ullevk.h、 mx6ull_alientek_emmc.h
等,需要开启宏:
1 |
fatwrite <interface> <dev[:part]> <addr> <filename> <bytes>
interface 为接口,比如 mmc,dev 是设备号,part 是分区,addr 是要写入的数据在 DRAM中的起始地址,filename 是写入的数据文件名字,bytes 表示要写入多少字节的数据。
比如我们通过nfs or tftp命令下载镜像到DRAM后,通过fatwrite去烧写image:
zImage 大小为6785272(0X6788f8)
个字节(注意,由于开发板系统在不断的更新中,因此zImage 大小不是固定的,一切以实际大小为准),接下来使用命令fatwrite
将其写入到 EMMC 的分区 1 中,文件名字为 zImage:
fatwrite mmc 1:1 80800000 zImage 6788f8
完成以后使用fatls
命令查看一下 EMMC 分区 1 里面的文件:
1.8 文件操作命令(ext文件系统)#
ext文件系统是linux常用的文件系统,一般rootfs就是典型的ext2文件系统。ext2load、ext2ls、ext4load、ext4ls 和 ext4write
。这些命令的含义和使用与 fatload、fatls 和 fatwrite
一样,只是 ext2 和 ext4 都是针对 ext 文件系统的。
1 | ext4ls mmc 1:2 //emmc设备分区2就是ext4文件系统,存放了rootfs |
1.9 nandflash操作命令#
输入? nand
即可查看NAND 相关命令:
1.9.1 nand info#
打印 NAND Flash 信息:
1.9.2 nand device#
用于切换 NAND Flash,如果你的板子支持多片 NAND 的话就可以使用此命令来设置当前所使用的 NAND。
1.9.3 nand erase#
nand erase
命令用于擦除 NAND Flash,NAND Flash 的特性(位翻转,只能由1变成0,而不能由0变成1)决定了在向 NAND Flash 写数据之前一定要先对要写入的区域进行擦除.
1 | nand erase[.spread] [clean] off size //从指定地址开始(off)开始,擦除指定大小(size)的区域。 |
1.9.3 nand write#
nand write addr off size
addr 是要写入的数据首地址,off 是 NAND 中的目的地址,size 是要写入的数据大小。
编译出来 NAND版本的 kernel 和 dtb 文件,在烧写之前要先对 NAND 进行分区,也就是规划好 uboot、linux kernel、设备树和根文件系统的存储区域,I.MX6U-ALPHA 开发板出厂系统 NAND 分区如下:
1 | 0x000000000000-0x0000003FFFFF : "boot" |
一共有六个分区,第一个分区存放 uboot,地址范围为 0x0~0x3FFFFF(共 4MB)
;第二个分区存放 env(环境变量),地址范围为 0x400000~0x420000(共 128KB)
;第三个分区存放 logo(启动图标),地址范围为 0x420000~0x51FFFF(共 1MB)
;第四个分区存放 dtb(设备树),地址范围为0x520000~0x61FFFF(共 1MB)
;第五个分区存放 kernel(也就是 linux kernel),地址范围为0x620000~0xE1FFFF(共 8MB)
;剩下的所有存储空间全部作为最后一个分区,存放 rootfs(根文件系统)。
1 | tftp 0x87800000 zImage //下载 zImage 到 DRAM 中 |
这里我们擦除了 8MB 的空间,因为一般 zImage 就是 6,7MB 左右,8MB 肯定够了,如果不够的话就再多擦除一点就行了。同理烧录dtb:
1 | tftp 0x87800000 imx6ull-14x14-emmc-7-1024x600-c.dtb //下载 dtb 到 DRAM 中 |
1.9.4 nand read#
nand read addr off size
从 NAND 中的指定地址读取指定大小的数据到 DRAM.
addr 是目的地址,off 是要读取的 NAND 中的数据源地址,size 是要读取的数据大小。
1 | nand read 0x83000000 0x520000 0x19000 //读取设备树(dtb)文件到 0x83000000 地址处 |
1.10 设备树相关#
1.10.1 fdt addr#
设置设备树起始地址:
1 | nand read 0x83000000 0x520000 0x19000 //比如把nand中dtb分区数据读到dram |
1.10.2 fdt header#
查看设备树头部信息:
fdt header
1.10.3 fdt print#
解析出dts内容:
1.11 启动相关#
1.11.1 bootz (启动zImage)#
bootz [addr [initrd[:size]] [fdt]]
addr 是 Linux 镜像文件在 DRAM 中的位置,initrd 是 initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘-’代替即可,fdt 就是设备树文件在 DRAM 中的地址.
1 | tftp 80800000 zImage |
换一张启动方式:从mmc1也就是emmc启动:
1 | fatload mmc 1:1 80800000 zImage |
1.11.1 bootm (启动uImage)#
bootm [addr [initrd[:size]] [fdt]]
bootm 命令和 bootz 类似,它是启动 uImage 镜像。uImage是U-boot专用的映像文件,它是在zImage之前加上一个长度为0x40的“头”,说明这个映像文件的类型、加载位置、生成时间、大小等信息。
bootm如果不需要启动设备树:
bootm addr
1.11.3 boot#
boot 会读取环境变量 bootcmd 来启动 Linux 系统:
比如设置bootcmd如下,从网络启动linux:
1 | setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000' |
同理,如果想从emmc启动linux,设置bootcmd如下:
1 | setenv bootcmd 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000' |
1.11.4 go命令#
go addr
跳到指定的地址处执行, addr表示DRAM地址
1 | tftp 87800000 printf.bin //一个裸机程序,打印输入的按键,将两个整数相加 |
1.11.5 run#
run 命令用于运行环境变量中定义的命令,比如可以通过run bootcmd
来运行 bootcmd 中的启动命令:
1 | setenv mybootemmc 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb;bootz 80800000 - 83000000' |
设置了3个环境变量,可以run mybootemmc或者run mybootnand或者run mybootnet
来分别从emmc启动,从nand启动,从网络启动。
1.12 内存测试mtest#
mtest [start [end [pattern [iterations]]]]
start 是要测试的 DRAM 开始地址,end 是结束地址,比如我们测试 0X80000000~0X80001000
这段内存,输入mtest 80000000 80001000
可以看出,测试范围为 0X80000000~0X80001000
,已经测试了 486 次,如果要结束测试就按下键盘上的“Ctrl+C”键。