title: 系统烧写与量产 tags: [系统烧写, SD卡, 串口, USB, 量产, MfgTool, 嵌入式Linux] created: 2026-09-16 updated: 2026-09-17
关联知识: [[06-系统移植与启动/01-U-Boot基础与命令]] | [[06-系统移植与启动/04-根文件系统构建]] | [[06-系统移植与启动/02-Linux内核编译]]
系统移植完成后,需要将 U-Boot、Linux Kernel、设备树(.dtb)和根文件系统(rootfs)四个文件烧写到板载 EMMC、NAND Flash 或 QSPI Flash 等存储设备上,使产品脱离网络独立运行。
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);紧急恢复可用串口;大批量部署用网络。
在 Linux 主机上执行,将 SD 卡分为两个分区:
# 查看 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
U-Boot 需要写入 SD 卡的特定偏移位置(IMX6ULL 为扇区 2,即 1KB 偏移):
# 将 U-Boot 写入 SD 卡(跳过前 1KB)
sudo dd if=u-boot.imx of=/dev/sdb bs=1k seek=2 conv=fsync
# 验证写入
sudo dd if=/dev/sdb bs=1k skip=2 count=100 2>/dev/null | xxd | head -5
将编译好的文件复制到 FAT32 分区:
# 挂载分区
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
# 挂载 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
插入 SD 卡后,设置 U-Boot 从 SD 卡启动:
# 在 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
# 串口终端观察启动日志
# 成功标志:出现 Linux version 和 login 提示
# 登录后验证
uname -a # 确认内核版本
df -h # 确认文件系统挂载
ls / # 确认根文件系统内容
⚠️ 注意: 一旦 SD 卡启动测试通过,建议用 USB OTG(MfgTool)烧写 EMMC 进行最终部署。
串口烧写主要用于紧急恢复场景——当 EMMC 中无有效系统、网络不可用、USB 也无法使用时,通过 UART 串口将固件传输到板载 DDR,再由 U-Boot 写入存储。
在 U-Boot 命令行中使用 loadb 命令配合串口协议传输文件:
# 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
# === 阶段一:传输 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
| 优点 | 缺点 |
|---|---|
| 不依赖任何外部接口(仅需串口) | 速度极慢(115200 bps ≈ 10KB/s) |
| 可恢复任何状态的板子 | 大文件传输耗时长 |
| 工具简单,几乎所有终端都支持 | 需要人工操作发送协议 |
💡 实用建议: 串口烧写仅作为最后手段。对于 IMX6ULL 的量产恢复,建议保留一个最小 U-Boot 在 EMMC 中,通过 U-Boot 的
usb烧写功能恢复系统。
MfgTool 是 NXP 官方提供的系统烧写工具,专为 I.MX 系列芯片设计,运行在 Windows 平台。工具路径通常为:
5、开发工具 -> 3、NXP官方原版MFG_TOOL烧写工具 -> L4.1.15_2.0.0-ga_mfg-tools.tar.gz
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
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。
USB_OTG1 接口到电脑⚠️ V2.4 以上版本底板:USB OTG 口已更换为 Type-C 接口。
将自己编译的文件重命名后替换 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 |
# 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 启动,重启开发板
烧写完成后,Linux 内核不会自动打开网卡。在 /etc/init.d/rcS 中添加:
#!/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
| 工具 | 平台 | 速度 | 适用规模 | 特点 |
|---|---|---|---|---|
| MfgTool | Windows | ~20MB/s | 小批量 | NXP 官方,配置灵活 |
| uuu (Universal Update Utility) | 跨平台 | ~20MB/s | 中批量 | NXP 新工具,命令行友好 |
| SD卡量产 | 任意 | ~10MB/s | 中批量 | 无需电脑,可预烧写 |
| OTA远程升级 | 云端 | 受限于带宽 | 大规模 | 远程部署,需网络 |
| 自动化脚本 | Linux | 可并行 | 大批量 | 灵活定制,可多设备并行 |
uuu 是 NXP 推荐的新一代跨平台烧写工具,替代 MfgTool:
# 安装 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
适用于需要大量预烧写 SD 卡的生产场景:
#!/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=2 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 "=== 烧写完成 ==="
#!/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 "所有设备烧写完成"
# 烧写后自动化验证脚本
#!/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 "✅ 验证通过"
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 无法识别 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 一致 |
现象: 串口输出 "Starting kernel ..." 后无任何信息。
# 在 U-Boot 命令行中检查
mmc dev 1 # 切换到 EMMC
ls mmc 1:1 # 查看分区 1 文件列表
# 确认设备树文件名是否正确
# 检查 bootcmd 中的设备树文件名
printenv bootcmd
# 确保设备树文件名与实际烧写的一致
解决方案:
# 方法一:在 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
# 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)
# 启用日志记录,保存完整启动日志用于分析
| 特性 | 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 分区原生支持 |
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
考察点: 系统烧写原理理解
参考答案:
嵌入式 Linux 系统烧写通常分为两个阶段:
这种"借鸡生蛋"的设计思路使得烧写工具不需要直接操作存储芯片的底层驱动,而是利用 Linux 内核已有的文件系统和块设备驱动来完成写入操作。
考察点: 工具配置能力
参考答案:
ucl2.xml 是 MfgTool 的核心配置文件,负责:
<CFG> 段定义各芯片的 VID/PID,自动识别处理器型号<LIST> 段定义不同存储介质(EMMC/NAND/SD)的烧写命令序列自定义时需修改三个地方:新建 .vbs 启动脚本、修改 ucl2.xml 中的烧写命令、替换 firmware/files 中的文件。关键是确保文件命名与 ucl2.xml 中的路径一致。
考察点: 烧写方式选型
参考答案:
| 维度 | SD卡烧写 | USB OTG 烧写 |
|---|---|---|
| 原理 | 直接 dd 写入块设备 |
通过 USB 传输到 DDR,再烧写 |
| 速度 | ~10MB/s(取决于卡速) | ~20MB/s |
| 依赖 | 需要读卡器 + 主机 | 仅需 USB 线 |
| 量产性 | 可并行多卡 | 通常单设备烧写 |
| 灵活性 | 每次需物理插拔 | 可远程/脚本控制 |
| 恢复能力 | 可修复任何状态的板子 | 需要 ROM 中有 USB 启动代码 |
考察点: 量产工程能力
参考答案:
考察点: 调试能力
参考答案:
这种现象说明 U-Boot 已正常工作,但 Linux 内核启动失败。排查步骤:
ls mmc 1:1 确认设备树文件是否存在且名称正确printenv bootargs 确认 console 参数(串口号和波特率)与硬件一致earlycon 和 ignore_loglevel 获取更多日志fdt addr + fdt print 验证设备树内容DDR 检查:确认内核加载地址和设备树地址没有重叠
# 增强调试的 bootargs 示例
setenv bootargs 'console=ttymxc0,115200 earlycon=imxuart,0x02020000,115200 ignore_loglevel root=/dev/mmcblk1p2 rootwait rw'
最后更新: 2026-09-17