Linux驱动学习之---体验uboot
前言:在上一节中编译了uboot,接下来就实际体验一下uboot
uboot的启动过程是怎么样的?
U-Boot的启动过程是一个多阶段、结构化的流程。首先,处理器从重置向量开始执行,进行基础的硬件设置和初始化,为U-Boot建立基础运行环境。接着,U-Boot进行低级的硬件初始化,如时钟、内存控制器和串口,以便U-Boot能够使用内存和串口。然后,U-Boot将自己从非易失性存储中复制到RAM中运行,进行重定位。随后,进行板级初始化,包括网络接口、存储设备等,并进行特定于具体硬件平台的初始化。接下来,U-Boot初始化环境变量,加载配置和启动参数。完成所有初始化后,U-Boot提供命令行接口,用户可以输入命令来控制U-Boot,并可配置自动启动。用户通过U-Boot命令加载操作系统,然后使用bootm命令启动操作系统。最后,U-Boot设置操作系统参数并将控制权交给操作系统,完成其任务。这个流程虽然复杂,但每个阶段都有其明确的目标和任务,共同构建了系统的启动过程。
以下是各个阶段的工作
1. 重置向量和处理器初始化
- 当系统上电或重置时,处理器会从重置向量开始执行代码。重置向量通常指向一段初始化代码,这段代码会进行一些基础的硬件设置和初始化。
- 这一阶段主要包括设置堆栈、清除 BSS 段、初始化处理器的模式和状态等。
2. 低级初始化
- 在这一阶段,U-Boot 会进行一些低级的硬件初始化,包括初始化时钟、内存控制器、串口等。
- 这一阶段的目标是建立一个基础的运行环境,使得 U-Boot 能够使用内存和串口。
3. 重定位 U-Boot 到 RAM
- U-Boot 的初始部分通常是存储在闪存或其他非易失性存储中的,但为了更高的运行效率,U-Boot 会将自己从这些存储中复制到 RAM 中运行。
- 重定位包括复制 U-Boot 的代码和数据到 RAM,并更新相关的指针和地址。
4. 板级初始化
- 在这一阶段,U-Boot 会进行更多的硬件初始化,包括初始化网络接口、存储设备等。
- 这一阶段还会进行一些板级特定的初始化,这些初始化是依赖于具体硬件平台的。
5. 环境变量初始化
- U-Boot 会初始化环境变量。环境变量通常存储在闪存或其他非易失性存储中,包含了 U-Boot 的配置和启动参数。
- U-Boot 会加载这些环境变量,并根据这些变量来配置自己的行为。
6. 命令行接口和自动启动
- 在完成了以上所有初始化之后,U-Boot 会提供一个命令行接口,用户可以通过这个接口输入命令来控制 U-Boot。
- 如果配置了自动启动,U-Boot 会在一段延时之后自动执行预配置的启动命令来启动操作系统。
7. 加载和启动操作系统
- 用户可以通过 U-Boot 的命令来加载操作系统内核、设备树和 ramdisk 到内存中。
- 加载完成后,用户可以使用
bootm或其他相关命令来启动操作系统。
8. 交控制权给操作系统
- U-Boot 会设置好操作系统需要的参数,并将控制权交给操作系统内核。
- 从这一点开始,操作系统接管系统控制,U-Boot 的任务就完成了。

在上电之后串口打印出的这些信息是什么,接下来逐一了解下
上电打印信息
U-Boot 版本和编译时间
U-Boot 2016.03 (Sep 29 2023 - 09:48:15 +0800)这一行显示了 U-Boot 的版本(2016.03)和它的编译时间(2023年9月29日,09:48:15,+0800 表示时区)。
CPU 信息
CPU: Freescale i.MX6ULL rev1.1 792 MHz (running at 396 MHz)
CPU: Industrial temperature grade (-40C to 105C) at 43C这两行显示了 CPU 的型号(Freescale i.MX6ULL rev1.1),其最大频率(792 MHz),当前运行频率(396 MHz),工作温度范围(-40C 到 105C),以及当前温度(43C)。
Reset Cause
Reset cause: POR这一行显示了系统最后一次重启的原因。在这里,POR 表示 Power-On Reset,即上电复位。
Board 信息
Board: I.MX6U ALPHA|MINI这一行显示了当前使用的开发板的名称或型号。
I2C 状态
I2C: ready这一行显示了 I2C 接口的状态,这里是准备就绪。
DRAM 信息
DRAM: 512 MiB这一行显示了系统的 DRAM 大小,这里是 512 MiB。
MMC 信息
MMC: FSL_SDHC: 0, FSL_SDHC: 1这一行显示了可用的 MMC(MultiMediaCard)设备,这里有两个,分别是 FSL_SDHC: 0 和 FSL_SDHC: 1。
环境变量 CRC 警告
*** Warning - bad CRC, using default environment这一行显示了一个警告,表明环境变量的 CRC(循环冗余校验)校验失败,因此 U-Boot 使用默认的环境变量。
输入/输出/错误流
In: serial
Out: serial
Err: serial这三行显示了 U-Boot 的输入、输出和错误流都被设置为串行接口。
网络接口
Net: FEC1
Error: FEC1 address not set.这两行显示了网络接口的信息。FEC1 是网络接口的名称,但它的地址尚未设置,这可能意味着网络接口未正确配置。
自动引导
Normal Boot
Hit any key to stop autoboot: 0这两行显示了 U-Boot 正在尝试正常引导,并且用户可以按任意键来中止自动引导过程。
默认倒计时 3 秒,倒计时结束之前按下回车键就会进入 Linux 命令
行模式。如果在倒计时结束以后没有按下回车键,那么 Linux 内核就会启动,Linux 内核一旦启
动,uboot 就会寿终正寝。
查看uboot支持的指令
uboot 是来干活的,倒计时结束之前按下回车,我们现在已经进入 uboot 的命令行模式了,进入命令行模式以后就可以给 uboot 发号施令了,
uboot 支持哪些指令??
我们可以通过
help 或者 ? 查看这与linux下的 --help 类似


支持的指令这里没有全部贴出来,串口打印的这些指令并不是uboot的所有,我们还可以去构建更多指令
具体指令的说明
举例:我们要查看GPIO的指令

可使用
? gpio 或者 help gpio注:中间有空格

以上的图中详细列出了gpio这个命令的详情
接下来看下常用的命令
信息查询命令
常用的和信息查询有关的命令有 3 个:bdinfo、printenv 和 version

// bdinfo 命令输出的解释
// arch_number 表示系统架构的编号。0x00000000 通常表示未设置。
unsigned int arch_number = 0x00000000;
// boot_params 是内核引导参数的内存地址。
unsigned int boot_params = 0x80000100;
// DRAM bank 的相关信息
struct DRAMBank {
unsigned int start; // DRAM 的起始地址
unsigned int size; // DRAM 的大小
} dram_bank = {0x80000000, 0x20000000}; // start 是 DRAM 的起始地址,size 是 DRAM 的大小,即 512 MiB。
// eth0name 是第一个以太网接口的名称,current eth 是当前使用的以太网接口的名称。
char eth0name[] = "FEC1";
char current_eth[] = "FEC1";
// ethaddr 是以太网接口的 MAC 地址,这里它没有被设置。
// ip_addr 是 IP 地址,这里它也没有被设置。
char ethaddr[] = "(not set)";
char ip_addr[] = "<NULL>";
// baudrate 是串行接口的波特率,这里是 115200 比特每秒。
unsigned int baudrate = 115200;
// TLB addr 是 Translation Lookaside Buffer(TLB)的地址。
// relocaddr 是 U-Boot 重定位地址。
unsigned int tlb_addr = 0x9FFF0000;
unsigned int relocaddr = 0x9FF55000;
// reloc off 是 U-Boot 重定位偏移量。
unsigned int reloc_off = 0x18755000;
// irq_sp 是中断堆栈指针的地址。
// sp start 是堆栈指针的起始地址。
unsigned int irq_sp = 0x9EF52EA0;
unsigned int sp_start = 0x9EF52E90;
->符号通常用于表示属于某个分类或者结构体的成员。在这个例子中,-> start 和 -> size 是 DRAM bank 的成员,表示DRAM bank的起始地址和大小。

在U-Boot的环境变量中,有几个重要的信息和变量,这些变量定义了系统的启动行为和一些重要的系统参数。以下是一些重要的变量和它们的意义:
# U-Boot Environment Variables
baudrate=115200
# 定义了串行通信的波特率,即串行通信的速度。
bootcmd=...
# 系统启动时执行的命令。定义了一系列的启动脚本和条件,用于尝试从不同的来源加载和启动操作系统。
bootdelay=1
# 启动延迟,定义了用户可以中断自动启动过程的时间。
console=ttymxc0
# 定义了系统控制台的设备。
ethact=FEC1
ethprime=FEC
# 定义了以太网活动和主要的网络接口。
fdt_file=imx6ull-14x14-evk.dtb
# 设备树二进制文件的名称,用于定义硬件的结构和配置。
image=zImage
# 定义了要加载的内核映像的名称。
loadaddr=0x80800000
# 定义了内核映像加载到RAM的地址。
mmcdev=0
mmcpart=1
# 定义了MMC设备的编号和分区。
mmcroot=/dev/mmcblk0p2 rootwait rw
# 定义了根文件系统的位置和类型。
netargs=...
netboot=...
# 定义了通过网络启动时的参数和启动命令。
script=boot.scr
# 定义了启动脚本的名称。
stderr=serial
stdin=serial
stdout=serial
# 定义了标准错误、标准输入和标准输出的设备,这里都设置为串行设备。

arm-linux-gnueabihf-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0显示的是用于编译U-Boot的GCC编译器的信息。这里,编译器的目标架构是arm-linux-gnueabihf,这是一个硬浮点的ARM架构。编译器的版本是11.4.0,它是Ubuntu 22.04的一部分。如果获得别人编译好的UBOOT,自己编译不成功大概是交叉编译工具链接的问题,我们可以通过这里来查看
GNU(GNU's Not Unix)是一个自由、开源的操作系统项目,其目标是开发一套完全自由的Unix兼容操作系统。
环境变量操作命令
环境变量的操作涉及到两个命令:setenv 和 saveenv,命令 setenv 用于设置或者修改环境变
量的值。命令 saveenv 用于保存修改后的环境变量,一般环境变量是存放在外部 flash 中的,
uboot 启动的时候会将环境变量从 flash 读取到 DRAM 中。所以使用命令 setenv 修改的是 DRAM
中的环境变量值,修改以后要使用 saveenv 命令将修改后的环境变量保存到 flash 中,否则的话
uboot 下一次重启会继续使用以前的环境变量值。
举例:
命令 saveenv 使用起来很简单,格式为:
saveenv
比如我们要将环境变量 bootdelay 改为 5,就可以使用如下所示命令:
setenv bootdelay 5
saveenv其中,环境变量bootdelay为启动时候进入到linux内核的倒计时,前面说了默认是3s

重启看看,按下复位按键,刚启动时,时间变成了5

新建环境变量
命令 setenv 也可以用于新建命令,用法和修改环境变量一样,比如我们新建一个环境变量名称(可自定义)
author,author 的值为我的名字拼音:hedejiang,那么就可以使用如下命令:
setenv author hedejiang
saveenv新建命令 author 完成以后重启 uboot,然后使用命令 printenv 查看当前环境变量


删除环境变量
刚才我们创建了一个环境变量,author = hedejiang 现在将它删除
只删除环境变量的名称就可以了
setenv author
saveenv可以看到刚才的环境变量没了

环境变量作用
U-Boot中的环境变量可以被用来替代命令中的具体值。当你在U-Boot命令中使用环境变量时,它会被解析为该变量的值。例如,如果你有一个环境变量定义如下:
setenv ipaddr 192.168.1.10然后,如果在另一个命令中使用${ipaddr},它会被替换为192.168.1.10。例如:
ping ${ipaddr}这条命令会被解析为:
ping 192.168.1.10同样地,如果环境变量包含了一系列的命令或参数,使用run命令执行这个变量会执行这一系列的命令或参数。例如:
setenv bootcommands 'setenv bootargs root=/dev/mmcblk0p2 rw rootwait; bootm 0x82000000'
run bootcommands在这个例子中,run bootcommands会执行setenv bootargs root=/dev/mmcblk0p2 rw rootwait; bootm 0x82000000这一系列的命令。
这种替代机制允许用户创建灵活和可配置的启动脚本和命令,可以根据不同的需求和条件来动态地改变它们的行为。
内存操作命令:
内存操作命令就是用于直接对 DRAM 进行读写操作的,常用的内存操作命令有 md、nm、
mm、mw、cp 和 cmp。我们依次来看一下这些命令都是做什么的
注:uboot 命令中的数字都是十六进制的!不是十进制的!
1. md (Memory Display)
- 用途:用于显示内存中的内容。
- 语法:
md [地址] [数量] - 示例:
md 0x80000000 10,显示从地址0x80000000开始的16个32位字。(0X10=16)

其中命令md的扩展
md[.b, .w, .l] address [# of objects] 其中 [.b .w .l]对应 byte、word 和 long也就是分别以 1 个字节、2 个字节、4 个字节来显示内存值。
示例 :
md.b 0x80800000 2
其他 md.w md.l 不演示了,应该能理解
2. nm (Memory Modify (constant address))
- 用途:用于修改内存中的内容,地址不变。
- 语法:
nm [地址] - 示例:
nm 0x80000000,修改地址0x80000000处的内容。
3. mm (Memory Modify (auto-incrementing address))
- 用途:用于修改内存中的内容,地址自增。
- 语法:
mm [地址] - 示例:
mm 0x80000000,修改从地址0x80000000开始的内容,地址自动递增。
4. mw (Memory Write)
- 用途:用于向内存写入数据。
- 语法:
mw [地址] [数据] [数量] - 示例:
mw 0x80000000 0x1234 10,将10个32位字的数据0x1234写入从地址0x80000000开始的内存。
5. cp (Memory Copy)
- 用途:用于复制内存中的数据。
- 语法:
cp [源地址] [目标地址] [数量] - 示例:
cp 0x80000000 0x81000000 10,将从地址0x80000000开始的10个32位字的数据复制到从地址0x81000000开始的内存。
6. cmp (Memory Compare)
- 用途:用于比较内存中的数据。
- 语法:
cmp [地址1] [地址2] [数量] - 示例:
cmp 0x80000000 0x81000000 10,比较从地址0x80000000和0x81000000开始的10个32位字的数据是否相同。
不禁好奇 uboot中内存操作命令 对于实际开发中有什么作用?
- 当我们谈论在U-Boot中进行调试时,通常是指在U-Boot运行期间,也就是在系统启动过程中的U-Boot阶段进行的调试。这包括硬件初始化阶段、内核加载阶段,以及可能的U-Boot脚本执行阶段。
- 一旦U-Boot将控制权传递给Linux内核,U-Boot的运行就会结束,此时将无法再使用U-Boot的命令进行调试。在这一点之后,开发人员需要使用Linux内核和用户空间工具进行进一步的调试。
在U-Boot中,内存操作命令主要用于开发和调试阶段,它们允许开发人员直接访问和修改内存中的数据。以下是这些命令在实际开发中的一些用途:
- 开发人员可以使用这些命令来检查和验证内存中的数据是否正确,例如,检查加载到内存中的内核映像或设备树的完整性。
- 在硬件调试过程中,可以用于验证某些硬件寄存器的状态和值。
mm和mw命令允许开发人员直接修改内存中的数据,这对于测试不同的配置或参数而不重新编译代码非常有用。cp命令可以用于在内存的不同区域之间复制数据,这在需要移动数据时很有用,例如,将内核映像从一个加载地址复制到另一个执行地址。cmp命令可以用于比较内存中的两个区域的数据,这对于验证数据的完整性和一致性很有用。- 这些命令允许开发人员快速尝试不同的参数和配置,以测试系统的行为和性能。
- 在系统出现问题时,开发人员可以使用这些命令来检查和修改内存中的数据,以帮助识别和解决问题。
- 这些命令可以在U-Boot的启动脚本中使用,以实现自动配置和初始化过程。
结合以上所述,内存操作指令对于uboot调试来说确实不错,学习uboot应该是必须要掌握的
网络操作指令:
uboot 是支持网络的,我们在移植 uboot 的时候一般都要调通网络功能,因为在移植 linux
kernel 的时候需要使用到 uboot 的网络功能做调试。uboot 支持大量的网络相关命令,比如 dhcp、
ping、nfs 和 tftpboot,接下来依次学习一下这几个和网络有关的命令。
在使用 uboot 的网络功能之前先用网线将开发板的 ENET2 接口和电脑或者路由器连接起
来,I.MX6U-ALPHA 开发板有两个网口:ENET1 和 ENET2,一定要连接 ENET2,不能连接错
了(i.mx6ull靠近rs232的网口)


我先不配置静态ip,使用dhcp方式 我的路由ip为192.168.5.1
setenv ethaddr b8:ae:1d:01:00:00
setenv gatewayip 192.168.5.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.253
saveenv
网络操作指令单独写一章节吧:内容较多 link
emmc和sd卡操作指令
uboot 支持 EMMC 和 SD 卡,因此也要提供 EMMC 和 SD 卡的操作命令。一般认为 EMMC
和 SD 卡是同一个东西,这里把SD也叫做emmc
mmc 是一系列的命令,其后可以跟不同的参数,输入“?mmc”即可查看 mmc 有关的命令

从以上的信息中可以看出支持的指令

介绍常用的
mmc info 指令
mmc设备信息(mmc/sd)

Device: FSL_SDHC
- 表示 MMC/SD 卡的设备名称,这里是 Freescale 的 SDHC 控制器。
Manufacturer ID: 89
- 制造商 ID,这是一个唯一标识制造商的值。
OEM: 303
- OEM ID,表示原始设备制造商的标识符。
Name: NCard
- 卡的名称或品牌。
Tran Speed: 50000000
- 传输速度,单位是位/秒,这里是 50,000,000 位/秒,或 50 MHz。
Rd Block Len: 512
- 读块长度,表示每个数据块的字节数,这里是 512 字节。
SD version 3.0
- SD 卡的版本,这里是 3.0 版本。
High Capacity: Yes
- 高容量标志,如果是 "Yes",表示这是一张高容量 SD 卡 (SDHC/SDXC)。
Capacity: 7.5 GiB
- 卡的总容量,这里是 7.5 GiB。
Bus Width: 4-bit
- 总线宽度,表示数据总线的宽度,这里是 4 位。
Erase Group Size: 512 Bytes
- 擦除组大小,表示擦除操作影响的最小数据量,这里是 512 字节。
mmc read 指令
读取mmc中数据

1. mmc info
- 显示当前 MMC 设备的信息。
2. mmc read addr blk# cnt
- 从 MMC/SD 卡的指定块读取数据到内存中的指定地址。
3. mmc write addr blk# cnt
- 将数据从内存中的指定地址写入 MMC/SD 卡的指定块。
4. mmc erase blk# cnt
- 擦除 MMC/SD 卡上的指定块。
5. mmc rescan
- 重新扫描 MMC/SD 卡。
6. mmc part
- 列出当前 MMC 设备上可用的分区。
7. mmc dev [dev] [part]
- 显示或设置当前 MMC 设备[分区]。
8. mmc list
- 列出可用设备。
9. mmc hwpartition [args...]
- 执行硬件分区。
- 有多个参数和模式,可以设置用户数据区属性、通用目的分区等。
10. mmc bootbus dev boot_bus_width reset_boot_bus_width boot_mode
- 设置指定设备的 BOOT_BUS_WIDTH 字段。
11. mmc bootpart-resize <dev> <boot part size MB> <RPMB part size MB>
- 更改指定设备的 boot 和 RPMB 分区的大小。
12. mmc partconf dev boot_ack boot_partition partition_access
- 更改指定设备的 PARTITION_CONFIG 字段的位。
13. mmc rst-function dev value
- 更改指定设备的 RST_n_FUNCTION 字段。
- 这是一个一次性写入字段,只有 0 / 1 / 2 是有效值。
14. mmc setdsr <value>
- 设置 DSR 寄存器值。
mmc write 指令
mmc write addr blk# cnt
mmc rescan指令
mmc rescan 命令用于扫描当前开发板上所有的 MMC 设备,包括 EMMC 和 SD 卡,输入
“mmc rescan”即可。
咱这啥也没有?

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

mmc dev指令
mmc dev 命令用于切换当前 MMC 设备,命令格式如下:
mmc dev [dev] [part]
[dev]用来设置要切换的 MMC 设备号,
[part]是分区号。如果不写分区号的话默认为分区 0。
使用如下命令切换到 SD 卡:
mmc dev 0 
mmc list 指令
mmc list 命令用于来查看当前开发板一共有几个 MMC 设备

mmc erase指令
慎用:
mmc erase blk# cntblk 为要擦除的起始块,cnt 是要擦除的数量。没事不要用 mmc erase 来擦除 MMC 设备!!!
FAT格式文件操作指令
有时候需要在 uboot 中对 SD 卡或者 EMMC 中存储的文件进行操作,这时候就要用到文件
操作命令,跟文件操作相关的命令有:fatinfo、fatls、fstype、fatload 和 fatwrite,但是这些文件
操作命令只支持 FAT 格式的文件系统!!
fatinfo 命令
fatinfo 命令用于查询指定 MMC 设备分区的文件系统信息,格式如下:
fatinfo <interface> [<dev[:part]>]interface 表示接口,比如 mmc,dev 是查询的设备号,part 是要查询的分区。比如我们要查
询 EMMC 分区 1 的文件系统信息,命令如下:
fatinfo mmc 1:1
Interface: MMC
- 表示这是一个 MMC(多媒体卡)接口。
Device 1:
- 表示这是设备编号为 1 的设备。
Vendor: Man 000015 Snr cfaa58ac Rev: 0.6 Prod: 8GTF4R
- Vendor: 表示制造商信息。
- Man 000015: 制造商 ID。
- Snr cfaa58ac: 序列号。
- Rev: 0.6: 版本号。
- Prod: 8GTF4R: 产品型号。
Type: Removable Hard Disk
- 表示这是一种可移动硬盘。
Capacity: 7456.0 MB = 7.2 GB (15269888 x 512)
- 表示设备的容量为 7456.0 MB,即 7.2 GB,由 15269888 个 512 字节的块组成。
Filesystem: FAT32 "NO NAME "
- 表示设备上的文件系统类型为 FAT32。
- "NO NAME ": 表示该设备没有卷标,或卷标为 "NO NAME"。
fatls命令
fatls 命令用于查询 FAT 格式设备的目录和文件信息,命令格式如下:
fatls
interface 是要查询的接口,比如 mmc,dev 是要查询的设备号,part 是要查询的分区,directory
是要查询的目录。比如查询 EMMC 分区 1 中的所有的目录和文件,输入命令:
fatls mmc 1:1
fstype 命令
fstype 用于查看 MMC 设备某个分区的文件系统格式,命令格式如下:
fstype
正点原子 EMMC 核心板上的 EMMC 默认有 3 个分区,我们来查看一下这三个分区的文件
系统格式,输入命令:
fstype mmc 1:0
fstype mmc 1:1
fstype mmc 1:2
从上图可以看出,分区 0 格式未知,因为分区 0 存放的 uboot,并且分区 0 没有格式化,所
以文件系统格式未知。分区 1 的格式为 fat,分区 1 用于存放 linux 镜像和设备树。分区 2 的格
式为 ext4,用于存放 Linux 的根文件系统(rootfs)。
fatload 命令
fatload 命令用于将指定的文件读取到 DRAM 中,命令格式如下:
fatload
interface 为接口,比如 mmc,dev 是设备号,part 是分区,addr 是保存在 DRAM 中的起始
地址,filename 是要读取的文件名字。bytes 表示读取多少字节的数据,如果 bytes 为 0 或者省
略的话表示读取整个文件。pos 是要读的文件相对于文件首地址的偏移,如果为 0 或者省略的
话表示从文件首地址开始读取。我们将 EMMC 分区 1 中的 zImage 文件读取到 DRAM 中的
0X80800000 地址处,命令如下:
fatload mmc 1:1 80800000 zImage
从上图可以看出在 222ms 内读取了 6785480 个字节的数据,速度为 29.1MiB/s,速度是非
常快的,因为这是从 EMMC 里面读取的,而 EMMC 是 8 位的,速度肯定会很快的。
fatwrite 命令
注意!uboot 默认没有使能 fatwrite 命令,需要修改板子配置头文件,比如 mx6ullevk.h、
mx6ull_alientek_emmc.h 等等,板子不同,其配置头文件也不同。找到自己开发板对应的配置头
文件然后添加如下一行宏定义来使能 fatwrite 命令:
#define CONFIG_FAT_WRITE /* 使能 fatwrite 命令 */fatwrite 命令
EXT 格式文件系统操作命令
uboot 有 ext2 和 ext4 这两种格式的文件系统的操作命令
常用的就五个命令,分别为:
ext2load、ext2ls、ext4load、ext4ls 和 ext4write
这些命令的含义和使用与 fatload、fatls 和 fatwrite
一样,只是 ext2 和 ext4 都是针对 ext 文件系统的。比如 ext4ls 命令,EMMC 的分区 2 就是 ext4
格式的,使用 ext4ls 就可以查询 EMMC 的分区 2 中的文件和目录,输入命令:
ext4ls mmc 1:2
NAND 操作命令
uboot 是支持 NAND Flash 的,所以也有 NAND Flash 的操作命令,前提是使用的 NAND 版
本的核心板,由于我的是emmc版,无法演示,这里只给出命令,直接搬正点原子的了
nand info 命令
此命令用户打印 NAND Flash 信息,
nand info
nand device 命令
用到较少
nand device 用于切换 NAND Flash,如果你的板子支持多片 NAND 的话就可以使用此命令
来设置当前所使用的 NAND。这个需要你的 CPU 有两个 NAND 控制器,并且两个 NAND 控制
器各接一片 NAND Flash。就跟 I.MX6U 有两个 SDIO 接口,这两个 SDIO 接口可以接两个 MMC
设备一样。不过一般情况下 CPU 只有一个 NAND 接口,而且在使用中只接一片 NAND。
nand erase 命令
nand erase 命令用于擦除 NAND Flash,NAND Flash 的特性决定了在向 NAND Flash 写数据
之前一定要先对要写入的区域进行擦除。“nand erase”命令有三种形式:
nand erase[.spread] [clean] off size //从指定地址开始(off)开始,擦除指定大小(size)的区域。
nand erase.part [clean] partition //擦除指定的分区
nand erase.chip [clean] //全篇擦除nand write 命令
此命令用于向 NAND 指定地址写入指定的数据,一般和“nand erase”命令配置使用来更新
NAND 中的 uboot、linux kernel 或设备树等文件,命令格式如下:
nand write addr off size解释: addr 是要写入的数据首地址,off 是 NAND 中的目的地址,size 是要写入的数据大小。
由于 I.MX6ULL 要求 NAND 对应的 uboot 可执行文件还需要另外包含 BCB 和 DBBT,因
此直接编译出来的 uboot.imx 不能直接烧写到 NAND 里面。关于 BCB 和 DBBT 的详细介绍请
参考《I.MX6ULL 参考手册》因此我们不能在 NAND 版的 uboot 里面更新 uboot 自身
nand read 命令
此命令用于从 NAND 中的指定地址读取指定大小的数据到 DRAM 中,命令格式如下:
nand read addr off sizeaddr 是目的地址,off 是要读取的 NAND 中的数据源地址,size 是要读取的数据大小。比
如我们读取设备树(dtb)文件到 0x83000000 地址处,命令如下:
nand read 0x83000000 0x520000 0x19000
BOOT 操作命令
由于涉及到网络部分,放在网络操作指令章节里面
总结:
- U-Boot 是嵌入式 Linux 系统的第一个软件组件,它在系统上电后由硬件加载并运行。
- U-Boot 负责初始化硬件(例如,设置内存控制器、时钟、网络接口等)。
- 它加载内核映像和根文件系统到 RAM,并将控制权交给 Linux 内核。
笔者所了解的只是UBOOT的冰山一脚,对于深入UBOOT的学习应该是需要几个月的时间
U-Boot 学习路径:
- 理解 U-Boot 的架构和工作流程:学习 U-Boot 的启动过程、内存布局、命令处理等。
- 学习 U-Boot 的源代码:阅读和理解 U-Boot 的源代码,学习其内部实现。
- 配置和编译 U-Boot:学习如何配置 U-Boot,为特定的硬件平台编译 U-Boot。
- U-Boot 驱动开发:学习如何为 U-Boot 开发设备驱动。
- U-Boot 移植:学习如何将 U-Boot 移植到新的硬件平台上。