重要说明:本文的烧写目标存储器是eMMC存储器
百问网提供的烧写工具不仅可以把各镜像文件烧写到eMMC存储器,还可以烧写到NADN,SD卡等存储设备,如下图所示:
但是本文的烧写目标存储器是eMMC存储器,这点是前提,要先注意哈。
读本篇博文所需要的先行知识
关于芯片内部的ROM的作用、工作原理的介绍,链接如下:
https://blog.csdn.net/wenhao_ir/article/details/145969584
eMMC存储器详解(存储区域结构、EXT_CSD[179]、各分区介绍、主要引脚、命令格式与类型等)
https://blog.csdn.net/wenhao_ir/article/details/145967306
IMX6ULL运行Linux系统的Bootloader的三个阶段详解(BootROM、SPL、U-Boot)(SPL和U-Boot合成镜像u-boot-dtb.imx
时需要作填充数据处理)
https://blog.csdn.net/wenhao_ir/article/details/145999721
百问网(100ask)提供的烧写工具的原理和详解;将自己编译生成的u-boot镜像文件烧写到eMMC中
https://blog.csdn.net/wenhao_ir/article/details/145653414
运行于u-boot中的Fastboot(FB)协议介绍(快速烧写 eMMC、NAND、UFS 等存储设备的协议)
https://blog.csdn.net/wenhao_ir/article/details/145985144
u-boot中与eMMC/SD卡相关的功能模块“MMC sub system”的详细介绍
https://blog.csdn.net/wenhao_ir/article/details/146016551
包含SPL和U-Boot的镜像文件u-boot-dtb.imx烧写到eMMC存储器的脚本分析
所需背景知识
除了前面的目录“读本篇博文所需要的先行知识”中列出的博文,还需要知道下面两篇博文记录的知识。
关于SPL、U-Boot、u-boot-dtb.imx的详细介绍,请参看我的另一篇博文:
https://blog.csdn.net/wenhao_ir/article/details/145999721
关于如何烧写镜像文件u-boot-dtb.imx到eMMC,请参看我的另一篇博文
https://blog.csdn.net/wenhao_ir/article/details/145653414
脚本内容
脚本位置如下图所示:
“D:\Program Files\100ask_imx6ull_pro开发板系统烧写工具\scripts\basic\emmc\write_boot.clst”
脚本内容如下:
uuu_version 1.2.39
FB: ucmd setenv fastboot_dev mmc
FB: ucmd setenv emmc_dev 1
FB: ucmd setenv emmc_ack 1
FB: ucmd setenv mmcdev ${emmc_dev}
FB: ucmd mmc dev ${emmc_dev}
FB: flash bootloader ../../../files/u-boot-dtb.imx
FB: ucmd if env exists emmc_ack; then ; else setenv emmc_ack 0; fi;
FB: ucmd mmc partconf ${emmc_dev} ${emmc_ack} 1 0
FB: done
脚本内容详细分析
阅读以下代码详解的内容前请先详细我的阅读我的另两篇博文:
https://blog.csdn.net/wenhao_ir/article/details/145985144
https://blog.csdn.net/wenhao_ir/article/details/146016551
阅读了上面两篇博文后你才能知道FB: ucmd
、FB: flash
等是什么意思,你才知道u-boot和Fastboot之间的关系是怎么样的。
请务必记住 :Fastboot是u-boot的子功能,带Fastboot功能的U-boot是可以进行Fastboot状态的,从而利用Fastboot进行eMMC/SD卡设备的烧写。
这段 write_boot.clst
是百问网基于 NXP 官方烧写工具 uuu (Universal Update Utility)
编写的 eMMC 启动 U-Boot 的烧写脚本。它的作用是通过 Fastboot 协议 将 包含SPL和U-Boot的镜像文件u-boot-dtb.imx 烧写到 IMX6ULL 开发板的 eMMC 中,并配置 eMMC 以支持启动。
逐行解析脚本如下
uuu_version 1.2.39
- 指定
uuu
版本号,确保使用的是 1.2.39 及以上的uuu
工具,以避免不兼容的问题。
1. 设定 Fastboot 设备为 eMMC
FB: ucmd setenv fastboot_dev mmc
FB: ucmd setenv emmc_dev 1
FB: ucmd setenv emmc_ack 1
FB: ucmd setenv mmcdev ${emmc_dev}
FB: ucmd mmc dev ${emmc_dev}
这些命令的作用如下:
01- setenv fastboot_dev mmc
设置u-boot的环境变量fastboot_dev
的值为mmc
,这个环境变量显然是u-boot中的Fastboot来使用了。这个环境变量的意思是告诉Fastboot,我要操作的设备类型为MMC(即 eMMC 或 SD 卡)。
02- setenv emmc_dev 1
定义一个名叫emmc_dev
的环境变量,并设置其值为1。
这个环境变量是为后面的多个环境变量进行赋值而调定的,从名字来看,它与eMMC的设备编号相关。由于有它存在,在整个脚本中,如需修改eMMC的设置编号,那么改这个环境变量的值就可以了。
03-setenv emmc_ack 1
设置 emmc_ack
变量,表示 eMMC 需要 boot acknowledge(启动确认信号)。
关于这个启动确认信号的详细介绍见我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145967306
04- setenv mmcdev ${emmc_dev}
让 mmcdev
变量等于 emmc_dev
,即 mmcdev=1
。
环境变量mmcdev
告诉u-boot的Fastboot模式,要操作的目标eMMC/SD 设备的编号,从前文来看,这里实际上是把mmcdev的值设为了1。(IMX6ULL 通常 mmc 1
对应 eMMC,mmc 0
对应 SD 卡)。
可以用命令mmc list
来查看eMMC 设备的编号,我在我自己进行了移植修改操作的u-boot上运行命令mmc list
的结果如下:
mmc list
这个结果表明在当前u-boot下,eMMC存储器在SD/MMC 总线上的 SD/MMC 控制器的编号为1。
虽然通过烧写工具uuu
下载到板子内存中的u-boot并不是我移植修改的u-boot,但大概率二者对eMMC设备的编号是相同的。
所以我们可以大胆认为通过烧写工具uuu
下载到板子内存中的u-boot也把eMMC设备编号为1,所以我们需要设置供Fastboot所使用的环境变量mmcdev
的值为1。【后来的烧写事实和运行情况也证明通过烧写工具uuu
下载到板子内存中的u-boot确实把eMMC设备编号为1。】
输出结果中FSL_SDHC
的全称为:Freescale Secure Digital Host Controller
,其中:
- FSL = Freescale(飞思卡尔,现已并入 NXP)
- SDHC = Secure Digital Host Controller(安全数字主机控制器)
在 NXP i.MX 处理器(如 i.MX6、i.MX7、i.MX8)中,FSL_SDHC
负责管理 SD/MMC 总线,通常有 2~4 个 SD/MMC 控制器(编号从 0
开始)。 SD/MMC 控制器可以管理 SD 卡、eMMC 存储设备。
例如,在 i.MX6ULL 处理器上:
- FSL_SDHC0 可能连接 SD 卡
- FSL_SDHC1 可能连接 eMMC
- FSL_SDHC2 可能是额外的 SD/MMC 控制器
这些编号在 U-Boot 和 Linux 设备树中都可以看到。
05- mmc dev ${emmc_dev}
这条命令的作用是告诉u-boot将当前操作的 MMC 设备切换到编号 1 的设备,即将编号为1的 MMC 设备设置为当前活动的MMC 设备。编号为1的 MMC 设备设为活动状态后,后面Fastboot才能对它进行操作嘛。
2. 烧写 U-Boot 到 eMMC
FB: flash bootloader ../../../files/u-boot-dtb.imx
这条命令显然就是一条典型的Fastboot命令,详解如下:
flash bootloader
是uuu
工具从PC端发出的一条 Fastboot 命令:../../../files/u-boot-dtb.imx
是 U-Boot 镜像文件的路径。- 这个
u-boot-dtb.imx
是一个 带设备树(dtb) 的 U-Boot 二进制文件。 Fastboot
会将 U-Boot 烧写到 eMMC 的 Boot 分区( eMMC的boot1
或boot2
分区)。- 至于到底是烧写到哪个Boot 分区,这个的默认值是由u-boot来决定的,具体是怎么决定的、怎么样查看烧写到哪里、怎么样改变烧写位置,请参看我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145985144 【搜索“Fastboot的flash命令如何确定将镜像烧写到哪里”】
- 从后面的命令
FB: ucmd mmc partconf ${emmc_dev} ${emmc_ack} 1 0
来看,是烧写到了boot1
,而不是boot2
。其实当u-boot烧写完成后,也可以查看其EXT_CSD[179]的值来倒推是烧写到了boot1
还是boot2
。关于查看EXT_CSD[179]的值以及结果分析,可以参看我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/146016551 【搜索“运行下面的命令查看EXT_CSD[179]配置信息”】
3. 配置 eMMC 使其支持 Boot
FB: ucmd if env exists emmc_ack; then ; else setenv emmc_ack 0; fi;
FB: ucmd mmc partconf ${emmc_dev} ${emmc_ack} 1 0
-
if env exists emmc_ack; then ; else setenv emmc_ack 0; fi;
- 检查
emmc_ack
是否已定义,如果没有,就设置为0
。
- 检查
-
mmc partconf ${emmc_dev} ${emmc_ack} 1 0
-
配置 eMMC 的启动参数:
mmc partconf <dev> <boot_ack> <boot_partition> <partition_access>
具体参数:
dev = ${emmc_dev}
→ 选择编号为1的MMC设备,为什么编号为1,我在本篇博文的上面已经有说明,详情请在本博文中搜索“我们可以大胆认为通过烧写工具”。boot_ack = ${emmc_ack}
→ 设定要发送 Boot Acknowledge信号。boot_partition = 1
→ 选择 eMMC Boot 分区 1(即 boot1,而不是boot2) 作为启动分区。partition_access = 0
→ 设置eMMC进入“正常数据操作阶段”后,eMMC的活动分区为普通用户数据区(0值就是代表普通用户数据区),即从普通用户数据区进行数据的读写操作。关于这一点详细的介绍请参看我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145967306 【搜索“控制当前访问的 eMMC 分区”】
-
这条命令 告诉 IMX6ULL BootROM,U-Boot 存在于 eMMC 的
boot1
分区,并启用它作为启动分区。
-
4. 结束烧写流程
FB: done
uuu
在执行完上述命令后,通知烧写完成。
小结
这段 uuu
脚本的作用:
-
设置 eMMC 设备
- 选择 eMMC 作为 Fastboot 设备。
- 设定 eMMC 设备编号(通常是
1
)。
-
烧写 U-Boot
- 将
u-boot-dtb.imx
写入 eMMC 的 Boot 分区。
- 将
-
配置 eMMC Boot
- 设定 eMMC 的 Boot Partition 1 作为启动分区。
- 使能 eMMC Boot Acknowledge,确保 BootROM 识别它为可引导设备。
-
完成烧写
uuu
退出,设备可以尝试从 eMMC 启动。
内核镜像文件zImage的烧写脚本分析
烧写脚本的位置如下:
“D:\Program Files\100ask_imx6ull_pro开发板系统烧写工具\scripts\basic\emmc\write_kernel.clst”
脚本内容如下:
uuu_version 1.2.39
FB: ucmd setenv emmc_dev 1
FB: ucmd setenv emmc_ack 1
FB: download -f ../../../files/zImage
FB[-t 60000]: ucmd ext4write mmc ${emmc_dev}:2 ${fastboot_buffer} /boot/zImage ${fastboot_bytes}
FB: Done
脚本内容分析如下:
这个脚本是NXP的UUU(Universal Update Utility)工具的烧写脚本,主要用于在IMX6ULL等NXP处理器的嵌入式开发板上进行固件烧写。下面是对该脚本的详细分析:
1. 脚本格式
uuu_version 1.2.39
- 指定该脚本适用于
UUU
版本1.2.39
及以上。
- 指定该脚本适用于
FB:
开头的指令用于U-boot的Fastboot模式(即FB:
是Fastboot命令的前缀)。通过博文 https://blog.csdn.net/wenhao_ir/article/details/145985144 内容我们知道NXP的UUU(Universal Update Utility)工具会通过USB发送一个特制的u-boot到开发板的内存中运行,这个特制的u-boot的支持Fastboot模式。- 这个脚本的作用是将 Linux 内核 zImage 烧写到 eMMC 的 ext4 文件系统中的 /boot/zImage。
2. 命令解析
(1) FB: ucmd setenv emmc_dev 1
- 作用:在Fastboot模式下,执行 U-Boot 命令
setenv emmc_dev 1
。 - 含义:设置
emmc_dev
变量的值为1
,表示 eMMC 设备号为1
(通常mmc 1
指向 eMMC 存储设备)。关于为什么 eMMC 设备号为1
,之前已经说过了,请在本文搜索“所以我们可以大胆认为”。
(2) FB: ucmd setenv emmc_ack 1
- 作用:在Fastboot模式下,执行
setenv emmc_ack 1
。 - 含义:设置
emmc_ack
变量为1
,表示要启用eMMC的Boot Acknowledge信号。这个在博文 https://blog.csdn.net/wenhao_ir/article/details/145967306 中已经详细介绍过了。 - 其实这条语句在这个烧写内核镜像文件的脚本中是没有用的,是多余的,可以去除掉。因为从后边的分析来看其实根本没有用到它。
(3) FB: download -f ../../../files/zImage
- 作用:从主机(PC)端通过USB传输
zImage
文件到目标设备的内存中,注意:是内存中,这里还没有把镜像文件zImage烧写到eMMC中。这个脚本是先把镜像文件zImage发送到内存中,再利用u-boot的mmc命令集将镜像文件zImage写到eMMC中。这里并没有像前面烧写u-boot那样使用flash
命令。 - 参数解释:
download
:Fastboot 命令,表示下载文件到设备的RAM(内存)。-f ../../../files/zImage
:指定要下载的文件路径,即zImage
内核文件。
(4) FB[-t 60000]: ucmd ext4write mmc ${emmc_dev}:2 ${fastboot_buffer} /boot/zImage ${fastboot_bytes}
-
作用:在eMMC的当前活动分区(具体在这里为
User Area
区)的第2个逻辑分区中,将zImage
写入到位置/boot/zImage
,由于User Area
区的第2个逻辑分区的文件系统是ext4 ,所以需要用命令ext4write
,而不是fatwrite
。 -
参数解析:
ext4write mmc ${emmc_dev}:2 ...
mmc ${emmc_dev}:2
:由于前面的脚本设置了emmc_dev=1
,所以这条命令相当于mmc 1:2
,它的意思是在设备编号为1的MMC设备的当前活动分区(在前面的烧写u-boot的命令末尾已把eMMC进入数据传输模式后的活动分区设置为了User Area
区)的第2逻辑分区的目录/boot
下写入文件zImage
,当然数据是来源于RAM(内存)中。${fastboot_buffer}
:指的是Fastboot模式下下载的zImage
临时存储的 内存地址,它是由上一条命令FB: download -f ../../../files/zImage
执行时产生的。/boot/zImage
:写入的目标路径,即/boot/
目录下的zImage
。从这里来看,显然,在写入内核镜像到eMMC存储设备前,我们应该先把根文件系统写到User Area
区第2个逻辑分区中。${fastboot_bytes}
:Fastboot 的ext4write命令传输的文件大小。它是由上一条命令FB: download -f ../../../files/zImage
执行时产生的。
-
FB[-t 60000]
:-t 60000
:超时时间设置为 60000 毫秒(即 60 秒),确保写入操作不会因过短时间限制失败。
(5) FB: Done
- 作用:结束脚本执行,表示烧写完成。
3. 执行流程总结
- 设置 eMMC 设备编号(
emmc_dev=1
)。 - 从 PC 端下载
zImage
到目标设备 RAM。 - 将
zImage
写入 eMMC 的 ext4 文件系统的/boot/zImage
。 - 结束烧写过程。
4. 要引起注意的地方
从这个脚本的过程来看,在写内核镜像文件zImage之前应该要先把根文件系统写入到到User Area
区第2个逻辑分区中,否则内核镜像文件zImage是写入不成功的。
设备树文件的烧写脚本
脚本内容如下:
uuu_version 1.2.39
FB: ucmd setenv emmc_dev 1
FB: ucmd setenv emmc_ack 1
FB: download -f ../../../files/100ask_imx6ull-14x14.dtb
FB[-t 60000]: ucmd ext4write mmc ${emmc_dev}:2 ${fastboot_buffer} /boot/100ask_imx6ull-14x14.dtb ${fastboot_bytes}
FB: Done
从中可以看出,和内核镜像的烧写脚本几乎是一样的,除了文件名不一样,其它都不一样,所以这里就不再分析。
根文件系统的镜像文件的烧写脚本分析
并没有根文件系统的镜像文件的烧写脚本,根文件系统的烧写我觉得还是用Linux系统直接解压根文件系统的压缩文件到eMMC存储器的相应逻辑分区比较好,详情见 https://blog.csdn.net/wenhao_ir/article/details/146122161