正点原子阿尔法开发板uboot使用实验笔记以及踩过的坑

一、Uboot是什么?

Linux要启动必须要有bootloader程序。芯片在上电之后先运行bootloader程序,bootloader程序初始化DDR等外设。然后将内核从存储介质(SD,NAND,NOR FLASH,MMC等)中拷贝到DDR中。然后启动linux内核。Uboot属于bootloader程序的一种。

Uboot有三种:(1)uboot 官方的源码;(2)半导体厂商根据uboot官方的源码自己维护的代码;(3)采用半导体厂商芯片的开发板厂商,根据半导体厂商的uboot代码,自己维护的代码。三者是递进迭代的。

二、uboot编译和命令使用

(1)Uboot的编译

我使用的是正点原子的阿尔法开发板。几天来终于把uboot的使用按照教程过了一遍。初学linux,跌跌撞撞踩了很多坑。现在回顾一下。作为记录。

首先进行的是U-BOOT的初次编译。在这第一步我就卡了很久很久。我这里使用的是512MB(DDR3)+8GB(EMMC)核心板。

我按照要求把uboot源码的压缩包放到指定的文件夹,并解压之后。执行三条指令uboot源码进行编译。

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean

这一行ARCH=arm为指定ARM架构。CROSS_COMPILE=arm-linux-gnueabihf指定交叉编译器为gnueabihf。 distclean为清除工程。

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- (加空格) mx6ull_14x14_ddr512_emmc_defconfig

这里面有两个坑。第一是指出来的空格。我在自行操作的时候发现了这个问题。改正过来了;第二是14x14的“x”号,是英文字母x。我之前 一直输入算数×号,导致系统一直提示找不到这个文件。最后去问了正点原子的客服,技术客服远程操作,自己打完文件名称,没有问题。后来我才发现问题出现在这里。是个大坑啊。

make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12

第三行是-j12是指用12核来编译uboot。

这三条指令执行完毕之后,uboot就算编译成功了。

此外正点原子还提供了使用shell文件来进行编译的方法。为了图省事,我在windows系统下面编写了shell文件中的内容,通过TFP传送到ubuntu系统。在执行shell文件的时候总是出错。

后来去网上查了原因。我在windows系统中建立的文件是dos格式的。dos格式下每一行的结尾是\r\n, 而unix格式下行的结尾是\n。所以执行会报错。文件需要转换成unix格式的。使用dos2unix  filename函数转换之后。shell就可以执行了。

接着使用正点原子的imxdownload来下载到SD卡,将SD卡插入到开发板上,并且设置开发板从SD卡启动。

(2)U-Boot 命令使用

输入”help”或者“?”可以查看当前Uboot支持的命令。

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

1.信息查询命令

bdinfo

正点原子阿尔法开发板uboot使用实验笔记以及踩过的坑

这一命令用于查看板子的信息。

printenv

这是我用到最多的一个命令,用于查看环境信息。环境信息里面有很多需要配置的变量。尤其是在网络命令的时候,需要配置本地IP地址,主机IP地址,MAC地址,子网掩码。

正点原子阿尔法开发板uboot使用实验笔记以及踩过的坑

上图是环境变量的部分信息

version

这一命令用于查看ubuntu的版本号。

正点原子阿尔法开发板uboot使用实验笔记以及踩过的坑

我的ubuntu的版本信息

可以看到版本日期是2016.03,编译日期是2020年5月3日12:35:27 东八时区。这还包含了编译器信息。

2.环境变量操作命令

修改环境变量用到setenv和saveenv命令。

setenv 环境变量 变量值.

系统开启的时候会将环境变量从flash中读取到SDRAM中,使用setenv命令修改的环境变量是在SDRAM中的环境变量。使用saveenv命令可以保存修改后的环境变量到flash中去。下次开机的时候,就会使用修改后的环境变量。

要修改的环境变量值有空格的时候要用单引号括起来‘’。

新建环境变量值和删除环境变量也使用setenv命令。

新建环境变量格式为:

setenv 新的环境变量 环境变量值

删除环境变量格式为:

setenv 要删除的环境变量

3.内存操作命令

md

该命令用于显示内存的数值。格式如下。

md[.b, .w, .l] address [# of objects]。b,w,l三选一,表示的是数值显示的单位,b是指以一个字节为单位显示,w是以一个字(两个字节为显示单位),l是以四个字节为显示单位。address为要查看的内存起始地址。[# of objects]指的是显示变量的数量。表示多少个指定格式的数据。如果数据格式指定为b,数量为字节的数量;如果数据格式指定为w,数量为字的数量;如果数据格式指定为l,数量为long的数量;

ubuntu中的数字都是十六进制的。不是十进制的。

比如你想查看以 0X80000000 开始的 20 个字节的内存值,显示格式为.b 的话使用:

md.b 80000000 14

比如你想查看以 0X80000000 开始的 40 个字节的内存值,显示格式为.w 的话使用:

md.w 80000000 14

比如你想查看以 0X80000000 开始的 80 个字节的内存值,显示格式为.l 的话使用:

md.l 80000000 14

nm

该命令用于修改指定地址的内存值。

nm [.b, .w, .l] address

[.b, .w, .l]用于指定操作格式。address用于指定要修改的地址。

按照格式输入后,会显示地址和地址现有的数据值,最后是一个?号。直接输入修改后的值,按回车即可修改。这种修改方式地址不自增,按输入q,按回车退出修改;

mm

使用该命令修改内存值时,地址会自增。其他的格式同nm命令。

mw

该命令为使用一个指定的数据,重复填充一段指定的内存。

mw [.b, .w, .l] address value [count]

[.b, .w, .l]和address的作用和上面几个命令是一样的。value是要填充的值, [count]是要填充的数量。

实例:mw.l 80000000 0A0A0A0A 10为以long的格式从80000000地址处开始,填充10个0a0a0a0a数值。

cp

cp是数据拷贝命令。从指定地址以指定格式拷贝指定数量的数据到另一个地址。

cp [.b, .w, .l] source target count

[.b, .w, .l]指定数据格式;source指定源地址;target指定目标地址;count指定要拷贝的数据的数量。

示例:cp.l 80000000 80000100 10为 从80000000地址处以long的格式拷贝16个数据到80000100地址处。

cmp

该命令用于比较两段内存值是否相等。

cmp [.b, .w, .l] addr1 addr2 count

[.b, .w, .l]为指定数据格式;addr1第一个地址;addr2第二个地址;count要比较的数据的数量。

4.网络命令

网络调试命令有ping,dhcp,nfs,tftp.

进行网络调试之前首先要配置环境变量。

setenv ipaddr 开发板ip地址。这个地址要与电脑上的ubuntu主机在同一个网段内。

setenv ethaddr 00:04:9f:04:d2:35  这个是MAC地址。如果同一个网段内有多个板子,要保证MAC地址是不一样的。        

setenv serverip 服务器ip地址。这个地址是主机ubuntu的ip地址。

setenv gatewayip 网关ip

setenv netmask 子网掩码

配置完成之后保存环境变量即可。

ping命令

这是我碰到的第一个网络命令的难点。我在一开始自己照着教程ping的时候,完全没有ping通过,即使是在开发板和电脑都使用网线连接路由器的情况下。

正点原子阿尔法开发板uboot使用实验笔记以及踩过的坑

ping不通的结果

后来还是找了技术客服来解决。首先是因为我的开发板ip地址和ubuntu的地址不在同一个网段内。然后主机ubuntu的网络使用桥接模式。解决了这两点,就可以ping通了。

如果要使用TFP传输文件的时候,主机ubuntu的网络模式要切换到NAT格式。IPV4的设置修改为自动DHCP模式。

dhcp

该命令是开发板向路由器请求分配ip地址。

nfs

nfs(Network File System)网络文件系统。通过nfs可以在计算机之间通过网络在分享资源。

nfs [loadAddress] [[hostIPaddr:]bootfilename]

[loadAddress]为要保存的DRAM地址,[[hostIPaddr:]bootfilename]是要下载的文件地址。

tftp

走到这里又是一个坑。在教程里先下载并搭建tftp服务器,建立tftp文件夹。然后配置tftp。这个文档里面说“安装完成以后新建文件/etc/xinetd.d/tftp,如果没有/etc/xinetd.d 目录的话自行创建。”我以为是自己建立一个etc文件夹。就自己建立了etc/xinetd.d/tftp文件。并在文件中添加配置内容。启动tftp服务,修改/etc/default/tftpd-hpa文件。将建立的tftpboot文件路径添加进去。

然后将镜像文件复制到tftpboot文件夹中,给予文件和文件夹相应的权限。执行tftp下载命令。

是不通的!

又检查了好几遍,确认是不通的。

我自己实在不知道是怎么回事。完全按照教程上来的。为什么会有这样的结果?

无奈之下,再一次去找客服。客服远程鼓捣了一通之后,发现我建立的配置文件是不对的。etc文件夹是在根目录中已有的,只是没有显示出来。自己去建立一个etc文件夹,然后添加配置文件,肯定是不能用的了。

5.emmc和SD卡操作命令

mmc info

该命令用于输出当前选中的 mmc info 设备的信息

mmc rescan

扫描开发板上的所有mmc设备。

mmc list

mmc list 命令用于来查看当前开发板一共有几个 MMC 设备。

mmc dev

mmc dev 命令用于切换当前 MMC 设备。

mmc dev [dev] [part]

[dev]指设备号,0为SD卡,1为emmc,[part]指分区号,默认为0。

mmc part

查看当前磁盘分区。

mmc read 命令

mmc read 命令用于读取 mmc 设备的数据,命令格式如下:

mmc read addr blk# cnt

addr是读取到DRAM中的地址,blk 是要读取的块起始地址(十六进制),一个块是512字节。cnt为要读取的块的数量。

mmc write 命令

将数据从DRAM写入到mmc设备里面 。

mmc write addr blk# cnt

addr为要写入的数据在DRAM中的地址。blk为要写入mmc的块起始地址,一个块为512个字节。

mmc write 可以通过uboot来更新uboot。先使用tftp命令将uboot下载到DRAM中去。然后使用mmc write 命令将uboot写入到SD卡。

mmc erase

mmc擦除命令。mmc erase blk# cnt

blk为要擦除的块起始地址,cnt为要擦除的块的数量。

6.FAT格式文件系统操作命令

Fatinfo

fatinfo <interface> [<dev[:part]>]

interface表示接口,dev表示要查询的设备号,part为要查询的分区

fatls

用于查询 FAT 格式设备的目录和文件信息

fatls <interface> [<dev[:part]>] [directory] interface 是要查询的接口,比如 mmc,dev 是要查询的设备号,part 是要查询的分区,directory是要查询的目录。

比如fatls mmc 1:1是要查询emmc分区1的目录和文件信息。

fstype

fstype 用于查看 MMC 设备某个分区的文件系统格式。

fstype <interface> <dev>:<part>格式项描述同上。

fatload 命令用于将指定的文件读取到 DRAM 中,命令格式如下:

fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]。

Interface为设备号。dev[:part]设备号和分区;addr为保存在DRAM中的起始地址;filename为要读取的文件的名字;bytes表示读取多少个字节的数据,byte为0表示读取整个文件。Pos为读取地址相对于文件首地址的偏移量,如果为0的情况下表示从首地址开始读取。

7. EXT 格式文件系统操作命令

uboot 有 ext2 和 ext4 这两种格式的文件系统的操作命令,常用的就四个命令,分别为:

ext2load、ext2ls、ext4load、ext4ls 和 ext4write。这些命令的含义和使用与 fatload、fatls 和 fatwrit一样,只是 ext2 和 ext4 都是针对 ext 文件系统的。

比如EMMC分区2是EXT4格式的。所以可以使用ext4ls来查看文件系统

ext4ls mmc 1:2

8.BOOT 操作命令

bootz

bootz [addr [initrd[:size]] [fdt]]

addr为镜像文件起始地址,initrd是initrd文件在DRAM中的起始地址,不用可以用“-”代替;fdt为设备树文件在DRAM中的起始地址。

使用网络启动linux

tftp 80800000 zImage

tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dt

bootz 80800000 – 83000000

从EMMC中启动linux

fatload mmc 1:1 80800000 zImage

fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dt

bootz 80800000 – 83000000

在这里文档又出现了一个错误(1.3版本的),文档中说设备树文件的名字是imx6ull-alientek-emmc.dtb但是我在网盘里翻了很久,也没有找到这个文件名对应的文件。后来去了B站,看视频发现操作的时候用的不是这个名字。是imx6ull-14x14-emmc-7-1024x600-c.dtb这个名字。

文档出错简直是要新手的命啊。

bootm

bootm用于启动uImage 镜像。。

boot

boot命令引用bootcmd变量来启动linux。将启动方式放在bootcmd中,直接使用boot命令即可使用该方式启动linux。bootcmd中可以存放任意一种启动方式。

9.其他命令

reset

重启uboot

go

跳到指定的地址处直接执行应用。

run

运行环境变量中定义的命令。

mtest

内存读写测试命令。

mtest [start [end [pattern [iterations]]]] start是起始地址,end为结束地址。