【Linux驱动学习】第一篇-Uboot基础部分之基础知识点

学习过程中的资料:该部分学习是参考正点原子的“【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.8”文档进行学习编写。正点原子官方资料下载

1-Uboot简介

Linux 系统要启动就必须需要一个 bootloader 程序,也就说芯片上电以后先运行一段bootloader 程序。这段bootloader程序会先初始化DDR等外设,然后将Linux内核从flash(NAND,NOR FLASH,SD,EMMC 等)拷贝到 DDR 中,最后启动 Linux 内核。当然了,bootloader 的实际工作要复杂的多,但是它最主要的工作就是启动 Linux 内核, bootloader 和 Linux 内核的关系就跟 PC 上的 BIOS 和 Windows 的关系一样,bootloader 就相当于 BIOS。所以我们要先搞定bootloader,很庆幸,有很多现成的 bootloader 软件可以使用,比如 U-Boot、vivi、RedBoot 等等,其中以 U-Boot 使用最为广泛,[下载地址]

2-Uboot初次编译

2.1-使用Ubuntu来编译Uboot,需要先安装ncurses库,否则会编译报错。

sudo apt-get install libncurses5-dev

2.2-将下载的压缩包进行解压,我这里是使用6ullmini开发板,将下载的资料里面的Uboot包进行解压。这些资料去正点原子官网都可获取到,文章开头有链接地址,下载方式官方给的很清楚。

tar -vxjf uboot-imx-2016.03-2.1.0-g8b546e4.tar.bz2

2.3-还需要进行一些配置,按照自己需求进行配置架构、交叉编译工具等。

1 #!/bin/bash
2 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
3 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_defconfig
4 make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12

3-Uboot命令使用

在uboot下有很多命令可以使用,和Linux极为相似。

1、信息查询命令

常用的和信息查询有关的命令有 3 个: bdinfo、 printenv 和 version。
bdinfo:用于查看板子信息,直接输入bdinfo即可查看板子信息。
printenv:用于输出环境变量信息,uboot中有很多的环境变量,直接输入print也可以。
version:用于查看uboot版本。

2、内存操作命令

常用的内存操作命令有 md、 nm、mm、 mw、 cp 和 cmp。
md:用于显示内存值。

md[.b, .w, .l] address [# of objects]

命令中的[.b .w .l]对应 byte、 word 和 long,也就是分别以 1 个字节、 2 个字节、 4 个字节来显示内存值。 address 就是要查看的内存起始地址, [# of objects]表示要查看的数据长度,数据长度单位不是字节,而是跟你所选择的显示格式有关。比如你设置要查看的内存长度为20(十六进制为 0x14),如果显示格式为.b 的话那就表示 20 个字节;如果显示格为.w 的话就表示 20 个 word,也就是202=40 个字节;如果显示格式为.l 的话就表示 20 个 long,也就是204=80 个字节。
nm:用于修改指定地址的内存值。
mm:也是修改指定地址内存值的,使用 mm 修改内存值的时候地址会自增,而使用命令 nm 的话地址不会自增。
mw:用于使用一个指定的数据填充一段内存。
cp:数据拷贝命令,用于将 DRAM 中的数据从一段内存拷贝到另一段内存中,或者把 NorFlash 中的数据拷贝到 DRAM 中。
cmp:比较命令,用于比较两段内存的数据是否相等。

3、网络操作命令

uboot 是支持网络的,移植 uboot 的时候要调通网络功能,因为在移植 linux kernel 的时候需要使用到 uboot 的网络功能做调试。uboot 支持大量的网络相关命令,比如 ping、dhcp、nfs 和 tftpboot等。
ping:开发板的网络能否使用,是否可以和服务器(Ubuntu 主机)进行通信,通过 ping 命令就可以验证,直接 ping 服务器的 IP 地址即可。
dhcp:用于从路由器获取 IP 地址,前提得开发板连接到路由器上的,如果开发板是和电脑直连的,那么 dhcp 命令就会失效。直接输入 dhcp 命令即可通过路由器获取到 IP 地址。
nfs :nfs(Network File System)网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源,比如我们将 linux 镜像和设备树文件放到 Ubuntu 中,然后在 uboot 中使用 nfs 命令将 Ubuntu 中的 linux 镜像和设备树下载到开发板的 DRAM 中。这样做的目的是为了方便调试 linux 镜像和设备树,也就是网络调试,通过网络调试是 Linux 开发中最常用的调试方法。
tftpboot:tftp 命令的作用和 nfs 命令一样,都是用于通过网络下载东西到 DRAM 中,只是 tftp 命令使用的 TFTP 协议, Ubuntu 主机作为 TFTP 服务器。因此需要在 Ubuntu 上搭建 TFTP 服务器,需要安装 tftp-hpa 和 tftpd-hpa,命令如下:

sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd

顺便给tftp创建一个目录并且赋予其权限,然后配置tftp,该部分可在网上搜索关于搭建tftp服务的内容。我们通过这种方式就可以将uboot启动,也可将zImage启动。

4、EMMC和SD卡操作命令

uboot 支持 EMMC 和 SD 卡,因此也要提供 EMMC 和 SD 卡的操作命令,uboot 中常用于操作 EMMC 设备的命令为“mmc”,其后面可以跟很多的参数。
mmc info:用于输出当前选中的 mmc info 设备的信息,输入命令“mmc info”即可。
mmc rescan:用于扫描当前开发板上所有的 MMC 设备,包括 EMMC 和 SD 卡,输入“mmc rescan”即可。
mmc list:用于来查看当前开发板一共有几个 MMC 设备,输入“mmc list”。
mmc dev :用于切换当前 MMC 设备,命令格式如下:

mmc dev [dev] [part]

[dev]用来设置要切换的 MMC 设备号, [part]是分区号。如果不写分区号的话默认为分区 0。

mmc part:有时候 SD 卡或者 EMMC 会有多个分区,可以使用命令“mmc part”来查看其分区,比如查看 EMMC 的分区情况,输入如下命令:

mmc dev 1 //切换到 EMMC
mmc part //查看 EMMC 分区

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

mmc read addr blk# cnt

addr 是数据读取到 DRAM 中的地址, blk 是要读取的块起始地址(十六进制),一个块是 512字节,这里的块和扇区是一个意思,在 MMC 设备中我们通常说扇区, cnt 是要读取的块数量(十六进制)。比如从 EMMC 的第 1536(0x600)个块开始,读取 16(0x10)个块的数据到 DRAM 的0X80800000 地址处,命令如下:

mmc dev 1 0 //切换到 MMC 分区 0
mmc read 80800000 600 10 //读取数据

mmc write:要将数据写到 MMC 设备里面,可以使用命令“mmc write”,格式如下:

mmc write addr blk# cnt

addr 是要写入 MMC 中的数据在 DRAM 中的起始地址, blk 是要写入 MMC 的块起始地址(十六进制), cnt 是要写入的块大小,一个块为 512 字节。我们可以使用命令“mmc write”来升级 uboot,也就是在 uboot 中更新 uboot。这里要用到 nfs 或者 tftp 命令,通过 nfs 或者 tftp 命令将新的 u-boot.bin 下载到开发板的 DRAM 中,然后再使用命令“mmc write”将其写入到 MMC设备中。
mmc erase:如果要擦除 MMC 设备的指定块就是用命令“mmc erase”,命令格式如下:

mmc erase blk# cnt

blk 为要擦除的起始块, cnt 是要擦除的数量。没事不要用 mmc erase 来擦除 MMC 设备!!!

5、FAT格式文件系统操作命令

有时候需要在 uboot 中对 SD 卡或者 EMMC 中存储的文件进行操作,这时候就要用到文件操作命令,跟文件操作相关的命令有: fatinfo、 fatls、 fstype、 fatload 和 fatwrite,但是这些文件操作命令只支持 FAT 格式的文件系统!!
fatinfo:用于查询指定 MMC 设备分区的文件系统信息。
fatls:用于查询 FAT 格式设备的目录和文件信息。
fstype:用于查看 MMC 设备某个分区的文件系统格式。
fatload :用于将指定的文件读取到 DRAM 中。
fatwrite:注意! uboot 默认没有使能 fatwrite 命令,需要修改板子配置头文件,比如 mx6ullevk.h、mx6ull_alientek_emmc.h 等等,板子不同,其配置头文件也不同。找到自己开发板对应的配置头文件然后添加如下一行宏定义来使能 fatwrite 命令:

#define CONFIG_FAT_WRITE /* 使能 fatwrite 命令 */

fatwirte 命令用于将 DRAM 中的数据写入到 MMC 设备中,命令格式如下:

fatwrite <interface> <dev[:part]> <addr> <filename> <bytes>

interface 为接口,比如 mmc, dev 是设备号, part 是分区, addr 是要写入的数据在 DRAM中的起始地址, filename 是写入的数据文件名字, bytes 表示要写入多少字节的数据。

6、EXT格式文件系统操作命令

uboot 有 ext2 和 ext4 这两种格式的文件系统的操作命令,常用的命令分别为:ext2load、 ext2ls、 ext4load、 ext4ls 和 ext4write。这些命令的含义和使用与 fatload、 fatls 和 fatwrite一样,只是 ext2 和 ext4 都是针对 ext 文件系统的。

7、NAND操作命令

uboot 是支持 NAND Flash 的,所以也有 NAND Flash 的操作命令,前提是使用的 NAND 版本的核心板,并且编译 NAND 核心板对应的 uboot,然后使用 imxdownload 软件将 u-boot.bin 烧写到 SD 卡中,最后通过 SD 卡启动。一般情况下 NAND 版本的核心板已经烧写好了 uboot、linux kernel 和 rootfs 这些文件,所以可以将 BOOT 拨到 NAND,然后直接从 NAND Flash 启动即可。
nand info:此命令用户打印 NAND Flash 信息,输入“nand info”。
nand device:用于切换 NAND Flash,如果你的板子支持多片 NAND 的话就可以使用此命令来设置当前所使用的 NAND。这个需要你的 CPU 有两个 NAND 控制器,并且两个 NAND 控制器各接一片 NAND Flash。
nand erase :用于擦除 NAND Flash, NAND Flash 的特性决定了在向 NAND Flash 写数据之前一定要先对要写入的区域进行擦除。
nand write:此命令用于向 NAND 指定地址写入指定的数据,一般和“nand erase”命令配置使用来更新NAND 中的 uboot、 linux kernel 或设备树等文件。
nand read :此命令用于从 NAND 中的指定地址读取指定大小的数据到 DRAM 中。

8、BOOT操作命令

uboot 的本质工作是引导 Linux,所以 uboot 肯定有相关的 boot(引导)命令来启动 Linux。常用的跟 boot 有关的命令有: bootz、 bootm 和 boot。
bootz:要启动 Linux,需要先将 Linux 镜像文件拷贝到 DRAM 中,如果使用到设备树的话也需要将设备树拷贝到 DRAM 中。可以从 EMMC 或者 NAND 等存储设备中将 Linux 镜像和设备树文件拷贝到 DRAM,也可以通过 nfs 或者 tftp 将 Linux 镜像文件和设备树文件下载到 DRAM 中。不管用那种方法,只要能将 Linux 镜像和设备树文件存到 DRAM 中就行,然后使用 bootz 命令来启动, bootz 命令用于启动 zImage 镜像文件, bootz 命令格式如下:

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

命令 bootz 有三个参数, addr 是 Linux 镜像文件在 DRAM 中的位置, initrd 是 initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘-’代替即可, fdt 就是设备树文件在 DRAM 中的地址。
bootm :bootm 和 bootz 功能类似,但是 bootm 用于启动 uImage 镜像文件。如果不使用设备树的话启动 Linux 内核的命令如下:

bootm addr

addr 是 uImage 镜像在 DRAM 中的首地址。
如果要使用设备树,那么 bootm 命令和 bootz 一样,命令格式如下:

bootm [addr [initrd[:size]] [fdt]]

其中 addr 是 uImage 在 DRAM 中的首地址, initrd 是 initrd 的地址, fdt 是设备树(.dtb)文件在 DRAM 中的首地址,如果 initrd 为空的话,同样是用“-”来替代。
boot:boot 命令也是用来启动 Linux 系统的,只是 boot 会读取环境变量 bootcmd 来启动 Linux 系统, bootcmd 是一个很重要的环境变量!其名字分为“boot”和“cmd”,也就是“引导”和“命令”,说明这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。

9、其它操作命令

uboot 中还有其他一些常用的命令,比如 reset、 go、 run 和 mtest 等。

4-Uboot顶层Makefile简介

4.1 Uboot工程目录分析,Uboot在没有编译之前文件较少,在编译之后会生成很多其他的文件,编译前后对比如下。
未编译
在这里插入图片描述
4.2-uboot顶层Makefile简介,uboot的Makefile和Linux的Makefile比较相似,因为uboot参考Linux设计,关于该部分,本文大致列出Makefile框架。
1、版本号:顶层 Makefile 一开始是版本号。
2、MAKEFLAGS 变量:make 是支持递归调用的,也就是在 Makefile 中使用“make”命令来执行其他的 Makefile文件,一般都是子目录中的 Makefile 文件。
3、命令输出:uboot 默认编译是不会在终端中显示完整的命令,都是短命令,在终端中输出短命令虽然看起来很清爽,但是不利于分析 uboot 的编译过程。可以通过设置变量“V=1“来实现完整的命令输出,这个在调试 uboot 的时候很有用,在其Makefile中也有体现。
4、静默输出:设置 V=0 或者在命令行中不定义 V 的话,编译 uboot 的时候终端中显示的短命令,但是还是会有命令输出,有时候我们在编译 uboot 的时候不需要输出命令,这个时候就可以使用 uboot 的静默输出功能。编译的时候使用“make -s”即可实现静默输出。
5、设置编译结果输出目录:uboot 可以将编译出来的目标文件输出到单独的目录中,在 make 的时候使用“O”来指定输出目录,比如“make O=out”就是设置目标文件输出到 out 目录中。这么做是为了将源文件和编译产生的文件分开,当然也可以不指定 O 参数,不指定的话源文件和编译产生的文件都在同一个目录内,一般我们不指定 O 参数。
6、代码检查:uboot 支持代码检查,使用命令“make C=1”使能代码检查,检查那些需要重新编译的文件。“make C=2”用于检查所有的源码文件。
7、模块编译:在 uboot 中允许单独编译某个模块,使用命令“ make M=dir”即可,旧语法“ makeSUBDIRS=dir”也是支持的。
8、获取主机架构和系统:顶层 Makefile 会获取主机架构和系统,也就是我们电脑的架构和系统,代码如下:

227 HOSTARCH := $(shell uname -m | \
228 sed -e s/i.86/x86/ \
229 -e s/sun4u/sparc64/ \
230 -e s/arm.*/arm/ \
231 -e s/sa110/arm/ \
232 -e s/ppc64/powerpc/ \
233 -e s/ppc/powerpc/ \
234 -e s/macppc/powerpc/\
235 -e s/sh.*/sh/)
236
237 HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
238 sed -e 's/\(cygwin\).*/cygwin/')
239
240 export HOSTARCH HOSTOS

这里前面的行号和实际的uboot源码里面的Makefile差不多,但是也许会有少许更改。

9、设置目标架构、交叉编译器和配置文件:编 译 uboot 的 时 候 需 要 设 置 目 标 板 架 构 和 交 叉 编 译 器 ,“ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- ”就是用于设置 ARCH 和 CROSS_COMPILE,在顶层Makefile 中代码如下:

244 # set default to nothing for native builds
245 ifeq ($(HOSTARCH),$(ARCH))
246 CROSS_COMPILE ?=
247 endif
248
249 KCONFIG_CONFIG ?= .config
250 export KCONFIG_CONFIG

10、调用 scripts/Kbuild.include:主 Makefile 会调用文件 scripts/Kbuild.include 这个文件,顶层 Makefile 中代码如下:

327 # We need some generic definitions (do not try to remake the file).
328 scripts/Kbuild.include: ;
329 include scripts/Kbuild.include

11、交叉编译工具变量设置:上面我们只是设置了 CROSS_COMPILE 的名字,但是交叉编译器其他的工具还没有设置,顶层 Makefile 中相关代码如下:

331 # Make variables (CC, etc...)
332
333 AS = $(CROSS_COMPILE)as
334 # Always use GNU ld
335 ifneq ($(shell $(CROSS_COMPILE)ld.bfd -v 2> /dev/null),)
336 LD = $(CROSS_COMPILE)ld.bfd
337 else
338 LD = $(CROSS_COMPILE)ld
339 endif
340 CC = $(CROSS_COMPILE)gcc
341 CPP = $(CC) -E
342 AR = $(CROSS_COMPILE)ar
343 NM = $(CROSS_COMPILE)nm
344 LDR = $(CROSS_COMPILE)ldr
345 STRIP = $(CROSS_COMPILE)strip
346 OBJCOPY = $(CROSS_COMPILE)objcopy
347 OBJDUMP = $(CROSS_COMPILE)objdump

12、导出其他变量:顶层 Makefile 会导出很多变量,代码如下:

368 export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION
369 export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
370 export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC
371 export CPP AR NM LDR STRIP OBJCOPY OBJDUMP
372 export MAKE AWK PERL PYTHON
373 export HOSTCXX HOSTCXXFLAGS DTC CHECK CHECKFLAGS
374
375 export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS
376 export KBUILD_CFLAGS KBUILD_AFLAGS

13、make xxx_defconfig 过程:在编译 uboot 之前要使用“make xxx_defconfig”命令来配置 uboot,那么这个配置过程是如何运行的呢?在顶层 Makefile 中有如下代码:

414 # To make sure we do not include .config for any of the *configtargets
415 # catch them early, and hand them over to scripts/kconfig/Makefile
416 # It is allowed to specify more targets when calling make, including
417 # mixing *config targets and build targets.
418 # For example 'make oldconfig all'.
419 # Detect when mixed targets is specified, and make a second invocation
420 # of make so .config is not included in this case either (for*config).
421
422 version_h := include/generated/version_autogenerated.h
423 timestamp_h := include/generated/timestamp_autogenerated.h
424
425 no-dot-config-targets := clean clobber mrproper distclean \
426 help %docs check% coccicheck \
427 ubootversion backup
428
429 config-targets := 0
430 mixed-targets := 0
431 dot-config := 1
432

14、Makefile.build 脚本分析:该部分需要分析scripts/Makefile.build,主要包括两部分的拆分,一个是scripts_basic 目标对应的命令;另一个则是%config 目标对应的命令。这两个部分分析起来比较麻烦,可参考正点原子手册或者网上搜索。
15、make 过程:配置好 uboot 以后就可以直接 make 编译了,因为没有指明目标,所以会使用默认目标,主Makefile 中的默认目标如下:

128 # That's our default target when none is given on the command line
129 PHONY := _all
130 _all:

目标_all 又依赖于 all,如下所示:

194 # If building an external module we do not care about the all: rule
195 # but instead _all depend on modules
196 PHONY += all
197 ifeq ($(KBUILD_EXTMOD),)
198 _all: all
199 else
200 _all: modules
201 endif

以上的就是整个Makefile的大致流程,详细分析的话可以参考正点原子的官方文档或者网上搜索,将uboot的Makefile流程搞明白之后,在学习Linux内核的话就很轻松,因为这两个大致一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值