---
title: 系统烧写与量产
tags: [系统烧写, SD卡, 串口, USB, 量产, MfgTool, 嵌入式Linux]
created: 2026-09-16
updated: 2026-09-17
pdf_ref: "【正点原子】I.MX6U嵌入式Linux驱动开发指南V2.0.1 - 第三十九章 系统烧写"
---
# 系统烧写与量产
> **关联知识**: [[06-系统移植与启动/01-U-Boot基础与命令]] | [[06-系统移植与启动/04-根文件系统构建]] | [[06-系统移植与启动/02-Linux内核编译]]
---
## 一、烧写方式概述
系统移植完成后,需要将 U-Boot、Linux Kernel、设备树(`.dtb`)和根文件系统(`rootfs`)四个文件烧写到板载 EMMC、NAND Flash 或 QSPI Flash 等存储设备上,使产品脱离网络独立运行。
> ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。第 39 章只讲解 **MfgTool + USB OTG** 一种烧写方式;SD 卡 dd、串口 loadb、网络烧写、uuu 等均为扩展内容。
```mermaid
flowchart LR
accTitle: Embedded Linux System Flashing Methods
accDescr: Four main methods for flashing embedded Linux systems: SD card, serial, USB OTG, and network
sd[💾 SD卡烧写] --> target[🎯 目标存储]
serial[📡 串口烧写] --> target
usb[🔌 USB烧写] --> target
net[🌐 网络烧写] --> target
classDef method fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef target fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
class sd,serial,usb,net method
class target target
```
| 烧写方式 | 接口 | 速度 | 适用场景 | 工具 |
| ------------ | ------------- | -------- | -------------------- | --------------- |
| **SD卡烧写** | SD/MMC卡槽 | ~10MB/s | 开发调试、批量生产 | `dd`、`mkfs` |
| **串口烧写** | UART (TTL) | ~115KB/s | 紧急恢复、无网络环境 | U-Boot `loadb` |
| **USB烧写** | USB OTG | ~20MB/s | 量产首选、NXP推荐 | MfgTool / `uuu` |
| **网络烧写** | Ethernet/WiFi | ~100MB/s | 大文件、远程部署 | TFTP + NFS |
> 💡 **选择建议**: 开发阶段优先用 SD卡 或 USB 烧写;量产环境首选 USB OTG(MfgTool);紧急恢复可用串口;大批量部署用网络。
---
## 二、SD卡烧写
> ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。第 39 章未讲解 SD 卡烧写;书中 U-Boot 烧写到 SD 卡使用的是`imxdownload`(见第 30 章)。
### 2.1 硬件准备
- 一张 MicroSD 卡(建议 8GB 以上 Class 10)
- 读卡器连接电脑
- 开发板支持 SD 卡启动(拨码开关设置)
### 2.2 格式化 SD 卡
在 Linux 主机上执行,将 SD 卡分为两个分区:
```bash
# 查看 SD 卡设备编号(以 /dev/sdb 为例)
lsblk
# 使用 parted 创建分区表
sudo parted /dev/sdb mklabel msdos
# 创建 FAT32 分区(存放 U-Boot、内核、设备树)
sudo parted /dev/sdb mkpart primary fat32 1MiB 128MiB
# 创建 ext4 分区(存放根文件系统)
sudo parted /dev/sdb mkpart primary ext4 128MiB 100%
# 格式化分区
sudo mkfs.vfat -F 32 /dev/sdb1
sudo mkfs.ext4 /dev/sdb2
```
### 2.3 烧写 U-Boot 到 SD 卡
U-Boot 需要写入 SD 卡的特定偏移位置(IMX6ULL 为扇区 2,即 1KB 偏移):
```bash
# 将 U-Boot 写入 SD 卡(跳过前 1KB)
sudo dd if=u-boot.imx of=/dev/sdb bs=1k seek=1 conv=fsync
# 验证写入
sudo dd if=/dev/sdb bs=1k skip=1 count=100 2>/dev/null | xxd | head -5
```
### 2.4 拷贝内核与设备树
将编译好的文件复制到 FAT32 分区:
```bash
# 挂载分区
sudo mkdir -p /mnt/sdboot
sudo mount /dev/sdb1 /mnt/sdboot
# 拷贝内核和设备树
sudo cp zImage /mnt/sdboot/
sudo cp imx6ull-alientek-emmc.dtb /mnt/sdboot/
# 卸载
sudo umount /mnt/sdboot
```
### 2.5 拷贝根文件系统
```bash
# 挂载 ext4 分区
sudo mkdir -p /mnt/sdrootfs
sudo mount /dev/sdb2 /mnt/sdrootfs
# 解压根文件系统
sudo tar -xvf rootfs.tar.bz2 -C /mnt/sdrootfs/
# 卸载
sudo umount /mnt/sdrootfs
```
### 2.6 U-Boot 启动参数设置
插入 SD 卡后,设置 U-Boot 从 SD 卡启动:
```bash
# 在 U-Boot 命令行中设置
setenv bootcmd 'mmc dev 0;fatload mmc 0:1 0x80800000 zImage;fatload mmc 0:1 0x83000000 imx6ull-alientek-emmc.dtb;bootz 0x80800000 - 0x83000000'
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk0p2 rootwait rw'
saveenv
boot
```
### 2.7 启动验证
```bash
# 串口终端观察启动日志
# 成功标志:出现 Linux version 和 login 提示
# 登录后验证
uname -a # 确认内核版本
df -h # 确认文件系统挂载
ls / # 确认根文件系统内容
```
> ⚠️ **注意**: 一旦 SD 卡启动测试通过,建议用 USB OTG(MfgTool)烧写 EMMC 进行最终部署。
---
## 三、串口烧写
> ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。第 39 章未讲解串口/Ymodem 烧写。
### 3.1 适用场景
串口烧写主要用于紧急恢复场景——当 EMMC 中无有效系统、网络不可用、USB 也无法使用时,通过 UART 串口将固件传输到板载 DDR,再由 U-Boot 写入存储。
### 3.2 工具准备
- 串口终端软件:SecureCRT、minicom 或 PuTTY
- 波特率:115200, 8N1
- 连接线:USB 转 TTL 串口线
### 3.3 U-Boot Kermit/Ymodem 烧写
在 U-Boot 命令行中使用 `loadb` 命令配合串口协议传输文件:
```bash
# 1. 设置串口波特率(U-Boot 中执行)
setenv baudrate 115200
saveenv
# 2. 使用 loadb 命令接收文件(Ymodem 协议)
loadb 0x80800000
# 3. 在终端软件中选择"发送文件" -> Ymodem 协议
# 选择 zImage 文件进行发送
# 4. 发送完成后,写入 EMMC
mmc dev 1
mmc write 0x80800000 0x800 0x3000
```
### 3.4 串口烧写完整流程
```bash
# === 阶段一:传输 U-Boot ===
loadb 0x87800000
# 通过 Ymodem 发送 u-boot.imx
mmc dev 1
mmc write 0x87800000 0x2 0x300
# === 阶段二:传输内核 ===
loadb 0x80800000
# 通过 Ymodem 发送 zImage
mmc dev 1
mmc write 0x80800000 0x800 0x3000
# === 阶段三:传输设备树 ===
loadb 0x83000000
# 通过 Ymodem 发送 imx6ull-alientek-emmc.dtb
mmc dev 1
mmc write 0x83000000 0x3800 0x200
# === 阶段四:传输根文件系统 ===
loadb 0x83800000
# 通过 Ymodem 发送 rootfs.tar.bz2
mmc dev 1
mmc write 0x83800000 0x4000 0x40000
```
### 3.5 优缺点分析
| 优点 | 缺点 |
| ------------------------------ | ------------------------------- |
| 不依赖任何外部接口(仅需串口) | 速度极慢(115200 bps ≈ 10KB/s) |
| 可恢复任何状态的板子 | 大文件传输耗时长 |
| 工具简单,几乎所有终端都支持 | 需要人工操作发送协议 |
> 💡 **实用建议**: 串口烧写仅作为最后手段。对于 IMX6ULL 的量产恢复,建议保留一个最小 U-Boot 在 EMMC 中,通过 U-Boot 的 `usb烧写` 功能恢复系统。
---
## 四、USB烧写
### 4.1 MfgTool 工具简介
MfgTool 是 NXP 官方提供的系统烧写工具,专为 I.MX 系列芯片设计,运行在 Windows 平台。工具路径通常为:
```
5、开发工具 -> 3、NXP官方原版MFG_TOOL烧写工具 -> L4.1.15_2.0.0-ga_mfg-tools.tar.gz
```
### 4.2 工具目录结构
```
mfgtools-with-rootfs/mfgtools/
├── MfgTool2.exe # 烧写主程序
├── mfgtool2-yocto-mx-evk-emmc.vbs # EMMC烧写脚本
├── mfgtool2-yocto-mx-evk-nand.vbs # NAND烧写脚本
├── cfg.ini # 配置文件
└── Profiles/Linux/OS Firmware/
├── ucl2.xml # 烧写命令脚本
├── firmware/ # 第一阶段文件(下载到DDR)
│ ├── u-boot-imx6ull14x14evk_emmc.imx
│ ├── zImage
│ └── zImage-imx6ull-14x14-evk-emmc.dtb
└── files/ # 第二阶段文件(写入EMMC)
├── u-boot-imx6ull14x14evk_emmc.imx
├── zImage
├── zImage-imx6ull-14x14-evk-emmc.dtb
└── rootfs_nogpu.tar.bz2
```
### 4.3 MfgTool 工作原理
```mermaid
flowchart TD
accTitle: MfgTool Two-Stage Flashing Process
accDescr: MfgTool uses a two-stage process: first boot Linux in DDR via USB, then flash full system to EMMC
connect["🔌 USB OTG连接"] --> bootstrap["📥 阶段一:BootStrap"]
bootstrap --> ddr["💾 下载firmware到DDR"]
ddr --> boot["🚀 DDR中启动Linux"]
boot --> flash["📦 阶段二:烧写"]
flash --> partition["🗂️ 格式化EMMC分区"]
partition --> write["✏️ 写入files目录文件"]
write --> done["✅ 烧写完成"]
classDef stage1 fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
classDef stage2 fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#713f12
classDef done fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
class bootstrap,ddr,boot stage1
class flash,partition,write stage2
class done done
```
**阶段一(BootStrap)**:将 `firmware/` 目录中的 U-Boot、zImage 和设备树通过 USB OTG 下载到 DDR,启动临时 Linux 系统。
**阶段二(Updater)**:利用 DDR 中运行的 Linux 系统,将 `files/` 目录中的完整系统(含 rootfs)烧写到 EMMC。
### 4.4 硬件连接与设置
1. **USB OTG 连接**:使用 USB 线连接开发板 `USB_OTG1` 接口到电脑
2. **拨码开关**:拨到 USB 下载模式
3. **弹出 TF 卡**:如已插入 TF 卡,先弹出,待识别后再插入
4. **按复位键**:进入 USB 模式,电脑识别出 HID 设备
> ⚠️ **V2.4 以上版本底板**:USB OTG 口已更换为 Type-C 接口。
### 4.5 自制系统的文件替换
将自己编译的文件重命名后替换 MfgTool 中的原始文件:
| 原始文件 | 重命名目标 | 所在目录 |
| --------------------------- | ----------------------------------- | ---------------- |
| `u-boot.imx` | `u-boot-imx6ull14x14evk_emmc.imx` | firmware + files |
| `zImage` | `zImage`(不改名) | firmware + files |
| `imx6ull-alientek-emmc.dtb` | `zImage-imx6ull-14x14-evk-emmc.dtb` | firmware + files |
| `rootfs.tar.bz2` | `rootfs_nogpu.tar.bz2` | files |
### 4.6 烧写步骤
```bash
# 1. 准备根文件系统(在 Ubuntu 中打包)
cd rootfs/
tar -vcjf rootfs.tar.bz2 *
# 2. 将4个文件拷贝到 Windows 的 MfgTool 目录
# firmware/ 放 3 个文件(u-boot + zImage + dtb)
# files/ 放 4 个文件(u-boot + zImage + dtb + rootfs)
# 3. 双击 mfgtool2-yocto-mx-evk-emmc.vbs
# 4. 确认界面显示"符合 HID 标准的供应商定义设备"
# 5. 点击 Start 开始烧写
# 6. 等待显示 "Done" 后点击 Stop -> Exit
# 7. 拨码开关拨回 EMMC 启动,重启开发板
```
### 4.7 网络开机自启动配置
烧写完成后,Linux 内核不会自动打开网卡。在 `/etc/init.d/rcS` 中添加:
```bash
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH runlevel
# 网络开机自启动
ifconfig eth0 up
ifconfig eth0 192.168.1.251 netmask 255.255.255.0
route add default gw 192.168.1.1
```
### 4.8 ucl2.xml 结构与识别原理
`ucl2.xml` 以``开始、``结束:`...`判断烧写哪款芯片,``针对不同存储介质(SDCard/eMMC/Nor Flash/NAND Flash…)定义烧写命令序列。
``通过 VID/PID 识别芯片(节选):
```xml
```
即 VID=0x15A2、PID=0x0080 时判定为 I.MX6ULL。
`mfgtool2-yocto-mx-evk-emmc.vbs` 内容:
```vbscript
Set wshShell = CreateObject("WScript.shell")
wshShell.run "mfgtool2.exe -c ""linux"" -l ""eMMC"" -s ""board=sabresd"" -s ""mmc=1"" -s ""6uluboot=14x14evk"" -s ""6uldtb=14x14-evk"""
Set wshShell = Nothing
```
参数含义:`board=sabresd`、`mmc=1`、`6uluboot=14x14evk`、`6uldtb=14x14-evk`;文件名`%lite%`取`l`、`%6uluboot%`取`14x14evk`(在`cfg.ini`中定义),故`firmware/u-boot-imx6ul%lite%%6uluboot%_emmc.imx`展开为`u-boot-imx6ull14x14evk_emmc.imx`。第一阶段下载完 uboot/kernel/dtb 后输出`Jumping to OS image.`并跳转启动 Linux。
### 4.9 改造 MfgTool 支持正点原子开发板
书中 39.5 节从三方面改造:
1. **确定系统文件命名**:如`u-boot-alientek-emmc.imx`、`zImage-alientek-emmc`、`imx6ull-alientek-emmc.dtb`、`rootfs-alientek-emmc.tar.bz2`。
2. **新建 .vbs**:复制`mfgtool2-yocto-mx-evk-emmc.vbs`并重命名为`mfgtool2-alientek-alpha-emmc.vbs`(内容不改)。
3. **修改 ucl2.xml**:备份原文件后只保留``,把文件路径改为上面的命名。烧写关键命令:用`dd ... of=/dev/mmcblk%mmc%boot0 bs=512 seek=2`写 U-Boot(偏移 1024 字节),`mmc bootpart enable 1 1`使能启动分区,`mkfs.vfat`建 FAT 分区放 zImage/dtb,`mkfs.ext3 -F -E nodiscard`建 rootfs 分区,`pipe tar -jxv -C /mnt/...`解压 rootfs。
改造过后,`firmware/`放 3 个文件(uboot+zImage+dtb),`files/`放 4 个文件(再加 rootfs),双击新`.vbs`即可烧写。**注意**:一旦改造后的工具能正常烧写,`firmware/`目录下的文件以后不要再改,否则可能烧写失败。
### 4.10 解决 “Starting kernel ...” 卡死
现象:烧写自研系统后 U-Boot 输出`Starting kernel ...`便无任何信息。原因是 U-Boot 默认`findfdt`取`imx6ull-14x14-evk.dtb`,而 EMMC 分区 1 中的设备树名为`imx6ull-alientek-emmc.dtb`(`mmc dev 1`+`ls mmc 1:1`可确认)。两种解决:
1. 在 U-Boot 中临时修改:
```bash
setenv bootcmd 'mmc dev 1;fatload mmc 1:1 80800000 zImage;fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv
```
2. 永久修改 U-Boot 源码`include/configs/mx6ull_alientek_emmc.h`中`CONFIG_EXTRA_ENV_SETTINGS`的`findfdt`:
```c
"findfdt="\
"if test $fdt_file = undefined; then " \
"setenv fdt_file imx6ull-alientek-emmc.dtb; " \
"fi;\0" \
```
改完重新编译 U-Boot 并烧写即可。
---
## 五、量产方案
> ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识(uuu、批量脚本、质量检查等书中未涉及)。
### 5.1 量产工具对比
| 工具 | 平台 | 速度 | 适用规模 | 特点 |
| ---------------------------------- | ------- | ---------- | -------- | ---------------------- |
| **MfgTool** | Windows | ~20MB/s | 小批量 | NXP 官方,配置灵活 |
| **uuu (Universal Update Utility)** | 跨平台 | ~20MB/s | 中批量 | NXP 新工具,命令行友好 |
| **SD卡量产** | 任意 | ~10MB/s | 中批量 | 无需电脑,可预烧写 |
| **OTA远程升级** | 云端 | 受限于带宽 | 大规模 | 远程部署,需网络 |
| **自动化脚本** | Linux | 可并行 | 大批量 | 灵活定制,可多设备并行 |
### 5.2 uuu 工具使用
uuu 是 NXP 推荐的新一代跨平台烧写工具,替代 MfgTool:
```bash
# 安装 uuu(Linux/Mac/Windows)
# Ubuntu:
sudo apt install uuu
# 编写烧写脚本 uuu.lst
SDPS: boot -f firmware/u-boot-imx6ull14x14evk_emmc.imx
FB: flash -raw2sparse all firmware/image.img
FB: done
# 执行烧写
sudo uuu uuu.lst
```
### 5.3 SD卡批量量产流程
适用于需要大量预烧写 SD 卡的生产场景:
```bash
#!/bin/bash
# sdcard_flash.sh - SD卡批量烧写脚本
SD_DEV=$1 # 如 /dev/sdb
echo "=== 格式化 SD 卡 ==="
sudo parted ${SD_DEV} mklabel msdos
sudo parted ${SD_DEV} mkpart primary fat32 1MiB 128MiB
sudo parted ${SD_DEV} mkpart primary ext4 128MiB 100%
sudo mkfs.vfat -F 32 ${SD_DEV}1
sudo mkfs.ext4 ${SD_DEV}2
echo "=== 烧写 U-Boot ==="
sudo dd if=u-boot.imx of=${SD_DEV} bs=1k seek=1 conv=fsync
echo "=== 拷贝内核与设备树 ==="
sudo mount ${SD_DEV}1 /mnt/sdboot
sudo cp zImage /mnt/sdboot/
sudo cp imx6ull-alientek-emmc.dtb /mnt/sdboot/
sudo umount /mnt/sdboot
echo "=== 拷贝根文件系统 ==="
sudo mount ${SD_DEV}2 /mnt/sdrootfs
sudo tar -xvf rootfs.tar.bz2 -C /mnt/sdrootfs/
sudo umount /mnt/sdrootfs
echo "=== 烧写完成 ==="
```
### 5.4 自动化烧写脚本(USB 多设备并行)
```bash
#!/bin/bash
# usb_mass_flash.sh - USB多设备并行烧写
IMAGE_DIR="./firmware"
FLASH_SCRIPT="./uuu.lst"
# 监控新设备接入
watch_usb_device() {
while true; do
DEVICE_COUNT=$(lsusb | grep "15a2:0080" | wc -l)
echo "检测到 ${DEVICE_COUNT} 个待烧写设备"
sleep 2
done
}
# 主流程
echo "等待设备连接..."
watch_usb_device &
# 为每个设备启动烧写进程
for dev in $(uuu_list 2>/dev/null); do
echo "烧写设备: ${dev}"
sudo uuu -d ${dev} ${FLASH_SCRIPT} &
done
wait
echo "所有设备烧写完成"
```
### 5.5 量产质量检查
```bash
# 烧写后自动化验证脚本
#!/bin/bash
# verify_flash.sh
BOARD_IP=$1
# 1. 启动检测(等待设备上线)
timeout 60 bash -c "until ping -c 1 ${BOARD_IP}; do sleep 2; done"
echo "✅ 设备启动成功"
# 2. 版本验证
VERSION=$(ssh root@${BOARD_IP} "cat /etc/version")
echo "固件版本: ${VERSION}"
# 3. 内存测试
ssh root@${BOARD_IP} "free -m"
# 4. 存储测试
ssh root@${BOARD_IP} "df -h"
# 5. 网络测试
ssh root@${BOARD_IP} "ping -c 3 8.8.8.8"
echo "✅ 验证通过"
```
---
## 六、烧写问题排查
### 6.1 MfgTool 常见错误
> ⚠️ **来源说明**:本小节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。6.2 节的“Starting kernel 卡死”与改`findfdt`属书中 39.5.3 内容。
| 错误现象 | 可能原因 | 解决方案 |
| ---------------------------- | -------------------------- | ---------------------------------------- |
| 无法识别 HID 设备 | USB 线未连接或拨码开关错误 | 检查 USB 线连接;确认拨码开关在 USB 模式 |
| "No device connected" | TF 卡未弹出 | 弹出 TF 卡后重新插拔 USB |
| 烧写过程中断 | USB 供电不足 | 使用独立供电 USB Hub 或更换 USB 口 |
| "Jumping to OS image" 后卡住 | firmware 文件错误 | 检查 firmware 目录文件是否正确替换 |
| "Done" 但无法启动 | 设备树或 U-Boot 名称不匹配 | 确认文件重命名与 ucl2.xml 一致 |
### 6.2 内核启动失败排查
**现象**: 串口输出 "Starting kernel ..." 后无任何信息。
```bash
# 在 U-Boot 命令行中检查
mmc dev 1 # 切换到 EMMC
ls mmc 1:1 # 查看分区 1 文件列表
# 确认设备树文件名是否正确
# 检查 bootcmd 中的设备树文件名
printenv bootcmd
# 确保设备树文件名与实际烧写的一致
```
**解决方案**:
```bash
# 方法一:在 U-Boot 中临时修改
setenv bootcmd 'mmc dev 1;fatload mmc 1:1 80800000 zImage;fatload mmc 1:1 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'
setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw'
saveenv
boot
# 方法二:修改 U-Boot 源码(永久方案)
# 文件:include/configs/mx6ull_alientek_emmc.h
# 修改 findfdt 环境变量,将设备树文件名改为 imx6ull-alientek-emmc.dtb
```
### 6.3 调试技巧
```bash
# 1. 查看 U-Boot 环境变量
printenv
# 2. 查看 EMMC 分区信息
mmc part
# 3. 手动读取文件验证
mmc dev 1
fatload mmc 1:1 0x80800000 zImage
# 无报错说明文件读取正常
# 4. 查看设备树内容
fdt addr 0x83000000
fdt print /
# 5. 串口日志抓取(SecureCRT)
# 启用日志记录,保存完整启动日志用于分析
```
---
## 七、跨平台对比
> ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识。
### 7.1 IMX6ULL vs STM32MP1 vs RK3568 烧写差异
| 特性 | IMX6ULL | STM32MP1 | RK3568 |
| -------------- | ------------- | ------------------- | ------------------------ |
| **官方工具** | MfgTool / uuu | STM32CubeProgrammer | RKDevTool / upgrade_tool |
| **烧写接口** | USB OTG | USB DFU / UART | USB OTG / SD 卡 |
| **启动模式** | 拨码开关 | BOOT0 引脚 | 按住 Recovery + 上电 |
| **分区格式** | 固定脚本定义 | XML 配置文件 | parameter.txt + 分区表 |
| **设备树支持** | `.dtb` 文件 | `.dtb` 文件 | `.dtb` 文件 |
| **量产推荐** | uuu 工具 | CubeProgrammer 脚本 | upgrade_tool 批量 |
| **OTA 支持** | 自行实现 | 自行实现 | A/B 分区原生支持 |
### 7.2 烧写流程对比
```mermaid
flowchart LR
accTitle: Cross-Platform Flashing Workflow Comparison
accDescr: Comparison of flashing workflows for three popular embedded Linux SoC platforms
subgraph IMX6ULL
a1[USB OTG] --> a2[MfgTool/uuu]
a2 --> a3[DDR运行临时系统]
a3 --> a4[写入EMMC]
end
subgraph STM32MP1
b1[USB DFU] --> b2[CubeProgrammer]
b2 --> b3[直接写入Flash]
end
subgraph RK3568
c1[USB OTG] --> c2[RKDevTool]
c2 --> c3[loader模式写入]
end
```
---
## 八、面试精选
> ⚠️ **来源说明**:本节不属于《I.MX6U嵌入式Linux驱动开发指南》内容,为扩展知识(答案基于书中事实整理)。
### 题目 1:嵌入式系统烧写的核心流程是什么?
**考察点**: 系统烧写原理理解
**参考答案**:
嵌入式 Linux 系统烧写通常分为两个阶段:
1. **引导阶段**:通过 USB/串口等方式将最小引导系统(U-Boot + 内核 + 设备树)下载到 DDR 中并运行,建立一个临时的 Linux 运行环境
2. **烧写阶段**:利用临时系统对目标存储(EMMC/NAND)进行分区、格式化,然后将完整系统(含 rootfs)写入存储
这种"借鸡生蛋"的设计思路使得烧写工具不需要直接操作存储芯片的底层驱动,而是利用 Linux 内核已有的文件系统和块设备驱动来完成写入操作。
### 题目 2:MfgTool 中 ucl2.xml 的作用是什么?如何自定义?
**考察点**: 工具配置能力
**参考答案**:
ucl2.xml 是 MfgTool 的核心配置文件,负责:
- **芯片识别**:通过 `` 段定义各芯片的 VID/PID,自动识别处理器型号
- **烧写命令**:通过 `` 段定义不同存储介质(EMMC/NAND/SD)的烧写命令序列
- **文件映射**:定义 firmware 和 files 目录中文件与目标芯片的对应关系
自定义时需修改三个地方:新建 `.vbs` 启动脚本、修改 `ucl2.xml` 中的烧写命令、替换 firmware/files 中的文件。关键是确保文件命名与 ucl2.xml 中的路径一致。
### 题目 3:SD 卡烧写和 USB OTG 烧写的主要区别?
**考察点**: 烧写方式选型
**参考答案**:
| 维度 | SD卡烧写 | USB OTG 烧写 |
| ------------ | --------------------- | --------------------------- |
| **原理** | 直接 `dd` 写入块设备 | 通过 USB 传输到 DDR,再烧写 |
| **速度** | ~10MB/s(取决于卡速) | ~20MB/s |
| **依赖** | 需要读卡器 + 主机 | 仅需 USB 线 |
| **量产性** | 可并行多卡 | 通常单设备烧写 |
| **灵活性** | 每次需物理插拔 | 可远程/脚本控制 |
| **恢复能力** | 可修复任何状态的板子 | 需要 ROM 中有 USB 启动代码 |
### 题目 4:量产中如何保证烧写的一致性和可靠性?
**考察点**: 量产工程能力
**参考答案**:
1. **固件版本管理**:每次烧写使用确定版本的固件包,建立版本号与 MD5 校验的映射表
2. **烧写后验证**:自动检查关键文件(U-Boot、内核、设备树)的完整性,运行基本功能测试
3. **日志记录**:记录每台设备的烧写时间、固件版本、校验结果,便于追溯
4. **A/B 分区**:对 OTA 场景,采用 A/B 分区方案,支持回滚
5. **自动化脚本**:减少人工操作,批量烧写 + 批量验证
6. **环境隔离**:烧写主机与生产网络隔离,防止固件被篡改
### 题目 5:Linux 内核启动后输出 "Starting kernel ..." 卡住,如何排查?
**考察点**: 调试能力
**参考答案**:
这种现象说明 U-Boot 已正常工作,但 Linux 内核启动失败。排查步骤:
1. **设备树检查**:在 U-Boot 中 `ls mmc 1:1` 确认设备树文件是否存在且名称正确
2. **启动参数检查**:`printenv bootargs` 确认 `console` 参数(串口号和波特率)与硬件一致
3. **内核调试输出**:在 bootargs 中添加 `earlycon` 和 `ignore_loglevel` 获取更多日志
4. **设备树调试**:在 U-Boot 中 `fdt addr` + `fdt print` 验证设备树内容
5. **DDR 检查**:确认内核加载地址和设备树地址没有重叠
```bash
# 增强调试的 bootargs 示例
setenv bootargs 'console=ttymxc0,115200 earlycon=imxuart,0x02020000,115200 ignore_loglevel root=/dev/mmcblk1p2 rootwait rw'
```
---
**内容来源**: 《I.MX6U嵌入式Linux驱动开发指南》第39章 系统烧写
**最后更新**: 2026-09-17