我的开发板是正点原子 i.MX6ULL ALPHA(eMMC 版),LCD屏幕是4.3寸的,但这并不重要,因为uuu工具适用于所有的搭载i.MX6ULL芯片的开发板,例如野火的开发板和韦东山的开发板。以前调试裸机程序或者u-boot,我要在电脑和开发板之间来回插拔三次 SD 卡;现在换成 NXP 官方的 uuu 工具,两条命令就够了。我把最近的总结与实际操作记录整理成文档,供大家参考。
欢迎关注微 信公 众号:青衫嵌入式,持续分享嵌入式知识与开发经验。
一、以前调试程序,要插拔三次 SD 卡
先说老流程。按照正点原子的教程,把 led.imx 或者 u-boot 镜像跑起来,是这样一套动作:
- 准备一张 SD 卡和读卡器;
- 读卡器插到电脑的 USB 口;
- 在虚拟机(Ubuntu)里把读卡器直通给虚拟机,用
lsblk认出/dev/sdb; - 用正点原子的
imxdownload把镜像写到 SD 卡的扇区上; sync、umount,把卡弹出;- 从读卡器里拔出 SD 卡,再插进开发板的卡槽;
- 上电(提前把拨码开关切到 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 中的落址
于是整个流程就串起来了:
- 主机侧的 uuu 解析命令行 / 脚本,通过 USB HID 把
.imx分块发给 ROM; - ROM 先执行 IVT 指向的 DCD(Device Configuration Data)——那是一串"寄存器地址 + 值"的写命令,任务是初始化时钟和 DDR 控制器;
- DDR 能用之后,ROM 按
boot_data把镜像搬到 DDR 的self处; - 最后跳到
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 玩家的原因。