【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第四篇 嵌入式Linux系统移植篇-第六十七章 Uboot编译及移植

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT、4G模块、CAN、RS485等接口一应俱全。H264、VP8视频硬编码,H.264、H.265、VP8、VP9视频硬解码,并提供相关历程,支持8路PDM接口、5路SAI接口、2路Speaker。系统支持Android9.0(支持获取root限)Linux4.14.78+Qt5.10.1、Yocto、Ubuntu20、Debian9系统。适用于智能充电桩,物联网,工业控制,医疗,智能交通等,可用于任何通用工业和物联网应用


第四篇 嵌入式Linux系统移植篇

六十七章 Uboot编译及移植

在之前学习开发板烧写的章节中,我们用到uboot和内核的镜像是怎么做出来的呢,我们在学习移植uboot之前先使用迅为电子移植好的uboot镜像来学习一下uboot的相关知识,本章节我们来学习下基础的知识“什么是uboot”和“uboot中的常用命令”,并且我们下载NXP官方的源码。

67.1 U-Boot介绍

67.1.1 什么是u-boot

uboot是一段裸机代码,它的实现非常复杂,主要是初始化一些硬件,部署整个计算机系统,然后将Linux内核从flash(NAND,NOR FLASH,SD,MMC 等)拷贝到 DDR 中,根据环境变量去启动内核,并向内核传递参数。它的目标就是启动内核,内核启动后它的生命也随之结束。

u-boot是SourceForge上的开源项目,由一个人发起,然后由整个世界所有感兴趣的人共同维护发展而来的一个bootloader,bootloader是用来引导和加载内核,向内核传递参数的,是内核引导程序的统称,bootloader除了u-boot还有bios,LilO,redboot,vivi等。

uboot 的全称是 Universal Boot Loader,uboot 是一个遵循 GPL 协议的开源软件,uboot 是一个裸机代码,可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、USB 等高级功能。uboot 官网为 http://www.denx.de/wiki/U-Boot/,如下图所示:

 可以在 uboot 官网下载 uboot 源码,点击图中左侧 Topics 中的“Source Code”,打开如下图 所示界面:

进入其 FTP 服务器即可看到 uboot 源码 

我们可以在uboot官网下载最原始的uboot源码,也就是没有经过修改的,原汁原味的uboot的,但是在实际工作中,我们并不会直接在uboot官网下载uboot源码来移植uboot。为什么呢?因为我们要在对应的平台上来运行uboot,那么这个uboot是不是就要对这个平台支持的非常全面呢,因为uboot本身就是裸机代码,所以想要对某一个平台支持的非常全面,就要对这个平台非常熟悉,比如i.MX 8M Mini,那就要对i.MX 8M Mini这个芯片非常熟悉,那谁对这个芯片非常熟悉呢,当然是半导体厂家呀,所以,uboot官网里面的原汁原味的uboot是给半导体厂家准备的,比如RK,NXP等等。NXP官方的 uboot 基本支持了 NXP 当前所有可以跑 Linux 的芯片,而且支持各种启动方式,比如 EMMC、NAND、NOR FLASH 等等,这些都是 uboot 官方所不支持的我们如果要移植对芯片支持最全面,最好的uboot的,我们一般是在半导体厂家维护uboot版本的基础上来二次开发自己的uboot,而不是直接在uboot官网下载源码来移植。

在迅为提供的资料里面有两个Linux的BSP源码包,一个是半导体厂商提供的源码包,里面的uboot是未经修改的,一个是迅为提供的BSP源码包,里面的uboot是经过迅为修改后的uboot,可以直接编译在开发板上来运行。当然了,你也可以在购买了第三方开发板以后使用半导体厂商提供的 uboot,只不过有些外设驱动可能不支持,需要自己移植,这个就是我们常说的 uboot 移植

67.1.2 常用命令

我们先烧迅为做好的uboot(flash.bin)到开发板上,我们先了解与uboot相关的命令。

uboot启动如下图所示:

 

上电以后,出现 Hit any key to stop autoboot: 0就按下任意键进入uboot命令行,输入?查看帮助信息,会弹出很多命令和介绍,如下图所示: 

上面的那些命令并不是 uboot 所支持的所有命令,前面说过 uboot 是可配置的,需要什么命令就使能什么命令。这些命令后面都跟有命令说明,用于描述此命令的作用,但是命令具体怎么用呢?我们输入“help(或?) 命令名”既可以查看命令的详细用法,以“bootz”这个命令为例,我们输入如下命令即可查看“bootz”这个命令的用法: 

=> ? bootz
bootz - boot Linux zImage image from memory

Usage:
bootz [addr [initrd[:size]] [fdt]]
    - boot Linux zImage stored in memory
        The argument 'initrd' is optional and specifies the address
        of the initrd in memory. The optional argument ':size' allows
        specifying the size of RAW initrd.
        When booting a Linux kernel which requires a flat device-tree
        a third argument is required which is the address of the
        device-tree blob. To boot that kernel without an initrd image,
        use a '-' for the second argument. If you do not pass a third
        a bd_info struct will be passed instead

常用的和信息查询有关的命令有 3 个:

  • bdinfo
  • printenv
  • version

先来看一下 bdinfo 命令,此命令用于查看板子信息,直接输入“bdinfo”即可,结果如下

从上面中可以得出 DRAM 的起始地址和大小、启动参数保存起始地址、波特率、sp(堆栈指针)起始地址等信息。

命令“printenv”用于输出环境变量信息,uboot 也支持 TAB 键自动补全功能,输入“print”然后按下 TAB 键就会自动补全命令,直接输入“print”也可以。输入“print”,然后按下回车键,环境变量如下面所示:

 

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=2
bootscript=echo Running bootscript from mmc ...; source
console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200
emmc_dev=1
ethprime=FEC
fastboot_dev=mmc1
fdt_addr=0x43000000
fdt_file=itop8mm-evk-7.0.dtb
fdt_high=0xffffffffffffffff
fdtcontroladdr=be8f5860
image=Image
initrd_addr=0x43800000
initrd_high=0xffffffffffffffff
jh_clk= 
jh_mmcboot=setenv fdt_file fsl-imx8mm-evk-root.dtb;setenv jh_clk clk_ignore_unused; if run loadimage; then run mmcboot; else run jh_netboot; fi; 
jh_netboot=setenv fdt_file fsl-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/mmcblk2p2 rootwait rw
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=0
soc_type=imx8mm

Environment size: 2333/4092 bytes

 有很多的环境变量,比如 baudrate、board_name、board_rec、boot_fdt、bootcmd等等。uboot 中的环境变量都是字符串,既然叫做环境变量,那么它的作用就和“变量”一样。

比如 bootdelay 这个环境变量就表示 uboot 启动延时时间,默认bootdelay=3,也就默认延时 3秒。前面说的 3 秒倒计时就是由 bootdelay 定义的,如果将 bootdelay 改为 5 的话就会倒计时 5s了。uboot 中的环境变量是可以修改的,有专门的命令来修改环境变量的值。

setenv修改环境变量:setenv 环境变量名 环境变量值

删除环境变量:setenv 环境变量名

例如设置自启动倒计时环境变量bootdelay,设置为5秒,默认是2秒,如下图所示:

输入命令setenv bootdelay 10然后输入printenv查看环境变量,发现环境变量已经改变。

删除环境变量也是使用命令 setenv,要删除一个环境变量只要给这个环境变量赋空值即可,比如我们删除掉上面新建的bootdelay 环境变量,使用命令 setenv bootdelay删除环境变量,如下图所示:

实验完成后,重新启动开发板恢复环境变量使设置的环境失效,因为环境变量没有保存到flash。

  1. reset重新启动

在uboot命令行输入reset即可重启开发板,如下图所示:

 

实验完成后,重新启动开发板恢复环境变量使设置的环境失效,因为环境变量没有保存到flash。

  1. reset重新启动

在uboot命令行输入reset即可重启开发板,如下图所示:

 

  1. mmc: 在uboot命令行,输入mmc可以查看跟mmc相关的命令,如下图所示: 

由上图我们可以发现,mmc后面的参数不同,mmc的功能就不一样,例如:

mmc info:打印mmc的信息

mmc list :查看mmc设备

mmc read addr blk# cnt从eMMC读cnt个块数据到内存addr处;

mmc write addr blk# cnt把内存addr处的cnt个块数据写到eMMC。

mmc erase blk# cnt:擦除blk#开始的cnt个数据块

其中,addr为内存地址,blk#是mmc的块号,cnt是设备块的个数,块的单位是512字节。

(1)mmc info命令

mmc info命令可以查看设备信息,如下图所示:

 

通过上图我们可以看出,当前的设备是emmc设备,也就是图中MMC version所表示的信息为emmc的版本为5.1,Capacity所表示的信息为容量大小为14.6 Gib,Bus Width表示带宽为8-bit,Bus Speed表示速度为52000000Hz。

(2)mmc list命令

mmc list查看mmc设备,直接输入mmc list即可,如下图所示:

(3)mmc rescan命令

mmc rescan可以扫描开发板上的emmc设备,直接输入mmc rescan命令即可

 

(4)mmc dev命令

mmc dev命令可以切换mmc设备,命令格式:mmc dev mmc dev [dev] [part],其中dev是我们要切换到的mmc设备号,part可以不写,不写的话默认分区为0。

我们找一张FAT32的TF卡,查到开发板上的TF卡座子上,一般我们把TF卡也认为是mmc设备。所以也可以用mmc命令来操作。连接好TF卡以后,使用以下命令切换到TF卡

mmc dev 0

其中0为sd卡,1为emmc。

然后我们使用mmc info命令查看是否切换成功,结果如下图所示:

从上图我们可以看到,sd卡的版本信息为3.0,容量为14.6 GiB,位宽为4-bit。

(5)mmc part命令

mmc part可以用来查看mmc设备的分区,比如我们要查看emmc的分区,我们先切换到emmc设备(如果当前已经是emmc设备则不用切换),命令如下:

mmc dev 1

切换成功如下图所示:

 

 使用命令mmc part查看emmc的分区,如下图所示:

从上图我们可以看出,emmc一共有2个分区,类型为DOS,其中第一个分区用来存放uboot镜像和内核镜像,第二个分区用来存放文件系统

(6)mmc read命令

使用mmc read命令可以读取mmc设备的数据信息,格式为mmc read addr blk# cnt,其中addr是读取到内存中的地址,blk为起始的块地址,一般为十六进制,一块是512字节,cnt是要读取的块的数量。

例如:mmc read 0xa0000000 10 10 ,表示mmc设备的第10块开始,读取10块到内存的0xa0000000地址当中去。结果如下:

 

5  go命令

go命令可以指定跳到地址处运行,命令格式为 go addr ,其中addr是应用在内存中的首地址。

6  run命令

可以执行环境变量中的命令,这个命令一般用于用户运行自定义的环境变量。

7  ls命令,默认uboot没有这个命令,可以配置上使用。

ls命令可以列出文件的目录,命令格式ls <interface> [<dev[:part]> [directory]]

例如,查看emmc分区5的信息。分区5为文件系统分区

ls mmc 1:5

其中,1为emmc,5为emmc里面的分区5

查看emmc分区5里面的etc信息,也就是文件系统里面的etc信息,命令如下

ls mmc 1:5 etc 

67.2设置交叉编译器

输入以下命令设置交叉编译器,只有设置了交叉编译器,才可以编译源码,否则会报错。

 . /opt/fsl-imx-xwayland/4.14-sumo/environment-setup-aarch64-poky-linux
export ARCH=arm64
export CROSS_COMPILE=aarch64-poky-linux-

67.3 获取u-boot-imx 源码并编译

输入以下命令下载u-boot-imx 源码。

git clone https://source.codeaurora.org/external/imx/uboot-imx

进入uboot-imx目录,如下所示:

cd uboot-imx

 

查看git分支,如下所示:

git branch -a

 

切换分支,输入以下命令:

git checkout imx_v2018.03_4.14.78_1.0.0_ga

 

同步到当前仓库,输入以下命令:

git pull origin

输入以下命令,开始编译。

make distclean    

make imx8mm_ddr4_evk_defconfig

 

输入以下命令,开始编译。

 . /opt/fsl-imx-xwayland/4.14-sumo/environment-setup-aarch64-poky-linux

make -j 8

 

编译成功后会产生所需的文件:

u-boot-nodtb.bin

spl/u-boot-spl.bin

arch/arm/dts/fsl-imx8mm-ddr4-evk.dtb

67.4 获取 imx-mkimage源码并编译

下载 imx-mkimage源码,输入以下命令:

git clone https://source.codeaurora.org/external/imx/imx-mkimage/ && cd imx-mkimage

 查看远程分支,输入以下命令:

git branch -a

切换到与imx_4.14.78_1.0.0_ga版本对应的分支上,输入以下命令:

git checkout imx_4.14.78_1.0.0_ga

 

同步到当前仓库,输入以下命令:

git pull origin

67.5获取imx-atf源码并编译

退回上一级目录,下载 imx-atf,并同样切换分支

cd ..    

git clone https://source.codeaurora.org/external/imx/imx-atf/ && cd imx-atf    

 

切换到与imx_4.14.78_1.0.0_ga版本对应的分支上,输入以下命令:

git checkout imx_4.14.78_1.0.0_ga   

同步到当前仓库,输入以下命令:

git pull origin

 

编译 imx-atf,输入以下命令:

make clean PLAT=imx8mm

LDFLAGS="" make PLAT=imx8mm

 编译完成会生成build/imx8mm/release/bl31.bin文件,如下图所示:

67.6 获得firmware-imx源码

返回上一级目录,输入以下命令获得firmware-imx源码

cd .. && mkdir firmware-imx-8.10

cd firmware-imx-8.10

wget http://www.freescale.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-8.1.bin

 解压输入以下命令:

./firmware-imx-8.1.bin --auto-accept

 

67.7生成flash.bin

使用 imx-mkimage 链接合成所有文件生成最后二进制文件

输入以下命令拷贝uboot-imx中的文件到imx-mkimage目录。

cp uboot-imx/tools/mkimage ./imx-mkimage/iMX8M/mkimage_uboot    

cp uboot-imx/arch/arm/dts/fsl-imx8mm-ddr4-evk.dtb ./imx-mkimage/iMX8M/fsl-imx8mm-ddr4-evk.dtb    

cp uboot-imx/spl/u-boot-spl.bin ./imx-mkimage/iMX8M/    

cp uboot-imx/u-boot-nodtb.bin ./imx-mkimage/iMX8M/

 

cpfirmware-imx-8.10/firmware-imx-8.1/firmware/ddr/synopsys/ddr4_dmem_1d.bin ./imx-mkimage/iMX8M/    
cpfirmware-imx-8.10/firmware-imx-8.1/firmware/ddr/synopsys/ddr4_dmem_2d.bin ./imx-mkimage/iMX8M/    
cp firmware-imx-8.10/firmware-imx-8.1/firmware/ddr/synopsys/ddr4_imem_1d.bin ./imx-mkimage/iMX8M/    
cp firmware-imx-8.10/firmware-imx-8.1/firmware/ddr/synopsys/ddr4_imem_2d.bin ./imx-mkimage/iMX8M/

cp imx-atf/build/imx8mm/release/bl31.bin ./imx-mkimage/iMX8M/ 

cd imx-mkimage    

make SOC=iMX8MM clean    

make SOC=iMX8MM flash_ddr4_evk

编译完会生成flash.bin镜像,如下图所示: 

然后我们可以使用TF卡启动uboot,但是不能使用UUU工具烧写,接下来进一步优化源码,请查看第二章。 

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值