在前一篇 Hi3516DV300开发板——2.uboot、kernel、fs文件系统烧写
之后,还是有很多坑的,比如 uboot
烧写进去后,如何根据自己手里不同的开发板,设置 bootargs
和 bootcmd
等选项。
同时最后会解决一些上一篇的小问题。
bootargs 传递给内核的启动参数,告诉内核相关内容,决定内核启动后根文件系统如何挂载
bootcmd: 用于实现内核的自启动的参数传递
这里有兴趣的同学,可以去看看韦东山老师的 uboot
的分析课程,可以结合实践去分析了解。
说明:
其中很多人遇到的一个问题:就是当你 uboot
烧录进去没问题,但是去启动 Kernel
或者挂载 rootfs
的时候就会出现类似的错误:## Error: "distro_bootcmd" not defined
或者挂载根文件系统失败、uboot一直重启等。
原因:
这是因为你的 bootargs
和 bootcmd
设置和你的实际板卡外围芯片型号和硬件电路原理图不匹配,导致 Kernel
启动失败。
解决:
这里用我的开发板举个例子:
# HiSpark AI Camera Hi3516DV300 uboot printenv
arch=arm
baudrate=115200
board=hi3516dv300
board_name=hi3516dv300
bootargs=console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=15M rw
bootcmd=mmc read 0x0 0x80000000 0x800 0x4800; saveenv; go 0x80000000
bootdelay=2
cpu=armv7
ethact=eth0
ethaddr=7a:fb:28:6b:e7:60
gatewayip=192.168.1.1
ipaddr=192.168.1.15
netmask=255.255.255.0
serverip=192.168.1.5
soc=hi3516dv300
stderr=serial
stdin=serial
stdout=serial
vendor=hisilicon
verify=n
bootargs
:主要是要告诉内核一些相关设置和 rootfs文件系统
的相关参数参数分析:
console=ttyAMA0,115200n8
串口作为console终端,波特率为115200,8为数据,无校验
root=emmc
rootfs根文件系统挂载的介质为:eMMC
fstype=vfat
rootfs根文件挂载的文件系统类型为:vfat
rootaddr=10M rootsize=15M
rootfs根文件系统储存的地址为10M的位置,大小为15M
rw
默认文件系统只读,需要在 bootargs 中加入rw 选项,文件系统才可读写
解释:
rootfs
根文件系统挂载的介质一般有:
fstype
挂载的文件的类型一般有:(下一篇文章会细讲)
vfat
jffs2
— SPI NORyaffs2
— SPI NANDext4
— eMMC这里着重说明一下 rootaddr 和 rootsize,这里的addr对应上一篇 HiTools 烧录时 rootfs
根文件后面的开始地址和文件大小 (重要!!!!!)
如果自己编译了 内核和rootfs,这里rootaddr地址需要根据内核的实际大小去算,rootsize对应你实际文件的大小,一般向上取整!!!
比如这里uboot 大小1M,然后我自己编译的OHOS_Image.bin大小和18.6M,rootfs 大小为25.6M,这里就需要改了,修改命令为:
setenv bootargs 'console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=20M rootsize=26M rw'
计算过程如下:
文件 | 开始地址 | 文件大小 |
---|---|---|
u-boot-hi3516dv300.bin | 0 | 1M |
OHOS_Image.bin | 1M | 19M |
userfs.img | 20M | 26M |
bootcmd
:参数分析:
# mmc 按块儿读 一块大小是512字节
mmc read 0x0 0x80000000 0x800 0x4800;
读取emmc起始地址为0x800(单位为512B,即1MB)
大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址
saveenv;
保存uboot的环境变量设置
go 0x80000000
跳转到地址为0x80000000
解释:
命令:mmc read < device num > addr beg_addr SIZE
参数:
mmc list
查询这里先解释下这个读取的是 uboot
的 mmc read
的作用:
简单来说,主要是内核启动的时候,把以beg_addr起始的位置读取SIZE大小 的内核文件,读到addr内存位置去,然后保存设置,跳转到addr内存位置去启动内核。
实质就是,把你烧录的OHOS_Image.bin内核文件读到内存去启动。
包括我很多人开始看到这些这么多地址啊、大小的值,啥是啥啊,一脸懵逼,哪怕自己移植,也不会算,但后面细心看看不难,这里我计算一遍,看一遍,自己也算算。
这里前两个参数 0x0 0x80000000
是指:把内核从emmc(0x0)读出,放到0x80000000地址,所以第一个参数是设备号,第二个是设备的地址,我们不用管。
这里以我手里的板子和官方的镜像,内核,rootfs为例子:
文件 | 开始地址 | 文件大小 |
---|---|---|
u-boot-hi3516dv300.bin | 0 | 1M |
OHOS_Image.bin | 1M | 9M |
userfs.img | 10M | 15M |
继续,后面的 0x800
是指读取的的起始地址,也就是内核( OHOS_Image.bin) ,实际就是你烧录进去emmc储存的实际物理地址,也就是那个开始的地址,但为什么是0x800
因为一个“块”为512字节:
//起始地址
0x800(hex) ===> 2048(dec十进制)
2048 * 512 = 1048576 (字节)
1048576 / 1024 / 1024 = 1M
//所以0x800 = 1M
要把0x4800大小的内核文件移动到内存(0x8000000)中,计算如下:
//移动大小
0x4800(hex) ===> 18432(dec十进制)
18432 * 512 = 9437184(字节)
1048576 / 1024 / 1024 = 9M
//所以0x4800 = 9M
所以这样就很明显了,后面你的内核大小改变了,你这里的大小也就需要修改,不过是需要逆向的推回十六进制了。
如果你要修改相关命令,可以这样:
setenv uboot_cmd 内容
# eg:
# 设置uboot 倒计时为10s
setenv bootdelay 10
要清除某个命令的操作:
setenv uboot_cmd
# eg:
# 清除ipaddr
setenv ippaddr
bootcmd
:设置了内核相关读取搬移和启动位置,如果内核编译大小变动了,这里的设置也就需要改变,不然无法启动内核!
bootargs
:设置了 rootfs
根文件系统的相关参数,如果 rootfs
变动了,这里的设置也需要改变,不然无法挂载根文件系统。
最后,如果你的开发板参考我的上一篇成功的烧录了 uboot
、内核
和根文件系统
,但是还无法启动,先进入 uboot
输入 pri
打印看看 bootargs 和 bootcmd 是否正确。