Linux--uboot移植(一)UBOOT介绍、原厂测试

10 篇文章 0 订阅

一、Linux移植概述

Linux 的移植主要包括3部分:

  • 移植bootloader 代码, Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段bootloader程序。 这段bootloader程序会先初始化DDR等外设, 然后将Linux内核从flash(NAND,NOR FLASH,SD,MMC 等)拷贝到 DDR 中,最后启动 Linux 内核。 bootloader 有很多,常用的就是 U-Boot。DDR就是随机存储器的一种,也就是内存。
    bootloader 和 Linux 内核的关系就跟 PC 上的 BIOS 和 Windows 的关系一样,bootloader 就相当于 BIOS。
  • 移植Linux 内核,Linux内核由一系列程序组成,包括负责响应中断的中断服务程序、负责管理多个进程从而分享处理器时间的调度程序、负责管理地址空间的内存管理程序、网络、进程间通信的系统服务程序等。内核负责管理系统的硬件设备。
  • 移植根文件系统(rootfs),Linux 中的根文件系统更像是一个文件夹或者叫做目录,在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文件,这些文件是 Linux 运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。根文件系统里面包含了一些最常用的命令和文件。
    U-Boot、Linux kernel 和 rootfs这三者一起构成了一个完整的 Linux 系统,一个可以正常使用、功能完善的 Linux 系统。

二、UBOOT简介

uboot 的全称是Universal Boot Loader,遵循 GPL 协议的开源软件。

uboot 是一个裸机代码,可以看作是一个裸机综合例程。现在的 uboot 已经支持液晶屏、网络、USB 等高级功能。uboot 官网为 https://www.denx.de/wiki/U-Boot/

但我们移植uboot时一般不会直接用 uboot 官方的源码的,官方的源码是给半导体厂商准备的,半导 体厂商会根据自家的芯片,维护自己芯片对应的uboot。

三、NXP uboot测试

uboot移植并不需要从零开始将 uboot 移植到我们现在所使用的开发板上。因为半导体厂商通常都会自己做一个开发板(原厂开发板), 将uboot移植到他们自己的原厂开发板上,再将这个uboot(原厂BSP 包)发布出去。

市面上的开发板,通常会参考原厂的开发板做硬件,然后在原厂提供的 BSP 包上做修改,如正点原子和野火的 I.MX6ULL 开发板参考的就是NXP官方的 I.MX6ULL EVK 开发板做的硬件。

四、UBOOT命令使用

信息查询指令

进入 uboot 的命令行模式以后输入“ help ”或者“?”,然后按下回车即可查看当前 uboot 所支持的命令,如图 所示:

输入“ help( ?) 命令名”既可以查看命令的详细用法

环境变量操作命令

环境变量的操作涉及到两个命令: setenv saveenv ,命令 setenv 用于设置或者修改环境变量的值。命令 saveenv 用于保存修改后的环境变量,一般环境变量是存放在外部 flash 中的,uboot 启动的时候会将环境变量从 flash 读取到 DRAM 中。所以使用命令 setenv 修改的是 DRAM中的环境变量值,修改以后要使用 saveenv 命令将修改后的环境变量保存到 flash 中,否则的话uboot 下一次重启会继续使用以前的环境变量值。

有时候我们修改的环境变量值可能会有空格,比如 bootcmd bootargs 等,这个时候环境变量值就得用单引号括起来,比如下面修改环境变量 bootargs 的值:
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv
上面命令设置 bootargs 的值为“ console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw ”,其中“console=ttymxc0,115200 ”、“ root=/dev/mmcblk1p2 ”、“ rootwait ”和“ rw ”相当于四组“值”,这四组“值”之间用空格隔开,所以需要使用单引号‘’将其括起来,表示这四组“值”都属于环境变量 bootargs

网络操作命令

uboot 是支持网络的,我们在移植 uboot 的时候一般都要调通网络功能,因为在移植 linux  kernel 的时候需要使用到 uboot 的网络功能做调试。
1 ping 命令
开发板的网络能否使用,是否可以和服务器 (Ubuntu 主机 ) 进行通信,通过 ping 命令就可以验证,直接 ping 服务器的 IP 地址即可。
注意!只能在 uboot ping 其他的机器,其他机器不能 ping uboot ,因为 uboot 没有对 ping
命令做处理,如果用其他的机器 ping uboot 的话会失败!
补充:

Ping命令是一种网络诊断工具,用于测试主机之间的连通性。它的实现原理基于ICMP(Internet Control Message Protocol,Internet控制消息协议)。

以下是Ping命令的实现原理:

  1. 发送ICMP Echo请求:Ping命令向目标主机发送一个ICMP Echo请求。ICMP Echo请求的作用是请求目标主机返回一个ICMP Echo Reply响应。

  2. 接收ICMP Echo Reply响应:目标主机收到ICMP Echo请求后,如果目标主机正常工作并且网络连接正常,它将会返回一个ICMP Echo Reply响应。ICMP Echo Reply中包含了原始请求的数据,以便发送主机可以确认响应是否与请求匹配。

  3. 计算往返时间(Round-Trip Time,RTT):发送主机接收到ICMP Echo Reply响应后,它会计算往返时间(RTT),即从发送请求到接收响应的时间。RTT通常用于衡量网络延迟。

  4. 显示结果:Ping命令将收到的ICMP Echo Reply响应和计算得到的往返时间显示给用户。这些信息可以用来判断网络连接的质量和稳定性。

需要注意的是,Ping命令通常需要在发送主机和目标主机之间存在双向的网络连接,并且目标主机需要正确地响应ICMP Echo请求。如果目标主机的网络连接出现故障或者目标主机配置了防火墙,可能会导致Ping命令无法正常工作。

2、nfs 命令
nfs(Network File System) 网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源,比如我们将 linux 镜像和设备树文件放到 Ubuntu 中,然后在 uboot 中使用 nfs 命令将 Ubuntu 中 的 linux 镜像和设备树下载到开发板的 DRAM 中。
这样做的目的是为了方便调试 linux 镜像和设备树,也就是网络调试,通过网络调试是 Linux 开发中最常用的调试方法。原因是嵌入式 linux开发不像单片机开发,可以直接通过 JLINK STLink 等仿真器将代码直接烧写到单片机内部的 flash 中,嵌入式 Linux 通常是烧写到 EMMC NAND Flash SPI Flash 等外置 flash 中,但是嵌入式 Linux 开发也没有 MDK IAR 这样的 IDE ,更没有烧写算法,因此不可能通过点击一个“download ”按钮就将固件烧写到外部 flash 中。虽然半导体厂商一般都会提供一个烧写固件的软件,但是这个软件使用起来比较复杂,这个烧写软件一般用于量产的。其远没有 MDK IAR的一键下载方便,在 Linux 内核调试阶段,如果用这个烧写软件的话将会非常浪费时间,而这个时候网络调试的优势就显现出来了,可以通过网络将编译好的 linux 镜像和设备树文件下载到 DRAM 中,然后就可以直接运行。
在使用 之前需要开启 Ubuntu 主机的 NFS 服务,并且要新建一个 NFS 使用的目录,以后所有要通过NFS 访问的文件都需要放到这个 NFS 目录中。
nfs 80800000 192.168.1.253:/home/zuozhongkai/linux/nfs/zImage
命 令 中 的 “ 80800000 ”表示 zImage 保 存在DRAM中的地址 ,“192.168.1.253:/home/zuozhongkai/linux/nfs/zImage ”表示 zImage 192.168.1.253 这个主机中, 路径为/home/zuozhongkai/linux/nfs/zImage
3、 tftp 命令
tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中,只是 tftp 命令使用的 TFTP 协议, Ubuntu 主机作为 TFTP 服务器。因此需要在 Ubuntu 上搭建 TFTP 服务器
和nfs命令相比,都是开启服务之后,创建文件夹存放映像文件, 但和nfs 命令的区别在于 tftp 命令不需要输入文件在 Ubuntu 中的完整路径,只需要输入文件名即可
tftp 80800000 zImage

EMMC和SD卡操作

如果 EMMC 里面烧写了 Linux 系统的话, EMMC 是有 3 个分区的,第 0 个分区存放 uboot ,第 1 个分区存放Linux 镜像文件和设备树,第 2 个分区存放根文件系统。

BOOT 操作命令

uboot 的本质工作是引导 Linux ,所以 uboot 肯定有相关的 boot( 引导 ) 命令来启动 Linux 。常用的跟 boot 有关的命令有: bootz bootm boot
1、bootz命令
bootz 命令用于启动 zImage 镜像文件,
bootz [addr [initrd[:size]] [fdt]]
addr Linux 镜像文件在 DRAM 中的位置, initrd initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘ - ’代替即可, fdt 就是设备树文件在 DRAM 中的地址。
2 bootm 命令
bootm bootz 功能类似,但是 bootm 用于启动 uImage 镜像文件。
补充:

zImage:更轻便

  • zImage是Linux内核的一种压缩格式。它是一种轻量级的内核映像文件,通常用于嵌入式系统或者对启动速度有较高要求的场景。
  • 在编译内核时,可以选择生成zImage格式的内核映像文件。这个文件通常命名为"zImage",并且是一个压缩过的内核镜像。

uImage:更灵活更扩展

  • uImage是一种带有头部和校验和的Linux内核映像文件格式,用于各种体系结构。
  • 与zImage/bzImage/vmlinuz相比,uImage提供了更多的元数据,如内核命令行参数、内核的加载地址等。
3 boot 命令
boot 命令也是用来启动 Linux 系统的,只是 boot 会读取环境变量 bootcmd 来启动 Linux 系统,bootcmd 是一个很重要的环境变量!其名字分为“ boot ”和“ cmd ”,也就是“引导”和“命令”,说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。比如我们要想使用 tftp 命令从网络启动 Linux 那么就可以设置 bootcmd 为“ tftp80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; bootz 80800000 - 83000000”,然后使用 saveenv bootcmd 保存起来。然后直接输入 boot 命令即可从网络启动Linux 系统。
setenv bootcmd 'tftp 80800000 zImage; tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb; 
bootz 80800000 - 83000000'
saveenv
boot

boot命令是在设置好环境变量bootcmd基础上执行的,boot命令会读取bootcmd参数启动Linux。

五、编译环境搭建

1、交叉编译工具链下载并设置

2、编译原厂uboot

首先、在Ubuntu中下载解压原厂uboot源码,然后编译uboot。

编译uboot使用下面3条指令:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8

这3条命令中 :

  • ARCH=arm 设置目标为 arm 架构
  • CROSS_COMPILE 指定所使用的交叉编译器。
  • 第1条命令相当于make distclean,目的是清除工程,一般在第一次编译的时候最好清理一下工程。
  • 第2条指令相当于make mx6ull_14x14_evk_emmc_defconfig ,用于配置 uboot,配置文件为 mx6ull_14x14_evk_emmc_defconfig。
  • 第3条指令相当于make -j8,也就是使用8核来编译uboot。

为了方便的执行着3条指令,可以将这些指令写成shell脚本,比如在uboot源码目录下新建一个build.sh文件,写入如下内容:

#!/bin/bash
​
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8

然后编译,编译完成以后uboot 源码多了一些文件,其中u-boot.bin就是编译出来的 uboot二进制文件。 uboot是个裸机程序, 因此需要在其前面加上头部(IVT、 DCD等数据)才能在I.MX6U上执行,u-boot.imx文件就是添加头部以后的 u-boot.bin。

u-boot.imx 就是我们最终要烧写到开发板中的 uboot 镜像文件。

3、烧录开发板

这是的烧录开发板,实际是要烧录uboot镜像文件到SD卡中,然后将SD卡插入开发板,让开发板从SD卡启动(需要在开发板上设置拨码开关来选择启动方式)。

3.1 烧录到SD卡

正点原子专门编写了一个小软件用来将编译出来的.bin 文件烧写到 SD 卡中,这个软件叫做“imxdownload

将imxdownload 复制到 Ubuntu 中的uboot源码文件夹,再使用如下指令,给予 imxdownload 可执行权限:

chmod 777 imxdownload

然后电脑USB中插入SD卡(读卡器),并在虚拟机中设置usb加载(VMware或VirtualBox虚拟机需要先安装增强功能才能使用)

然后可以使用如下指令来查看SD卡的挂载标识符:

ls /dev/sd* 

查看输出结果:

这里的/dev/sdb就是我的SD卡。

注:我第一次使用SD卡烧录时,只多出了/dev/sdb,但不知什么情况,用了几次后,再插入SD卡,就会同时多出来/dev/sdb和/dev/sdb1,但实际测试,仍然把程序烧录到/dev/sdb也能用)。

imxdownload向SD卡烧写led.bin文件,命令格式如下:

./imxdownload u-boot.bin /dev/sdb 
注意不能烧写到 /dev/sdasda1设备里面!那是系统磁盘。

烧写过程会输入如下信息:

烧写的最后一行会显示烧写大小、用时和速度,比如u-boot.bin烧写到SD卡中的大小是 423KB,用时 1.7s,烧写速度是 236KB/s。

注意这个烧写速度,如果这个烧写速度在几百KB/s 以下那么就是正常烧写。 如果这个烧写速度大于几十MB/s、甚至几百MB/s那么肯定是烧写失败了! 重新插拔/格式化SD卡或重启ubuntu再试。

烧写完成以后会在当前工程目录下生成一个load.imx的文件,这个文件就是软件 imxdownload 根据 NXP 官方启动方式介绍的内容, 在 bin 文件前面添加了一些数据头以后生成的。最终烧写到 SD卡里面的就是这个imx文件。

4. 启动开发板

烧录完之后,将SD卡插入开发板启动,使用串口连接电脑,查看uboot启动信息。

设置好串口参数(波特率115200)并打开,按键复位开发板

当串口打印上出现“Hit any key to stop autoboot”倒计时的时候按下键盘上的回车键,默认是 3 秒倒计时,在 3 秒倒计时结束以后如果没有按下回车键的话 uboot 就会使用默认参数来启动 Linux 内核了。

如果在 3 秒倒计时结束之前按下回车键,那么就会进入 uboot 的命令行模式:

解读一下这些信息的含义:

  • 第1行是 uboot 版本号和编译时间:当前的 uboot 版本号是 2016.03,编译时间是 2021/7 /11/15:22:25
  • 第3、4 行是 CPU 信息:当前使用的 CPU 是飞思卡尔(属于NXP)的 I.MX6ULL (频率为 792MHz),此时运行在 396MHz。这颗芯片是工业级的,结温为-40°C~105°C
  • 第 5 行是复位原因:I.MX6ULL 芯片上有个 POR_B 引脚,将这个引脚拉低即可复位 I.MX6ULL。
  • 第 6 行是板子名字,“MX6ULL 14x14 EVK”即NXP原厂开发板的名字 。
  • 第 7 行提示 I2C 准备就绪
  • 第 8 行提示当前板子的DRAM(内存) 为 512MB
  • 第 9 行提示当前有两个MMC/SD 卡控制器:FSL_SDHC(0)和 FSL_SDHC(1)。I.MX6ULL支持两个 MMC/SD,正点原子的 I.MX6ULL EMMC 核心板上 FSL_SDHC(0)接的 SD(TF)卡,FSL_SDHC(1)接的 EMMC。
  • 第10行是一条警告信息,先忽略。
  • 第 12、13 行是 LCD 型号,原厂默认的是TFT43AB (480x272)。
  • 第 14~16 是标准输入、标准输出和标准错误所使用的终端,这里都使用串口(serial)作为终端。
  • 第 17 、18行是切换到emmc的第0个分区上,因为当前的 uboot 是 emmc 版本的,也就是从 emmc 启动的。我们只是为了方便将其烧写到了 SD 卡上,但是它的“内心”还是 EMMC的。所以 uboot 启动以后会将 emmc 作为默认存储器 。
  • 第 19行是网口信息,提示我们当前使用的 FEC1 这个网口,I.MX6ULL 支持两个网口。
  • 第 20行提示 FEC1 网卡地址没有设置(后面我们会讲解如何在uboot 里面设置网卡地址)。
  • 第 22行提示正常启动, 也就是说 uboot要从emmc里面读取环境变量和参数信息启动 Linux内核了。
  • 第23行是倒计时提示,默认倒计时 3 秒,倒计时结束之前按下回车键就会进入 Linux 命令行模式。如果在倒计时结束以后没有按下回车键,那么 Linux 内核就会启动,Linux 内核一旦启动,uboot 就运行结束了。
  • 第23行是在倒计时 3 秒内按了回车键,符号=>表示可以继续与uboot进行命令交互

看过了串口的uboot信息,再来看一下板子是实际运行情况:

由于原厂的uboot驱动的屏幕是TFT43AB (480x272),与我这里屏幕不一样,所以屏幕没有正常显示(现在的屏幕看起来有许多彩色的小点点),接下来,就是对uboot进行屏幕驱动的修改。

参考资料:安全验证 - 知乎

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值