|
上一篇文章的地址是[MYS-8MMX开发板]U-boot的编译与移植[一] https://www.cirmall.com/bbs/thread-209095-1-1.html (出处: 电路城论坛)
本篇文章我们主要是基于上一篇提到的模板,稍微修改几个启动的时候,我们能看到的打印的错误。其次主要分析下默认启动内核,设备树及文件系统的流程。这样的话下一篇我们按照我们自定义的需求修改下启动参数。
那好了,现在开始吧。
1
这个是uboot的启动打印,很明显的错误是:
tcpc_init: Can't find device id=0x52
setup_typec: tcpc port2 init failed, err=-19
tcpc_init: Can't find device id=0x50
setup_typec: tcpc port1 init failed, err=-19
包括下面的错误:
adv7535_init: Can't find device id=0x3d, on bus 1
可以在我们创建的文件board/xiheniao/imx8mm_bird/imx8mm_bird.c中找对应的错误,查看是evk板子的初始化是否不符合现在的板子,对应的修改初始化代码或者设备树,本篇不再细说了,下一篇我们会详细说明的。本篇的重点是启动参数,和和启动参数相关的参数。
启动设备进入uboot的命令行,并在命令行中执行pri查看全部的环境变量。
- u-boot=> pri
- baudrate=115200
- boot_fdt=try
- bootcmd=mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else booti ${loadaddr} - ${fdt_addr}; fi
- bootcmd_mfg=run mfgtool_args;if iminfo ${initrd_addr}; then if test ${tee} = yes; then bootm ${tee_addr} ${initrd_addr} ${fdt_addr}; else booti ${loadaddr} ${initrd_addr} ${fdt_addr}; fi; else echo "Run fastboot ..."; fastboot 0; fi;
- bootdelay=0
- bootscript=echo Running bootscript from mmc ...; source
- console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200
- emmc_dev=2
- ethprime=FEC
- fastboot_dev=mmc1
- fdt_addr=0x43000000
- fdt_file=imx8mm-ddr4-evk.dtb
- fdt_high=0xffffffffffffffff
- fdtcontroladdr=be8e5548
- image=Image
- initrd_addr=0x43800000
- initrd_high=0xffffffffffffffff
- jh_clk=
- jh_mmcboot=mw 0x303d0518 0xff; setenv fdt_file imx8mm-evk-root.dtb;setenv jh_clk clk_ignore_unused; if run loadimage; then run mmcboot; else run jh_netboot; fi;
- jh_netboot=mw 0x303d0518 0xff; setenv fdt_file imx8mm-evk-root.dtb; setenv jh_clk clk_ignore_unused; run netboot;
- kboot=booti
- loadaddr=0x40480000
- loadbootscript=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${script};
- loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
- loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
- mfgtool_args=setenv bootargs console=${console},${baudrate} rdinit=/linuxrc clk_ignore_unused
- mmcargs=setenv bootargs ${jh_clk} console=${console} root=${mmcroot}
- mmcautodetect=yes
- mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; else echo wait for boot; fi;
- mmcdev=1
- mmcpart=1
- mmcroot=/dev/mmcblk1p2 rootwait rw
- nandfit_part=yes
- netargs=setenv bootargs ${jh_clk} console=${console} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp
- netboot=echo Booting from net ...; run netargs; if test ${ip_dyn} = yes; then setenv get_cmd dhcp; else setenv get_cmd tftp; fi; ${get_cmd} ${loadaddr} ${image}; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if ${get_cmd} ${fdt_addr} ${fdt_file}; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; else booti; fi;
- script=boot.scr
- sd_dev=1
- serial#=15382a09dab4d6b7
- soc_type=imx8mm
- Environment size: 2333/4092 bytes
复制代码 说起启动相关的参数,那么不可避免的就是bootargs和bootcmd了。在当前的环境变量并没有bootargs,那么它一定隐藏在bootcmd中。
在设备默认启动或者我们输入boot去执行启动过程的时候,实际上是执行了run bootcmd的操作。所以正确的实现bootcmd是非常重要的。我们看下现在的bootcmd:
- bootcmd=mmc dev ${mmcdev}; if mmc rescan; then if run loadbootscript; then run bootscript; else if run loadimage; then run mmcboot; else run netboot; fi; fi; else booti ${loadaddr} - ${fdt_addr}; fi
复制代码 我们仔细的分析下这个bootcmd:
1. mmc dev ${mmcdev}
从上面的环境变量中我们可以看出这个mmcdev的值为1,这个语句的作用就是切换mmc dev。我们使用的是sd卡启动,整个uboot,kernel,dtb,rootfs都在sd卡里面。当然了这里和uboot在不在sd卡没关系。
如果你执行mmc dev 0或者mmc dev 2的时候会提示你错误。原因是uboot就初始化了sd卡的那个FSL_SDHC,这固然没什么问题,但是uboot中就无法操作emmc了,我们之后会改掉这个问题。
2.if mmc rescan; then if run loadbootscript; then run bootscript;
这里没执行,这也不是重点,看下面
3.if run loadimage; then run mmcboot
这里就是核心操作了,我们先列出来这两个命令都干了啥。
- u-boot=> pri loadimage
- loadimage=fatload mmc ${mmcdev}:${mmcpart} ${loadaddr} ${image}
- u-boot=> pri mmcboot
- mmcboot=echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then booti ${loadaddr} - ${fdt_addr}; else echo WARN: Cannot load the DT; fi; else echo wait for boot; fi;
复制代码 (1)loadimage
直面上来看,loadimage这个命令是使用fat32分区读取命令,从mmc的${mmcpart}分区里面把${image}文件读到${loadaddr}里面去。结合前面的环境变量,我们先翻译下这一条操作:
- loadimage=fatload mmc 1:1 0x40480000 Image
复制代码 很直观,把内核加载到内存0x40480000处。
(2)mmcargs
- mmcargs=setenv bootargs ${jh_clk} console=${console} root=${mmcroot}
复制代码 翻译下就是
- mmcargs=setenv bootargs console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200 root=/dev/mmcblk1p2 rootwait rw
复制代码 果然,这里就是设置bootargs的,把bootargs设置为:- console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200 root=/dev/mmcblk1p2 rootwait rw
复制代码 这样的话表示告诉内核我的串口是ttymxc1,波特率115200,这个地方一定要设置,要不内核启动就没有打印了,现象上来看是直接卡死在starting kernel...那里。
然后root=/dev/mmcblk1p2,告诉内核,我的文件系统在sd卡的第二分区,内核启动后就会挂载此分区作为自己的根文件系统。
(3)run loadfdt
- loadfdt=fatload mmc ${mmcdev}:${mmcpart} ${fdt_addr} ${fdt_file}
复制代码 翻译下是
- loadfdt=fatload mmc 1:1 0x43000000 imx8mm-ddr4-evk.dtb
复制代码
就是加载设备树。
(4)booti ${loadaddr} - ${fdt_addr}
booti启动loadaddr和fdt_addr,这时候loadaddr我们已经加载了内核,fdt_addr是我们的设备树,加上之前设置过bootargs知道文件分区的挂载点,这时候就执行启动linux的过程,正常无误后进入系统。
通过上面的分析,我们知道了内核的加载,设备树的加载,和内核及设备树的启动的整个过程了。所以如果启动我们自己的内核及设备树,更改对应变量的名称即可。如果想给设备有所区分的话,在bootargs中天机自定义字段就可以了。
下一篇文章我们完成uboot的移植,和内核初编译,并使用我们自定义的启动方式。
|
|