这篇文章的内容,是学习“按工业标准思路,做 eMMC 分区设计”

目的是:学习工业嵌入式 Linux 存储架构的方案。

本文采用的手动 fdisk 分区 ,适合学习。工业量产:必须自动化 + 固化镜像。

下一篇博客内容,实现了 sfdisk 脚本,一键 分区、格式化。

存储架构:

设计项

工业意义

行业应用

A/B 系统

支持 OTA 升级、无缝切换、失败回滚

手机 / IoT / 车载 / 工控

Recovery 独立分区

系统修复、刷机、救援模式,不依赖主系统

工控 / 车载 / 手机

Data 分离

用户数据与系统隔离,系统升级不影响数据

手机 / 工业设备 / 嵌入式系统

Bootloader / env 独立分区

启动链与系统隔离,保证启动可靠性

所有嵌入式 Linux 设备

Env 独立分区

U-Boot 环境变量持久化存储,防止文件系统损坏影响启动

工业控制器 / 路由器 / SoC设备

预留空间(p9 / tail / OP)

用于对齐、坏块替换、未来扩展或 eMMC 内部磨损均衡

高可靠工业设备 / 长生命周期产品

OTA : Over-The-Air    远程无线升级。

下图是 开发板 emmc 分区计划:

分区

大小

起始扇区

结束扇区

文件系统

工业用途说明

p1

4MB

2048

10239

raw / nofs

U-Boot 备份

p2

1MB

10240

12287

raw / env

U-Boot 环境变量存储区

p3

64MB

12288

143359

FAT32

Boot A 分区(kernelA + dtbA )

p4

64MB

143360

274431

FAT32

Boot B 分区(kernelB + dtbB )

p5

2GB

274432

4468735

ext4

rootfs A

p6

2GB

4468736

8663039

ext4

rootfs B / OTA备份

p7

~3.4GB

8663040

14901247

ext4

Data(用户数据 / 应用数据 / 日志 / OTA缓存 + 预留空间)

p8

128MB

14901248

15114239

ext4

Recovery / Rescue System(出厂前烧录最小救援系统 / 刷机环境)

下图是 每个分区的类型:

83 = Linux 原生分区 (对应 ext4 / ext3 / ext2 等)

c = W95 FAT32 (LBA) (对应 FAT32 文件系统)

A/B 独立分区: bootA,bootB ,rootfs A ,rootfs B,每个都是独立文件系统。

p8 分区的后面,还剩约 76MB 空间,没分完,留作 eMMC 磨损均衡备用。

数据分离的逻辑,设置各个分区的读写权限和用户的权限:

1. 系统分区(rootfsA、rootfsB):日常运行全程设为只读(ro),仅在OTA升级更新系统镜像时,临时重新挂载为可读写,升级结束立刻切回只读,避免人为误改、恶意篡改导致系统损坏;

2. 启动分区(放内核、设备树、U-Boot环境变量的分区):保持只读属性,防止启动关键文件被误删,保障开机稳定性;

3. Data 用户分区:全程保持可读可写,用户所有自建文件、业务数据、自定义程序、动态日志都只能存放在这里。

4. 限制普通用户的权限。

 关于分区表:

 imx6ull开发板的 U-Boot 版本是 2016.03 ,配置里没有 GPT 支持,分区表 支持 MBR ,属于2016年前后的技术栈。

MBR: 简单,兼容性好,但脆弱,4 主分区限制。

GPT:  健壮,冗余备份,但 i.MX6ULL ROM 不支持。

GPT 标准支持 128 个分区。

MBR 格式限制:最多只能有 4 个主分区,超过必须用扩展分区。

方案A:p4 扩展分区 + 逻辑分区(p5~p9),独立块设备,隔离性好。

方案B:单分区 + 多个子目录替代 p5~p9,隔离级别降低。

方案C:升级 U-Boot 至 2022+,用户区切 GPT,直接分 8 个独立分区。(ROM 仍需 boot0 启动 U-Boot,

imx6ULL 的 Boot ROM 不支持 GPT,但 U-Boot 本身和 Linux 内核均支持 GPT)。

升级 U-Boot 是独立工程,脱离正点原子/NXP 的 BSP 支持后,DDR 时序、设备树、板级文件全部需要自己重写适配。

解决方案:选择方案A,p1~p3 占 3 个主分区槽位,p4 改成扩展分区(里面装的是逻辑分区的链表),承载 p5~p9。学习开发阶段可用,先用 U-Boot 2016.03 把系统全部跑通。

现在开始实操:

第一步,添加格式化工具

因为是 sd卡启动,要确保 运行的linux 系统,有格式化工具。

进入 Buildroot 的配置界面, 添加格式化工具,到根文件系统里。

如果不做OTA 远程升级,可以不安装后面的  OTA 工具

1.  dosfstools(提供 mkfs.vfat)

Target packages  →  Filesystem and flash utilities  →  [*] dosfstools ,    [*]  mkfs.vfat

2.  e2fsprogs(提供 mkfs.ext4/ext3/ext2)

Target packages  →   Filesystem and flash utilities  →   [*] e2fsprogs

 ( 不需要 额外勾选子选项 )

3. mmc-utils ( mmc 工具 )

Target packages  →     Filesystem and flash utilities  ->  Filesystem and flash utilities  ->   mmc-utils

4.  sfdisk (自动化 分区脚本需要的工具 )

Target packages  →    System tools  ->  util-linux   ->  basic set

如果编译后,显示没有sfdisk分区工具,buildroot 根目录 执行 make util-linux-dirclean ,再重新编译。

5. fw_printenv ( OTA 逻辑的核心工具 )

可以在 Linux 下安全读写 U-Boot 环境变量。

A/B 系统的核心是无缝切换和防变砖,完全依赖 fw_setenv

Target packages  →     Filesystem and flash utilities  ->  Hardware handling   ->  fw_printenv

6 .  wipefs 和 losetup ( OTA 需要的工具,后面做的OTA升级,实际没用到这2个工具,可以不安装

 Target packages  →     System tools   ->   util-linux   ->

重新编译 Buildroot ,解压,  我是nfs挂载的根文件系统。

第二步,emmc 擦掉旧分区表

 sd卡启动, 运行linux 系统

cd /dev/

 ls mmc*

 fdisk -l mmcblk1

没有分区表,可以直接开始分区

如果有分区表,擦掉旧分区表:

执行命令: dd if=zero of=mmcblk1 bs=512 count=1

命令解释:把 eMMC 的第 0 扇区(前 512 字节)全部写零。

这 512 字节里存的是:

MBR 分区表(446 字节的引导代码 + 64 字节的 4 个主分区条目)

磁盘签名(2 字节 0x55AA)

擦掉后 eMMC 就变回"没有分区表"的状态,相当于一张白纸,可以重新分区。

第三步,开始分区:

1.执行分区命令: fdisk mmcblk1

按顺序敲,示例: n 回车, p回车

(如果参数输入错了,q 退出 ,重新分区):

 下面是 p4 ( 扩展分区 ) 的示例图:

从扇区 143360 到 默认扇区 15269887 ,也就是从 0.068G 到 7.28G 之间

2.创建逻辑分区: 按顺序继续敲

Command: n

First sector: 直接回车

Last sector: +64M

Command: n

First sector : 直接回车

Last sector: +2G

Command: n

First sector: 直接回车

Last sector: +2G

Command: n

First sector : 直接回车

Last sector: +3G

Command: n

First sector: 直接回车

Last sector: 回车(吃满剩余)

3.  1、3、5分区 设置为 FAT32 类型: 按顺序继续敲

检查并写入,输入 p 和 w:

Command: p          ← 先看一眼对不对

Command: w          ← 确认无误再写

基本上全分完了,末尾没有多余空间。p9 实际 154M 左右,和前面预估略有偏差,但完全没问题。

验证:

fdisk -l mmcblk1

第四步,格式化:

格式化 p3、p5、p6、p7、p8、p9。不格式化 p1、p2、p4 。

mkfs.fat /dev/mmcblk1p3

mkfs.fat /dev/mmcblk1p5

mkfs.ext4 /dev/mmcblk1p6

mkfs.ext4 /dev/mmcblk1p7

mkfs.ext4 /dev/mmcblk1p8

mkfs.ext4 /dev/mmcblk1p9

全部格式化完后,验证:

fdisk -l mmcblk1

挂载测试(测试完后,卸载所有挂载点):

挂载测试是为了验证文件系统没有损坏,能正常读写。

mkdir -p /mnt/bootA /mnt/bootB /mnt/rootA /mnt/rootB /mnt/data /mnt/recovery

mount /dev/mmcblk1p3 /mnt/bootA

mount /dev/mmcblk1p5 /mnt/bootB

mount /dev/mmcblk1p6 /mnt/rootA

mount /dev/mmcblk1p7 /mnt/rootB

mount /dev/mmcblk1p8 /mnt/data

mount /dev/mmcblk1p9 /mnt/recovery

df -h

 emmc 烧系统时,参考上面这个表格。

卸载所有挂载点:

umount /mnt/bootA

umount /mnt/bootB

umount /mnt/rootA

umount /mnt/rootB

umount /mnt/data

umount /mnt/recovery

验证已卸载,确认不再有 /mnt/bootA 等条目。

df -h

清理挂载点目录(可选)

rmdir /mnt/bootA /mnt/bootB /mnt/rootA /mnt/rootB /mnt/data /mnt/recovery

第五步,烧系统:

eMMC 分区工作全部完成,可以开始烧系统了。

我是nfs挂载的根文件系统 ,通过 NFS 传到板子上烧录。

1.  在 Ubuntu 主机上,把 u-boot.imx  内核、设备树、根文件系统压缩包 拷贝到 NFS 上自己创建的目录里

2.  在板子上,烧录 U-Boot 到 eMMC boot0 区

解除 boot0 写保护

echo 0 > /sys/block/mmcblk1boot0/force_ro

烧录 U-Boot

dd if=u-boot.imx of=/dev/mmcblk1boot0 bs=512 seek=2

 恢复  boot0 写保护

echo 1 > /sys/block/mmcblk1boot0/force_ro 

3.   设置 eMMC 从 boot0 启动

mmc bootpart enable 1 1 /dev/mmcblk1

然后验证

mmc extcsd read /dev/mmcblk1 | grep PARTITION_CONFIG

显示 PARTITION_CONFIG: 0x48 就对了

4. 拷贝内核和 dtb 到 bootA(分区3)

mount /dev/mmcblk1p3 /mnt

cp zImage /mnt/

cp imx6ull-alientek-emmc.dtb /mnt/

然后验证

ls /mnt

umount /mnt

5. 解压根文件系统到 rootfs A(分区6)

mount /dev/mmcblk1p6 /mnt

tar -xaf rootfs.tar -C /mnt

然后验证

ls /mnt

umount /mnt

第五步,开机测试:

开发板的拨码开关,选择 emmc 启动,开机

U-Boot 从 eMMC 成功启动了

在 u-boot 命令行,查看分区信息

分区表 正确,U-Boot 能识别所有 9 个分区,p4 是扩展分区

查看 p3(bootA)里的文件

fatls mmc 1:3

如果有 zImage 和 dtb,直接启动

setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p6 rootwait'

fatload mmc 1:3 0x80800000 zImage

fatload mmc 1:3 0x83000000 imx6ull-alientek-emmc.dtb

bootz 0x80800000 - 0x83000000

登录账号后,验证系统:

df -h

cat /proc/partitions | grep mmcblk1

完美,全部正确。

现在做两件事收尾:

1.   固化 U-Boot 环境变量:

重启开发板,设置环境变量,

设置:从分区3 (bootA)  加载内核 设备树

setenv bootcmd 'fatload mmc 1:3 0x80800000 zImage; fatload mmc 1:3 0x83000000 imx6ull-alientek-emmc.dtb; bootz 0x80800000 - 0x83000000'

设置:开机使用分区6 (rootfs A) 的根文件系统

 setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk1p6 rootwait'

 保存环境变量   saveenv

 启动内核   boot

2. 把 bootA(分区3) 里的内核、设备树 拷贝到 bootB(分区5),目的是先备份,升级时再替换。

先挂 bootA,再挂 bootB,把文件拷过去:

mkdir -p /mnt/bootA /mnt/bootB

mount /dev/mmcblk1p3 /mnt/bootA

mount /dev/mmcblk1p5 /mnt/bootB

cp /mnt/bootA/* /mnt/bootB/

ls /mnt/bootB

umount /mnt/bootA

umount /mnt/bootB

现在 p8 (数据分区) 是空的,没挂载,所以看不到。

查看当前挂载    df -h

手动挂载数据区

mkdir -p /data

mount /dev/mmcblk1p8 /data

df -h

取消挂载  umount /data

如果想开机自动挂载

mkdir -p /data

mount /dev/mmcblk1p8 /data

echo "/dev/mmcblk1p8 /data ext4 defaults 0 0" >> /etc/fstab

cat /etc/fstab

设置 开机自动挂载 后,重启开发板:

进入 data 目录

目录

用途

/data

数据区,随便读写

/data/lost+found

ext4 文件系统修复后找回的损坏文件碎片,不要手动动它

以后,你的的应用数据、日志、用户文件全部放 /data 目录下,不是 /data/lost+found

lost+found 是每个 ext4 分区格式化后自动生成的系统目录,正常使用不用管。

 home 目录 和 data 目录 的 区别:

目录

位置

用途

/home

p6(rootfs A)

根文件系统,系统的一部分,升级会被覆盖

/data

p8(data)

独立分区,升级不丢

当前状态总结:

分区

内容

状态

p1 bootloader

4M 预留

p2 env

U-Boot 环境变量备份

空的,需要重新编译 U-Boot,指定 env 存 p2

p3 bootA

zImage + dtb

已就绪

p4 扩展

 

p5 bootB

zImage + dtb

内核、设备树的备份,已就绪

p6 rootfs A

rootfs

已挂载运行

p7 rootfs B

待 OTA 时写入(远程升级)

p8 data

已挂载,应用层使用

p9 recovery

待装救援系统

p1 和 p2 分区是空的,暂时没用上。

boot1 分区 其实也可以做U-Boot备份,boot0 + boot1 双备份数据,可以覆盖 U-Boot 冗余需求,p1 分区就显得有点多余了。把p1这个主分区槽位 腾出来给 rootA 或 recovery,重新分区,比留着 p1 空着 更好。暂时先这样,先跑通了再说,当作学习了解,有时间再改。

p9 recovery 分区:出厂前 预装最小救援系统,A/B 双系统如果都挂了,最后用它救援。

p9 Recovery 分区内容清单:见下图

关于升级:

正常启动 → rootfs A 根文件系统

OTA 升级 → 新系统写到 rootfs B → 切换启动 → rootfs B

下次升级 → 新系统写到 rootfs A → 切换启动 → rootfs A

工业级 OTA 的标准实现方式:

1. 设备正常运行在 A 槽

2. 服务器推送新版本

3. 下载新内核到 p5,新 rootfs 到 p7

4. U-Boot 切启动到 B 槽

5. 重启 → 运行新版本

6. 如果新版本连续启动失败 → U-Boot 自动切回 A

到这里, emmc 的分区,烧系统,测试,结束了。

分区、烧系统  :也可以用 sfdisk 分区工具 做成自动化脚本,取代手动输入。

eMMC 分区设计,也可以根据自己的需要,做优化。

------------------------------------------------------------------------------------------------------------------

 MFG Tool 烧录配置文件:

 imx6ull 学习资料里的这个 xml 文件,是 NXP 官方的 MFG Tool(Manufacturing Tool)烧录配置文件。

两种烧录模式:

模式

说明

"Install"

擦除介质 + 烧录完整固件(新板首次烧录)

"Update"

只更新固件,不擦除用户数据(OTA 场景)

xml 文档 和 本文,做对比:

步骤

NXP 官方

本文的做法

烧录工具

MFG Tool(USB OTG + 临时 Linux)

从 SD 卡/NFS 启动 Linux,手动 dd/tar

分区

调用 mksdcard.sh 脚本

手动 fdisk,一步步敲

U-Boot 位置

eMMC boot0,seek=2

相同

启动设置

mmc bootpart enable 1 1

相同

内核/dtb

放 p1(FAT32)

放 p3 bootA、p5 bootB

rootfs

放 p2(ext3)

放 p6  rootfs A , p7  rootfs B ,升级时切换根文件系统

分区方案

简单 2 分区(p1 boot, p2 rootfs)

9 分区 A/B 工业方案

关键点

  • NXP 的分区方案非常简单(2 个分区),没有 A/B、没有 recovery、没有 data 隔离
  • 烧录流程依赖 USB OTG 进入 BootStrap 模式,不需要 SD 卡
  • Android/Brillo 的方案里才有 A/B 分区(boot_a/boot_b、system_a/system_b)

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐