用 uuu 工具替代 SD 卡烧录 i.MX6ULL 镜像,效率提升 10 倍

0 阅读6分钟

我的开发板是正点原子 i.MX6ULL ALPHA(eMMC 版),LCD屏幕是4.3寸的,但这并不重要,因为uuu工具适用于所有的搭载i.MX6ULL芯片的开发板,例如野火的开发板和韦东山的开发板。以前调试裸机程序或者u-boot,我要在电脑和开发板之间来回插拔三次 SD 卡;现在换成 NXP 官方的 uuu 工具,两条命令就够了。我把最近的总结与实际操作记录整理成文档,供大家参考。

欢迎关注微 信公 众号:青衫嵌入式,持续分享嵌入式知识与开发经验。

一、以前调试程序,要插拔三次 SD 卡

先说老流程。按照正点原子的教程,把 led.imx 或者 u-boot 镜像跑起来,是这样一套动作:

  1. 准备一张 SD 卡和读卡器;
  2. 读卡器插到电脑的 USB 口;
  3. 在虚拟机(Ubuntu)里把读卡器直通给虚拟机,用 lsblk 认出 /dev/sdb;
  4. 用正点原子的 imxdownload 把镜像写到 SD 卡的扇区上;
  5. sync、umount,把卡弹出;
  6. 从读卡器里拔出 SD 卡,再插进开发板的卡槽;
  7. 上电(提前把拨码开关切到 SD 卡启动),才能看到 LED 亮。

第 4 步的命令很关键,因为把sd设备写错的话容易出事故事故:

sudo ./imxdownload led.bin /dev/sdb

代码改一行,上面这一套就要重来一遍。中间任何一步出错都可能白忙:/dev/sdb 认错成 /dev/sda 会写坏电脑硬盘;虚拟机的 USB 直通时不时掉线;卡和卡槽接触不良,偶尔还得重新插一次。

用一句话概括这条链路:镜像要先从主机内存搬到 SD 卡这个块设备上,人再把这个块设备从主机搬到开发板——两段物理搬运,全靠手。

二、使用UUU工具,通过USB串行下载

uuu 的全称是 Universal Update Utility,来自 NXP 官方仓库 nxp-imx/mfgtools,是 mfgtools 的通用命令行版,Windows / Linux / macOS 都能跑。本文用的是 Windows 版单文件,启动横幅里带着版本号:

uuu (Universal Update Utility) for nxp imx chips -- libuuu_1.5.243-0-g230f1b1

它和 imxdownload 的根本区别是:imxdownload 面对的是 SD 卡这个块设备,uuu 面对的是芯片内部的一段固化代码。i.MX6ULL 里有一段出厂就烧死的 Boot ROM,上电后会监听 USB;uuu 要做的,只是把镜像通过 USB 递给它。没有卡、没有分区、没有文件系统,也没有"换介质"这件事。

三、使用UUU工具烧录前的两项准备工作

1)把板子拨到 USB 串行下载模式

这是与"从 SD 卡启动"并列的另一种启动方式,由板子上的拨码开关决定。i.MX6ULL 上电时会采样 BOOT_MODE 引脚:采样结果是"串行下载",Boot ROM 就去等 USB;采样结果是"内部启动",ROM 才去读 SD 卡 / eMMC 里的镜像。

在这里插入图片描述

2)把 uuu.exe 放到固定位置并加进 PATH

我是把 uuu.exe 放在 D:\MyProgram\uuu,再把 D:\MyProgram\uuu 加进 Windows 的系统环境变量 Path。之后在 WSL 里直接敲:

uuu.exe -V

能打印出上面那行版本横幅,就说明通路已经打通了。顺手可以先用 uuu.exe -h 看一眼用法,它的帮助信息里也列出了支持的芯片和对应的 USB 设备表。

四、实际操作记录一:点亮 LED

进入镜像所在目录,一条命令:

uuu.exe led.imx

uuu 会把 led.imx 通过 USB 送给 Boot ROM,ROM 初始化好 DDR 之后直接跳到镜像入口执行。命令行里看到 Success 1 Failure 0:

在这里插入图片描述

板子上的 LED 就开始亮起来了。注意,此时板子仍然停在 USB 下载模式,程序是在 DDR 里跑起来的:

在这里插入图片描述

五、实际操作记录二:把 u-boot 拉起来

同样的道理,换成 u-boot 镜像,这个u-boot的镜像来源是正点原子官方给出的出厂系统镜像,你也可以自己编译:

uuu.exe u-boot-imx6ull-14x14-ddr512-emmc.imx

在这里插入图片描述

这次"程序"是 u-boot 本身。打开串口终端(115200-8-N-1),就能看到 u-boot 的启动打印:

在这里插入图片描述

两条命令对比一下:老流程要很多个繁杂的步骤、三次插拔,改一次代码就要重来一遍;uuu 这边,板子只需要拨一次拨码(以后就不用再拨了),之后每次验证都是"改代码 → 重新敲一条命令"。效率的差距就是这么来的。

六、讲讲UUU工具的原理

要理解这件事,得先看芯片里有什么。i.MX6ULL 的 Boot ROM 是出厂固化在芯片内部的,不受我们控制、也不能被改写。它认识两件事:

  • 上电时看 BOOT_MODE 引脚,决定"去哪找镜像";
  • 如果是串行下载模式,就通过 USB 等主机把镜像送过来。

这个 USB 协议叫 SDP(Serial Download Protocol),在 i.MX6/7 上是 HID 协议。用 uuu.exe -V 看它内置的设备表,i.MX6ULL 那行写得明明白白:

SDP:  MX6ULL   0x15a2  0x0080

0x15a2:0x0080 就是板子进入下载模式后,在电脑上出现的那个 USB 设备的 VID:PID。

然后是镜像本身。.imx 不是随便一堆二进制,它开头就带着给 ROM 看的元数据。以本文这份 u-boot 镜像为例,把开头 32 字节按 IVT(Image Vector Table)解出来:

tag       = 0xD1          # IVT 头
length    = 32
entry     = 0x87800000    # ROM 最终跳转的入口
dcd       = 0x877FF42C    # DCD:tag=0xD2,长度 488 字节
boot_data = 0x877FF420    # { start = 0x877FF000, size = 0x59000 }
self      = 0x877FF400    # 镜像在 DDR 中的落址

于是整个流程就串起来了:

  1. 主机侧的 uuu 解析命令行 / 脚本,通过 USB HID 把 .imx 分块发给 ROM;
  2. ROM 先执行 IVT 指向的 DCD(Device Configuration Data)——那是一串"寄存器地址 + 值"的写命令,任务是初始化时钟和 DDR 控制器;
  3. DDR 能用之后,ROM 按 boot_data 把镜像搬到 DDR 的 self 处;
  4. 最后跳到 entry(0x87800000)执行——裸机程序开始跑,或者 u-boot 开始打印。

顺手把 led.imx 也解一遍:entry、self、DCD 的位置都和上面一模一样,只有 boot_data.size 跟着负载大小变(led.imx 是 0x76000)。也就是说,裸机测试程序和 u-boot 用的是同一套镜像格式,ROM 处理它们的方式没有任何区别。

在这里插入图片描述

全程没有块设备参与,这是它能替代 SD 卡的根本原因。但也正因为如此,这份镜像只存在于板子的 DDR 里,掉电就没了——所以它最适合调试验证阶段,而不是最终交付。

七、两种方式的对比总结

维度SD 卡老流程uuu 新流程
需要什么SD 卡 + 读卡器一根 USB 线
镜像写到哪里SD 卡扇区(块设备)由 USB 递给 Boot ROM,直接落到 DDR
是否需要插拔至少 3 次0 次
是否需要改启动模式拨一次 SD 卡启动拨一次 USB 下载模式
镜像能保留吗能(写在卡上)不能,掉电即失(只加载到内存,不改写板子)
适合场景系统集成裸机 / u-boot 调试验证

调试阶段最烦的就是"改一行代码就要把整条链路重来一遍"。把介质那条链路砍掉之后,板子拨一次拨码、插一根 USB 线,剩下的就是两条命令的事——这也是我愿意把 uuu 推荐给每一个 i.MX6ULL 玩家的原因。 在这里插入图片描述