(一)移植uboot目标:
- 将linux内核和dtb设备树加载到RAM;
- 将文件系统加载到RAM;
- 引导Linux运行;
- 执行文件系统中的linuxrx程序,对linux系统初始化。
(二)u-boot下载编译
1.在官网(https://ftp.denx.de/pub/u-boot/)下载u-boot。
2.在ubuntu下面解压:tar -jxvf u-boot-2017.0ta1.tar.bz2 (注:如果加了sudo解压出来的文件所权则为root,编译可能会出错)
3.在根目录下执行make clean;(否则有可能会报错)。
4.选择配置文件,执行,cp ./configs/sama5d3xek_nandflash_defconfig ./
5.执行make sama5d3xek_nandflash_defconfig生成配置(根目录下生成.config文件)。
6.执行make,编译代码。
7.下载uboot。
(三)uboot的使用
查询u-boot信息的命令:bdinfo(board info板子信息),printenv(环境变量,执行print指令相同)、version。
帮助命令:help,boot ?(boot的帮助)
boot引导命令:bootz、bootm、boot;
flash操作:nand、mmc、sf;
环境变量:setevn(设置环境变量,参数为空时为删除环境变量)、saveenv(保存环境变量);
重启:reset
查看板子信息bdinfo,输出如下:
printevn,查看环境变量输出如下:
(四)修改环境变量参数
环境变量可通过uboot命令修改,也可通过代码修改。
举例1:修改uboot启动延时时间10秒
printenv(可以看到当前的bootdelay值为3秒)
执行setenv bootdelay 10、saveenv指令,reset重启uboot,可以看到uboot倒计时编程10秒。
从上图可以看出,参数写入到NAND,只要Nand不擦除,参数会一直保存在,即使重刷uboot。擦除nand指令“nand erase.chip”。
举例2:修改bootargs启动参数
bootargs 保存着 uboot 传递给 Linux 内核的参数,设置了多个参数值。
执行如下命令:
setenv bootargs ‘console=ttyS0,115200 initrd=0x21000000,0x1000000 root=/dev/ram0 rw init=/linuxrc’
console:表示控制台,从串口0,波特率115200进行Linux交互。
initrd=0x21000000,0x1000000:文件系统为ramdisk时,格式为initrd=r_addr,size, r_addr表示initrd在内存中的位置,size表示initrd的大小。如果没有使用ramdisk启动系统,需要使用noinitrd参数。
root=/dev/ram0 rw,/dev/ram0是ramdisk的设备节点,rw表示根文件系统可读、可写
init=/linuxrc:内核启起来后,进入系统中运行的第一个脚本,一般init=/linuxrc。
举例3:在代码中修改bootargs参数
通过指令可以设置的环境变量,通过代码也同样可以修改。
- 找到uboot中芯片对应的头文件,比如SAMA5D3xEK对应头文件为:“sama5d3xek.h”,在“sama5d3xek.h”中又包含了“at91-sama5_common.h”,所以参数修改在这两个文件中。
- “at91-sama5_common.h”中的CONFIG_BOOTARGS则为bootargs参数,该参数最终在“include/env_default.h”的default_environmen结构体中被调用,里面包含了所有环境变量的数值定义。
- 修改对应代码,设置bootargs值。
举例4:修改bootcmd启动参数
bootcmd 保存着 uboot 默认命令,uboot 倒计时结束以后就会执行 bootcmd 中的命令。一般用于启动内核。
假设已经将dtb设备树烧录在serialFlash(SPI的串行FLASH)的0x00064000,kernel烧录在serialflash的0x00070000位置。uboot需要从flash中读取dtb/kernel到内存中、并引导Linux启动。
需要执行以下指令:
sf probe; //初始化flash,输入”sf ?”可查看使用说明
sf read 0x24e00000 0x64000 0xc000;//偏移0x64000处读取0xc000长的内容加载到内存地址0x24e00000 中
sf read 0x24f00000 0x70000 0x390000;
bootm 0x24f00000 - 0x24e00000;//启动linux,uImage地址0x24f00000,dtb地址0x24e00000
执行效果如下,执行完之后,则系统启动。
bootm格式:bootm [addr [initrd[:size]] [fdt]]
其中 addr 是 uImage 在 DRAM 中的首地址, initrd 是 initrd 的地址, fdt 是设备树(.dtb)文件在 DRAM 中的首地址,如果 initrd 为空的话,同样是用“-”来替代。
设置环境变量执行指令:
setenv bootcmd ‘sf probe;sf read 0x24e00000 0x64000 0xc000;sf read 0x24f00000 0x70000 0x390000;bootm 0x24f00000 - 0x24e00000’
举例5:代码中修改bootcmd参数
在”sama5d3xek.h”中把指令赋值给CONFIG_BOOTCOMMAND,如下所示:
(五)修改uboot,启动运行
根据上诉操作,把CONFIG_BOOTCOMMAND和CONFIG_BOOTARGS参数设置好,则可以完成uboot启动Linux的引导过程。
启动Linux可以会遇到如下错误:
Kernel panic – not Syncing: VFS: Unable to mount root fs on unknown-block(0,0)
原因是没有设置根文件系统,需要对bootargs变量进行设置。