1. 分区烧录基础:理解嵌入式设备的分区表与分区作用

做嵌入式系统这么多年,我见过太多因为分区搞砸的项目。有一次,同事在量产前最后一刻发现系统起不来——查了半天,原来是分区表写错了,boot分区被data分区覆盖了一部分。嗯,从那以后,我每次做烧录方案,第一件事就是先把分区表理清楚。

说白了,分区就是给存储芯片画格子。每个格子装不同的东西:系统内核、用户数据、缓存文件……各有各的地盘,互不干扰。今天我们就从最基础的分区表讲起。

1.1 分区表:MBR 与 GPT

分区表就是一张地图,告诉芯片“哪个区域归谁管”。目前主流的有两种:MBR 和 GPT。

对比项 MBR(主引导记录) GPT(GUID分区表)
诞生时间 1983年(DOS时代) 2000年代(UEFI时代)
最大磁盘容量 2TB 9.4ZB(实际受OS限制)
分区数量 最多4个主分区 理论上无限制(Windows限制128个)
冗余备份 无(只有一份,坏了就完蛋) 有(主分区表和备份分区表)
校验机制 无 CRC32校验
适用场景 老旧设备、小容量Flash 新平台、大容量eMMC/UFS
⚠ 我曾经踩过的坑: 有一款老平台只支持MBR,我强行用了GPT分区表,结果BootROM根本不认,板子直接变砖。后来花了半天才用JTAG救回来。所以,选分区表之前,先查清楚BootROM支持什么。

1.2 嵌入式设备常见分区类型

不管用MBR还是GPT,嵌入式设备里通常都有这几个核心分区。我按启动顺序给你捋一遍。

1.2.1 Boot分区

这是系统的“第一口奶”。芯片上电后,BootROM会从这里加载启动代码。通常包含两个部分:

  • Primary Bootloader(PBL):固化在芯片内部,不可修改
  • Secondary Bootloader(SBL):存放在Flash上,比如U-Boot、LK

我个人习惯把Boot分区单独放在最前面,并且给它加上写保护。为什么?因为一旦Boot分区坏了,整个系统就彻底废了。你想想看,连启动都做不到,还谈什么恢复?

1.2.2 System分区

这里装的是操作系统内核、驱动、核心库和系统应用。在Android设备上,它就是/system目录;在Linux嵌入式设备上,它通常是rootfs。

System分区一般是只读的(或者挂载为ro)。我建议你永远不要在生产环境里把它挂载成读写——除非你在做开发调试。我在一个项目里见过有人为了省事,把system分区设成可写,结果OTA升级时文件系统损坏,整批设备返厂。

1.2.3 Data分区

用户数据存放区。包括应用安装包、配置文件、数据库、日志等。这个分区是可读写的,也是整个系统里最容易出问题的地方。

  • 空间不足导致应用崩溃
  • 异常断电导致文件系统损坏
  • 恶意软件写入垃圾数据
💡 我的经验: Data分区一定要用支持日志的文件系统,比如ext4或f2fs。我曾经用ext2做data分区,一次意外断电后,用户数据丢了一半。从那以后,我再也不用非日志文件系统做data分区了。

1.2.4 Cache分区

缓存分区,用来存放临时数据。比如OTA升级包、系统更新缓存、应用缓存等。这个分区可以随时清空,不影响系统运行。

你可能会问:既然可以随时清空,那它重要吗?重要。因为如果Cache分区满了,OTA升级可能失败,系统更新会卡住。我建议给Cache分区预留足够空间,至少是系统固件大小的1.5倍。

1.3 分区布局实战:一个典型的嵌入式Linux设备

下面是我在一个量产项目中用过的分区布局。你可以参考一下。

分区名称 起始地址 大小 文件系统 作用
boot 0x00000000 2MB raw U-Boot引导程序
env 0x00200000 128KB raw U-Boot环境变量
boot_a 0x00400000 16MB ext4 内核+dtb(A槽)
boot_b 0x01400000 16MB ext4 内核+dtb(B槽,备份)
system_a 0x02400000 256MB ext4 系统镜像(A槽)
system_b 0x12400000 256MB ext4 系统镜像(B槽,备份)
data 0x22400000 剩余空间 f2fs 用户数据
cache 0x80000000 64MB ext4 缓存
🔑 关键点: 注意我用了A/B分区方案。boot和system各有两个副本。这样OTA升级时,先升级B槽,如果失败还能回滚到A槽。这个方案救过我的命——有一次升级包有bug,整批设备靠A槽回滚保住了。

1.4 分区表操作:查看与备份

在实际工作中,你经常需要查看设备的分区表。下面是我常用的几个命令。

查看分区表

# 查看eMMC分区表(Linux环境下)
cat /proc/partitions

# 使用fdisk查看
fdisk -l /dev/mmcblk0

# 使用gdisk查看GPT分区表
gdisk -l /dev/mmcblk0

# 查看分区挂载情况
mount | grep mmcblk0

备份分区表

我建议你在量产前,先把分区表完整备份一份。万一哪天分区表损坏,这就是救命稻草。

# 备份MBR(前512字节)
dd if=/dev/mmcblk0 of=mbr_backup.bin bs=512 count=1

# 备份GPT(前34个LBA)
dd if=/dev/mmcblk0 of=gpt_primary.bin bs=512 count=34

# 备份GPT备份分区表(最后33个LBA)
dd if=/dev/mmcblk0 of=gpt_backup.bin bs=512 skip=$(($(blockdev --getsz /dev/mmcblk0) - 33)) count=33
⚠ 注意: 备份分区表时,一定要确保设备没有正在读写操作。我曾经在系统运行时备份GPT,结果读到一半数据变了,备份文件是坏的。后来我都是先进入恢复模式再备份。

1.5 分区烧录的核心流程

理解了分区表和分区类型,烧录就简单了。核心流程就三步:

  1. 擦除分区:把目标分区清空,避免旧数据干扰
  2. 写入镜像:把固件镜像写到指定分区
  3. 校验数据:读回来比对,确保写入正确

我习惯在烧录脚本里加上CRC校验。虽然会多花几秒钟,但能避免99%的烧录失败问题。有一次量产时,烧录器接触不良,数据写了一半就断了。如果没有校验,这批设备出厂后全都会变砖。

💡 小技巧: 烧录完成后,用dd命令把分区内容读出来,和原始镜像做md5sum比对。这是最笨但最可靠的方法。

1.6 本章知识结构图

下面这张图帮你梳理了本章的核心知识点。你可以把它当作一个快速索引。

分区烧录基础 - 知识结构图 分区烧录基础 - 知识结构图 分区表 MBR GPT MBR特性 • 最大2TB • 最多4个主分区 • 无冗余备份 GPT特性 • 支持大容量 • 分区数量无限制 • 有备份+CRC校验 分区类型 Boot分区 System分区 Data分区 Cache分区 Boot分区 • 存放引导程序 • 建议写保护 • 损坏=变砖 System分区 • 系统内核+应用 • 建议只读挂载 • OTA升级目标 Data分区 • 用户数据 • 可读写 • 需日志文件系统 Cache分区 • 临时缓存 • 可随时清空 • 影响OTA升级 烧录流程:擦除 → 写入 → 校验

这张图把分区表、分区类型和烧录流程串在了一起。你可以把它当作一个快速参考。在实际项目中,我经常把这张图打印出来贴在工位上——每次做分区方案时看一眼,能避免很多低级错误。