Edit online

配置分区

4 Dec 2024
Read time: 10 minute(s)

Luban-Lite 系统中,分区的设置和管理是系统正常运行和日常维护的重要方面。本章节介绍 Luban-Lite 系统中分区的特点、规则和分区修改的方法。

按照存储介质的逻辑划分,Luban-Lite 默认分区包括以下几种:
  • 启动分区:存放 BootLoader,用于系统启动。
  • 数据分区:用于存储用户数据。
  • 系统 A/B 分区:分为 A/B 系统,实现 OTA,即 Flash 上保存前后两个版本的系统程序。

启动分区

Luban-Lite 系统中,启动分区("spl" 分区)是存储介质上的第一个分区,用于存放 BootLoader,并且根据不同的存储介质类型和配置,其位置、大小和内容有所不同。

"spl" 分区为默认名称,用户可以根据需要自定义和修改启动分区名称。

Luban-Lite 系统中的默认分区设置如下:

  • SPINOR

    SPINOR Flash 的 0 ~ X 区间被设置为启动分区,主要用于存放 BootLoader,大小设置为 256K。

    尽管 BROM 加载的程序可以大于 256K,但是由于 BROM 运行时的速度较慢,不建议加载过大的程序。

  • SPINAND

    SPINAND Flash 的前四个物理块被用作启动块,启动分区内使用四个启动块保存两份启动镜像:
    • 对于块大小为 128K 的 SPINAND,启动分区为 512K。
    • 对于 块大小为 256K 的 SPINAND,启动分区为 1M。
  • eMMC

    eMMC 的启动分区位于 UDA 区域的 17K ~ X 区间,BROM 从该区域读取程序。

    建议启动镜像小于 512K。

数据分区

Luban-Lite 系统中,通过对 SPINOR/ SPINAND Flash 进行分区可以实现数据的存储和管理,为数据的读写提供了不同的功能和性能特点。

Luban-Lite 系统中,SPINOR/ SPINAND Flash 上设置了以下默认分区来保存数据。两个分区在设计和实现上有一些差异,用户需要了解并根据实际情况规划数据存储:

  • "rodata"

    目的:保存 APP 应用需要使用的资源文件,这些文件通常是应用的一部分,都是只读的数据,只是为了更好的管理和访问,使用 FAT 文件系统的方式保存。

    应用在访问这些资源文件的时候,通常要求能够快速读取数据,因此 "rodata" 分区在实现的时候,删减了多余的软件层次,通过直接访问 Flash 的方式读取数据,以达到更优的速度。这些优化,也使得 "rodata" 仅支持读取,不支持写入。

    注:
    使用 SPINOR 时,可以通过配置的方式强制使能 "rodata" 可读写,但是需要注意其中的风险:
    1. Flash 写入前需要先按块擦除,但是擦除和重新写入需要的时间比较长

    2. FATFS 没有日志,不支持异地写入,因此需要原地回写,如果擦除和回写时出现掉电,会导致文件系统损坏

  • "data"
    • 目的:提供一个可读写的文件系统分区,用于保存设备在使用过程中生成的需要写入 Flash 的数据。
    • 文件系统:
      • 在 SPINOR Flash 上,使用 LittleFS。
      • 在 SPINAND Flash 上,使用 FATFS。
      • 在 eMMC 上,每个分区都是可读写的,默认使用 FATFS。
    • 读写支持:可读写,适合存储设备运行过程中产生的临时数据或需要修改的数据。
    • 适用场景:需要频繁读写的场景,如用户设置、日志记录等。

系统 A/B 分区

Luban-Lite 系统中,A/B 系统分区是实现 Over-the-Air (OTA) 软件更新机制的一个重要部分。这种分区方式需要在 Flash 上保存前后两个版本的系统程序,并将每个版本保存在指定的分区中。

A/B 系统的分区命名比较直接,便于轻松识别两套软件版本,详细命名规则如下所示:

  • A 系统分区:直接使用其所代表的分区的名称,例如存储只读数据的 "rodata" 分区,则 A 系统分区即命名为 "rodata"。

  • B 系统分区:在对应的 A 系统分区名后加上 _r 后缀,例如 rodata_r

使用专门的 A/B 分区机制,可以最大化资源使用、实现备份,并且提前配置所需软件更新的存储空间,而不影响系统的运行性能。

分区与存储设备关系

Luban-Lite 上使用 RT-Thread 时,每个分区都对应一个或者多个系统设备。不同存储介质的对应关系如下表格所示。系统中出现但此处未列出的其他分区,同样遵循下列规则。

1. SPINOR 上的分区、设备和文件系统
分区名 MTD 设备名 块设备名 文件系统 备注
"spl" "spl" - - -
"os" "os" - - -
"rodata" "rodata" "blk_rodata" FATFS FATFS 通过 "blk_rodata" 设备访问 Flash
"data" "data" - LittleFS LittleFS 直接通过 MTD 设备访问 Flash
  • 分区名:
    • "spl":分区及其设备名,"spl" 分区主要用于存储二次引导加载程序,是系统启动的第一个阶段所加载的程序。
    • "os":"os" 分区,存放操作系统的主要部分,是系统运行的核心区域。
    • "rodata":"rodata" 分区,主要用于存储只读数据,包括系统在运行时需要读取但不修改的配置信息等。
    • "data":"data" 分区,用来存储可变数据,如用户生成的数据或系统运行时产生的临时数据。
  • MTD 设备名:对 Flash 的底层直接访问,便于进行读写硬件等操作。
  • 块设备名:通过将物理存储抽象为块设备,简化了对文件系统的操作。仅 "rodata" 分区关联了一个块设备名 "blk_rodata"。
  • 文件系统:"rodata" 分区使用 FATFS 文件系统,使得数据以文件的形式进行存储和管理。"data" 分区使用 LittleFS 文件系统。
  • 访问规则:
    • 直接访问 Flash,使用 MTD 设备

    • FATFS 访问 Flash,需要使用块设备

    • LittleFS 访问 Flash,使用 MTD 设备

2. SPINAND 上的分区、设备和文件系统
分区名字 MTD 设备名 块设备名 文件系统 备注
"spl" "spl" - - -
"os" "os" - - -
"rodata" "rodata" "blk_rodata" FATFS 通过 "blk_rodata" 设备访问 Flash,FATFS 只读
"data" "data" "blk_data" FATFS

"blk_data"设备是通过 NFTL 层创建,

FATFS 访问 "blk_data" 时,通过 NFTL 访问 Flash。

  • 分区名:
    • "spl":分区及其设备名,"spl" 分区主要用于存储 二次引导加载程序,是系统启动的第一个阶段所加载的程序。
    • "os":"os" 分区,存放操作系统的主要部分,是系统运行的核心区域。
    • "rodata":"rodata" 分区,主要用于存储只读数据,包括系统在运行时需要读取但不修改的配置信息等。
    • "data":"data" 分区,用来存储可变数据,如用户生成的数据或系统运行时产生的临时数据。
  • MTD 设备名:对 Flash 的底层直接访问,便于进行读写硬件等操作。
  • 块设备名:通过将物理存储抽象为块设备,简化了对文件系统的操作。"blk_rodata" 和 "blk_data" 分别支持对 "rodata" 和 "data" 分区的文件系统访问。
  • 文件系统:"rodata" 分区使用 FATFS 文件系统,使得数据以文件的形式进行存储和管理。"data" 分区使用 FATFS 文件系统。
  • NFTL 层:网络闪存转换层,主要用来将 Flash 的物理特性映射为一般块设备,便于 FATFS 等文件系统无需关心底层 NAND Flash 的具体特性。
    注:

    建议只设置一个使用 NFTL 的分区,并且分区不要太小。因为 NFTL 需要预留至少 6 MB 空间做坏块管理。

  • 访问规则:
    • 直接访问 Flash,使用 MTD 设备

    • FATFS 访问 Flash,需要使用块设备,通过 NFTL 层访问 Flash

3. eMMC 上的分区、设备和文件系统
分区名字 MTD 设备名 块设备名 文件系统 备注
"spl" - mmc0p0 - -
"os" - mmc0p1 - -
"rodata" - mmc0p2 FATFS 此处的分区排序仅为示例
"data" - mmc0p3 FATFS 此处的分区排序仅为示例
  • 分区名
    • "spl":分区及其设备名,"spl" 分区主要用于存储 二次引导加载程序,是系统启动的第一个阶段所加载的程序。
    • "os":"os" 分区,存放操作系统的主要部分,是系统运行的核心区域。
    • "rodata" :"rodata" 分区,主要用于存储只读数据,包括系统在运行时需要读取但不修改的配置信息等。
    • "data":"data" 分区,用来存储可变数据,如用户生成的数据或系统运行时产生的临时数据。
  • MTD 设备名:对 Flash 的底层直接访问,便于进行读写硬件等操作。
  • 块设备名:块设备按照分区顺序从 0 开始编号,例如从 mmc0p0 到 mmc0p3。每个块设备代表 eMMC 中的一个分区,简化了物理存储到逻辑存储的映射,便于后续的文件系统管理。
  • 文件系统:"rodata" 和 "data" 分区均使用 FATFS 文件系统。
  • 访问规则:块设备的命名,按照分区的排序从 0 开始编号

修改分区

image_cfg.json 文件是设置分区信息以及如何生成烧录镜像文件的配置文件,由于分区和烧录信息是相互关联的,因此在一个文件中进行配置。 image_cfg.json 文件的保存路径为 target/chip/board/pack/image_cfg.json

分区数值的书写规则如下:
  • 不带单位,表示字节

  • 可以使用单位 k 或者 K

  • 可以使用单位 m 或者 M

  • 可以使用单位 g 或者 G

输入分区 "size" 值时,需要注意存储介质的对齐要求:

  • SPINOR: 与最小擦除块大小对齐,一般为 4K 或者 64K,具体请参考 SPINOR 的数据手册。

  • SPINAND: 与最小擦除块大小对齐,一般为 128K 或者 256K,具体请参考 SPINAND 的数据手册。

  • eMMC: 需要 512 字节对齐。

分区设置步骤和流程如下所示:
  1. image_cfg.json 文件中查找对应媒介的分区配置信息。
    image_cfg.json 文件是设置分区信息以及配置烧录镜像文件生成方式的配置文件,保存路径为 target/chip/board/pack/image_cfg.json
    • chip 为对应芯片型号。
    • board 为芯片开发板型号。
    以下以 SPI NAND 的分区配置为例:
    注: 对于 SPI NAND Flash 的分区配置,需要注意 NFTL 分区的配置方法。
    "spi-nand": {
        "size": "128m", // Size of SPI NAND
        "partitions": {
            "spl":      { "size": "1m" },
            "env":      { "size": "256k" },
            "env_r":    { "size": "256k" },
            "os":       { "size": "4m" },
            "os_r":     { "size": "4m" },
            "rodata":   { "size": "12m" },
            "rodata_r": { "size": "12m" },
            "data": {
                "size": "40m",
                "nftl": { // Volume in NFTL device
                    "datavol": { "size": "-" },
                },
            },
        },
    },
  2. 根据所需分区尺寸,修改对应的分区 "size" 值,否则可跳过此步。
    例如,将 "data" 分区中的 "size" 从 40M 修改为 50M 后,示例如下:
    "spi-nand": {
        "size": "128m", // Size of SPI NAND
        "partitions": {
            "spl":      { "size": "1m" },
            "env":      { "size": "256k" },
            "env_r":    { "size": "256k" },
            "os":       { "size": "4m" },
            "os_r":     { "size": "4m" },
            "rodata":   { "size": "12m" },
            "rodata_r": { "size": "12m" },
            "data": {
                "size": "50m",
                "nftl": { // Volume in NFTL device
                    "datavol": { "size": "-" },
                },
            },
        },
    },
  3. 如需新增一个分区,在所需位置添加一行配置即可,否则可跳过此步。
    例如,新增一个 "user" 分区,示例如下:
    "spi-nand": {
        "size": "128m", // Size of SPI NAND
        "partitions": {
            "spl":      { "size": "1m" },
            "env":      { "size": "256k" },
            "env_r":    { "size": "256k" },
            "os":       { "size": "4m" },
            "os_r":     { "size": "4m" },
            "rodata":   { "size": "12m" },
            "rodata_r": { "size": "12m" },
            "user":     { "size": "20m" },      // 新添加的分区
            "data": {
                "size": "50m",
                "nftl": { // Volume in NFTL device
                    "datavol": { "size": "20m" },
                },
            },
        },
    },
  4. 如果新增的分区需要烧录预制内容,在 "target" 段中新增配置。
    注: 对于分区表中的分区,如果没有在 "target" 段中设置需要烧录的数据,则在烧录过程中,该分区不会被擦除和修改。
    "target": { // Image components which will be burn to device's partitions
        "spl": {
            "file": "bootloader.aic",
            "attr": ["required"],
            "part": ["spl"]
        },
    
        ...
    
        "mydata": {                 // 此处组件名字可自定义
            "file": "userdata.bin", // 此处为要烧录到分区的数据
            "attr": ["mtd", "optional"],
            "part": ["user"]        // 此处设置要烧录的分区名字
        },
    },
  5. 如需删除一个分区,删除对应的分区配置行即可。
    例如,删除新增的 "user" 分区,示例如下:
    "spi-nand": {
        "size": "128m", // Size of SPI NAND
        "partitions": {
            "spl":      { "size": "1m" },
            "env":      { "size": "256k" },
            "env_r":    { "size": "256k" },
            "os":       { "size": "4m" },
            "os_r":     { "size": "4m" },
            "rodata":   { "size": "12m" },
            "rodata_r": { "size": "12m" },
            "data": {
                "size": "50m",
                "nftl": { // Volume in NFTL device
                    "datavol": { "size": "20m" },
                },
            },
        },
    },
    注:

    检查 target 段中是否有使用该分区,如果有,则删除相关的配置。

分区配置示例

image_cfg.json 文件是设置分区信息以及配置烧录镜像文件生成方式的配置文件。由于分区和烧录信息是相互关联的,因此在一个文件中进行配置。 image_cfg.json 文件的保存路径为 target/chip/board/pack/image_cfg.json
  • chip 为对应芯片型号。
  • board 为芯片开发板型号。

SPINOR 的分区配置示例

"spi-nor": {
    "size": "16m", // Size of SPI NOR
    "partitions": {
        "spl":        { "size": "256k" },
        "env":        { "size": "128k" },
        "env_r":      { "size": "128k" },
        "os":         { "size": "1m" },
        "os_r":       { "size": "1m" },
        "rodata":     { "size": "3m" },
        "rodata_r":   { "size": "3m" },
        "data":       { "size": "7m" }
    },
},
SPINAND Flash 的分区配置示例
注: 对于 SPINAND Flash 的分区配置,需要注意 NFTL 分区的配置方法。
"spi-nand": {
    "size": "128m", // Size of SPI NAND
    "partitions": {
        "spl":      { "size": "1m" },
        "env":      { "size": "256k" },
        "env_r":    { "size": "256k" },
        "os":       { "size": "4m" },
        "os_r":     { "size": "4m" },
        "rodata":   { "size": "12m" },
        "rodata_r": { "size": "12m" },
        "data": {
            "size": "40m",
            "nftl": { // Volume in NFTL device
                "datavol": { "size": "-" },
            },
        },
    },
},
上述示例中, "data" 分区的配置了如下内容:
  • "size":40 MB
  • "nftl" 设备:
    • "datavol": 表示 NFTL 设备的一个卷。
    • "size":“-” 表示卷的大小是 NFTL 设备的所有剩余存储空间。

      NFTL 设备需要使用大约 6 MB 的空间做坏块管理,因此 “datavol” 的可用大小大约为 34 MB。

eMMC 的分区配置示例
注: 第一个分区的开始位置。eMMC 使用 GPT 分区表格式,需要在 eMMC 的开始和末尾都预留 17K 的空间存放 GPT 信息,因此 “spl” 的开始位置为 “0x4400”。
"mmc": {
    "size": "8G", // Size of SD/eMMC
    "partitions": {
        "spl":        { "offset": "0x4400", "size": "256k" },
        "os":         { "size": "1m" },
        "rodata":     { "size": "3m" },
        "data":       { "size": "5m" }
    },
},

每一个分区的配置项中,都有 "offset" 和 "size" 两个配置信息,其中 "offset" 用于配置该分区的开始位置。 如未设置 "offset",表示该分区紧跟上一个分区之后。