全部产品

HaaS100文件系统方案介绍

更新时间:2020-09-19 22:38:58

概述

随着智能设备和物联网场景的发展,嵌入式系统中也越来越多地使用到文件系统,如穿戴类设备对传感数据的存储、智能语音设备对图片和语音文件的存储、物联网网关设备对子设备信息的存储等。

AliOS Things自发布至今,已发展到现在的3.x版本,功能日臻完善。其中的文件系统方案,也已经在多个量产项目中规模化使用,功能和特性日渐丰富和成熟。

下图是AliOS Things文件系统的功能特性概要。

image.png

架构介绍

AliOS Things中,文件系统层次架构从上到下依次为:应用层、C库层、文件系统层、设备访问层、硬件层。

  • 应用层

    :用户应用。

  • C库

    :libc实现,提供POSIX标准接口服务。

  • VFS

    :虚拟文件系统(Virtual File System),可以集成不同的底层文件系统模块。VFS层屏蔽底层文件系统的细节,提供统一的VFS接口服务。

  • 文件系统

    :AliOS Things中提供了littlefs、fatfs、ramfs等文件系统功能。

  • 设备访问层

    :抽象块设备访问逻辑,其中NFTL主要用于NAND Flash设备访问。

  • 硬件层

    :支持的存储介质包括Nor Flash、NAND Flash、SD卡、eMMC、USB等。

截屏2020-09-15 14.24.34.png

文件系统方案

AliOS Things提供了littlefs、fatfs、ramfs等文件系统模块。其中,littlefs主要用于裸Flash存储介质,fatfs主要用于SD卡、eMMC、USB等存储介质,ramfs用于内存文件系统。

上述文件系统模块,通过VFS层提供统一的文件系统服务能力。不同类型的文件系统,挂载在不同的位置。其中,ramfs默认挂载路径为/RAMFS,littlefs默认挂载点为/data和/system分区,sd卡fatfs默认挂载在/sdcard分区,usb fatfs默认挂载在/usb分区。用户页可以根据需要,修改使用其他挂载路径。

内存文件系统

提供临时文件存储功能,所有的文件系统信息存储在内存中。系统掉电后,所有文件信息丢失;系统重启后,内存文件系统分区重新初始化和挂载。

内存文件系统挂载路径点为/RAMFS,可以通过/RAMFS/<dir>/<file>路径访问内存文件系统中的文件和目录。具体的使用方法,请参考示例application/example/vfs_demo

FatFS文件系统

FatFs是一种通用的文件系统,在嵌入式系统中实现FAT文件系统。

AliOS Things中也集成了FatFs文件系统,主要用于SD卡、eMMC、USB等存储介质上。其中,使用SD、eMMC的FatFs文件系统默认挂载路径为/sdcard,使用USB介质的Fatfs文件系统默认挂载在/usb路径下。

关于在AliOS Things中,如何使用FatFs存储和访问文件,请参考示例:application/example/shenmu_lite_vrf/sd_test.c

littlefs文件系统

为了更好地支持裸Flash场景,AliOS Things集成优化了littlefs文件系统模块。littlefs是一种高度完整的嵌入式文件系统,具有footprint小、抗掉电、磨损平衡等特点,可以更好地支持Flash存储介质的场景。

AliOS Things中,可以支持单个分区或双分区。默认情况下,第一个分区挂载路径为/data,第二个分区挂载路径为/system。用户可以根据需要进行单、双分区切换,也可以修改分区的挂载路径。在HaaS100平台上,默认只使能/data分区。

同时,AliOS Things littlefs文件系统支持/system分区只读功能。如果需要打开/system分区只读功能,可以在aos make编译时指定sys_readonly=1参数。

关于如何在AliOS Things上使用littlefs文件系统存储和访问文件,请参考示例应用代码:application/example/fs_demo/app.c

NAND Flash文件系统

littlefs在NAND Flash上的问题

上一章节介绍了littlefs文件系统可以适用裸Flash存储介质。对于NAND Flash的情况,虽然littlefs在功能和运行上可行,但是存在以下问题:

  • 坏块处理

    :由于NAND Flash允许出厂坏块的存在,所以在NAND上处理坏块需要更加健壮的逻辑。littlefs虽然具备完备的运行时坏块处理逻辑,但是对于出厂坏块的处理还需要增强。

  • 空间效率问题

    :对于NAND Flash,一般物理可擦除块都比较大(如128KB、256KB等)。而littlefs以块存储文件的设计,对于NAND这种场景,大多数情况下存在空间利用率低的问题。例如,对于块大小为256KB的NAND,当系统中存在大量10KB的文件时,整个文件系统的空间利用率只有40%,甚至更低。

为了解决NAND Flash场景下littlefs的上述问题,AliOS Things提供了NFTL(NAND Flash Translation Layer)模块。NFTL模块提供逻辑块到物理块/页的映射机制,通过这种映射机制到达以下目的:

  • 坏块屏蔽

    :通过逻辑块映射机制,使上层(NFTL的上层,即文件系统或其他使用NFTL的模块)使用的存储块变成逻辑块,上层不必关系逻辑块zai在物理介质上的存储和分布,且不用考虑坏块的问题。因此,在使用NFTL之后,上层可见的存储块是连续的、无坏块状态。

  • 大块切分

    :通过逻辑块映射机制,使上层可见的逻辑块可以灵活设置大小,而不必和物理块大小一一对应。一般,逻辑块大小可设置成NAND Flash物理页的倍数,如一个逻辑块对应4个物理页。目前,AliOS Things提供的NFTL模块支持逻辑块到物理页的映射(即一个逻辑块对应一个物理页)。通过这种方式,使littlefs在NAND Flash上不必使用较大的物理块作为文件存储块单位,而是以页为单位存储文件,大大提供NAND场景下littlefs的空间利用效率。

NFTL的基本原理

为了实现逻辑块的映射,NFTL使用NAND Flash物理页的spare区域存储逻辑块信息,每次数据写入物理页时,将其对应的逻辑块号写入spare区域。在系统启动时,通过读取spare区域的逻辑块信息,即可恢复逻辑块到物理页的映射关系表。上层模块访问逻辑块时,由NFTL层进行映射转换,将数据实际写入/读取到物理页。如下图所示。

截屏2020-09-15 16.49.45.png

为了加速系统启动中扫描spare区域数据建立映射表的流程,NFTL模块使用每个物理块的最后一页作为加速页,用于存储该物理块上所有页的spare区域的冗余数据(加速备份)。在系统启动中,只需要扫描每个物理块的最后一页数据,即可恢复映射表,缩短了启动时扫描的时间。其缺点是占用了一个物理页用于存储加速备份数据,浪费了一定的空间(在一个典型的系统上,每个物理块含64页,因此将消耗约1.5%的空间)。

NFTL还具备以下功能:

  • 掉电安全

    :所以数据的写入,不会直接覆盖老数据,而是新写入一个版本号更高的逻辑块数据,通过版本号识别和使用有效数据。当写入数据过程中掉电时,通过ECC校验排除写入不完整数据页,并尝试使用低版本号数据页作为有效数据,从而达到掉电保护的目的。

  • 坏块管理

    :在擦写过程中遇到坏块时,NFTL将自动进行数据迁移,并重新选取一个可用块用于数据操作。对于读取数据时的错误,目前主要依赖ECC校验保证。此外,由于NFTL不存在超级块的概念,因此对于出厂坏块问题的处理更加健壮可靠。

  • 磨损平衡

    :NFTL选取数据块进行擦写时,使用了一种动态平衡机制来达到磨损平衡的目的。

  • 垃圾回收

    :适时启动垃圾回收流程,保证垃圾块/页的回收利用。

如果想了解NFTL的具体细节,请参考NFTL的README文件(core/nftl/README.md)和代码实现(core/nftl)。

NFTL+littlefs方案的移植与使用

目前,HaaS100平台未支持NAND Flash。用户如果使用NAND Flash作为文件系统存储介质,按照以下步骤进行必要的移植适配后,即可运行和使用NFTL+littlefs文件系统功能。

  1. 根据您项目的实际情况,划分和修改Flash分区表,请注意划分给NFTL和文件系统使用的分区偏移位置和大小。注意,划分分区时,物理上只有NFTL分区的概念,没有文件系统分区的概念。NFTL分区包含文件系统分区部分和NFTL管理块部分,因此实际划分给文件系统的空间比NFTL分区大小略小。

  2. 根据分区表划分,修改nftl配置文件。修改文件路径:

    core/nftl/inc/nftl_conf.h

    。请注意修改如下配置项:

    • NFTL_PAGE_SIZE

      ,请配置为NAND Flash的物理页大小。

    • NFTL_PAGE_PER_BLOCK_NUMS

      ,请配置为NAND Flash物理块上的实际页数。

    • NFTL_LOGICAL_PARTITION_NUM

      :配置NFTL逻辑分区的数量,如支持/data分区则配置为1,支持/data、/system(A备份)、/system(B备份)则配置为3.

    • NFTL_PHYSICAL_PARTITION0/1/2

      ,NFTL对应的分区号,注意与实际Flash分区操作对应。

    • NFTL_PART0/1/2_PHY_BLOCK_NUMS

      ,NFTL分区所占用的物理块数量,请注意与分区表对应。

    • NFTL_PART0/1/2_RAW_BLOCK_NUMS

      ,NFTL分区内文件系统所占用的物理块数量。

      建议文件系统所占空间(物理块数)不超过其所在的NFTL分区空间的98%

      。因为,NFTL要预留一定的物理块用于坏块备份和管理。

  1. 修改和配置littlefs文件系统分区的大小,配置文件修改路径为:

    components/fs/littlefs/platform_conf/<platform>/platform_conf.h

参考如下示例和说明:

/* 配置分区数量,第一个分区为/data,第二个为/system */
#define LITTLEFS_CNT 2
/* 配置为NAND Flash的物理页大小 */
#define PROG_SIZE 4096
/* 配置块大小,目前仅支持配置为1 */
#define PAGE_NUMS_ON_BLOCK 1
/* /data分区所占用的block数量,注意与与NFTL的RAW_BLOCK_NUMS匹配。 */
#define DATA_BLOCK_NUMS 1024
/* /system分区所占block数,仅在LITTLEFS_CNT配置为2时有效。注意与与NFTL的RAW_BLOCK_NUMS匹配。 */
#define SYSTEM_BLOCK_NUMS 512
  1. Flash HAL接口的对接实现:

    • 通用接口实现

      :原型声明见文件

      include/aos/hal/flash.h

      ,可以参考HaaS100平台提供的实现

      platform/mcu/haas1000/hal/flash.c

    • NAND特有接口实现

      :原型声明位于

      include/aos/hal/nand_flash.h

  1. 内核镜像编译,请注意在

    aos make

    命令行指定

    nftl=1

    选项以使能NFTL模块的编译,

  2. 文件系统镜像打包,使用

    mklfs

    工具进行littlefs文件系统镜像的打包,mklfs工具位于

    components/fs/littlefs/tools/

    目录下,目前仅支持Linux版本。

  3. nftl镜像打包,使用

    mknftl

    工具进行nftl镜像的打包,

    mknftl

    工具位于

    core/nftl/tools/

    目录下。

  4. 镜像烧录和运行,请参考具体平台的烧录步骤。

总结

AliOS Things提供了丰富的文件系统方案,以及多样化的存储介质支持,特别是对NAND Flash的完备支持。同时提供了基于POSIX标准的的API,使基于标准接口开发的上层应用可以很轻易地进行移植。

如果您对AliOS Things的文件系统方案感兴趣,欢迎访问AliOS Things Github主页。如果您有任何建议或疑问,欢迎通过钉钉群或者阿里云开发者社区与我们联系。

dingding_haas