一、简介

        存储介质按物理材料的不同可分为三大类:光学存储介质、半导体存储介质和磁性存储介质。Nandflash属于非易失型的存储介质,常作为外存使用。而在实际MCU使用中因为nandflash的物理特性导致的安全问题,轻则数据错误、文件乱码,重则系统死机。这里对nandflash的软件存储管理技术进行总结,并给出了嵌入式端管理的方案,经验不足之处请多多指教。EMMC目前使用也十分广泛,推荐直接使用EMMC进行存储。

二、NandFlash的结构与特性

        下图是一个常见Nand(MT29F4G08)的芯片数据手册上的结构:

        比较通用的结构如下:Nand⇒ Chip/Die ⇒ Plane ⇒ Block ⇒ Page + oob,其中obb(Out Of Band)也叫做空闲区域(spare area)/冗余区域(redundant area),这样设计是为了保证数据的正确性,可以在obb区存储校验数据、标记坏块、映射信息等,这个后面会讲通常怎么使用这个obb。

  • 每个Nand包含一个或多个Chip。Chip是可以独立执行命令并上报状态的最小单元。
  • 每个Chip包含一个或多个plane。不同的plane间可以并发操作,不过有一些限制。
  • 每个plane包含多block,block是最小擦除单元(擦除后为全1,擦除失败则判定为坏块)。
  • 每个block包含多个page+obb, page是最小的读写单元

Nand有如下特性:

  • Nand在写入前需要先擦除,那么写入就必须要进行块操作,如果是更改数据那么需要先读取block再擦除后写入。
  • block的擦写次数是有限的,最大擦写次数称为PECycles,坏不能
  • 由于物理特性的原因,在读写时会对其他的页产生影响、漂移效应也会产生影响,会导致的出现位反转(bit flip)的现象(原先Nand中的某个位,从1变成0或者从0变成1)(这里写的物理的原因,也可能是软件上的原因,处理方法是一样的)

Nand会有如下问题:

  1. 既然flash的每个单元的擦写次数是有限的,那么如果我们总是频繁的擦写flash上的某些块,而另外一些块很少被擦写,那么这些擦写频繁的块就会很快达到使用寿命成为坏块,这样的坏块多了,如果设计上没有考虑好这个问题,就会影响整个设备的使用寿命。(磨损均衡
  2. 既然会发生位翻转,怎么发现存储的数据变了,怎么进行修复。(校验算法
  3. 怎么判定一个快为坏块
  4. 检测到坏块后,如何避免使用坏块?

三、Nand基础操作

        读页数据Read Page,写页数据(对页进行编程)Page Program,擦除整个块的数据Erase Block等操作,只需注意物理地址和操作数怎么传入的即可:物理地址 =块大小×块号 + 页大小×页号 + 页内地址/列地址,不同的Nand有不同的传输方式,分为多个Cycle进行传输。

很多资料将Nand操作分为读、写、擦除,结合实际情况应该有改的操作,这个操作对整体流程有一定的反映。

Nand的改写数据的流程(没优化流程):

  1. 读取block中的数据,将其转存到内存或者其他存储块中
  2. 校验读取的数据(如果与obb区不一致,看能不能修复,不能修复则判定为坏块)
  3. 擦除block(擦除失败则判定为坏块)
  4. 计算更改后数据的校验值
  5. 寻找一个新的block
  6. 写入新数据和校验值

四、ECC校验/位翻转修复

NAND闪存的ECC(Error Correction Code)校验方法用于检测和纠正存储在NAND闪存中的数据中的错误,有的MCU会提供硬件ECC,看使用场景用,下面列举常见的软件:

1. Hamming码是一种最简单的ECC方法,用于检测和纠正单个比特错误。每个数据字都伴随着几个校验比特,用于检测和纠正错误。如果出现单个比特错误,系统可以根据校验比特的值进行修复。

2. Bose-Chaudhuri-Hocquenghem (BCH)码是一种更强大的ECC方法,可以检测和纠正多个比特错误。BCH码的强大之处在于它可以针对不同的应用需求进行配置,以提供更高级别的纠正。

3.Reed-Solomon (RS)码是一种常用于光盘和QR码等应用中的ECC方法。RS码对于检测和纠正错误非常有用,特别是在存在大量噪声的环境中。

4. 低密度奇偶校验码(Low-Density Parity-Check)是一种现代的ECC方法,适用于NAND闪存等高密度存储介质。它在纠正性能方面非常强大,可以适应各种错误模式。

MCU中轻量化的ECC一般用Hamming码,原理可以移步到:https://www.cnblogs.com/scrutable/p/6052127.html

写时:将Page的数据输入,计算后的结果存入OBB区

读时:将Page的数据输入,与OBB区进行比较,能修复则修复,不能修复则标记为坏块。

五、坏块管理

1、背景

总结一下前面所说的,坏块出现的四种情况:

  • 出厂时的坏块
  • 操作过程中由擦除失败造成的
  • 擦除过程中写入操作失败引起的
  • 出现超出ECC校验算法纠正能力的错误时,也认为出现了坏块

坏块管理的基本作用:

标记nand中的所有坏块并建立坏块表,避免对坏块进行操作,在对nandflash进行操作时如遇到坏块则将其标记,跳过并找一好块替代该坏块,同时更新逻辑地址与物理地址的映射关系和坏块表,使得nandflash对上层文件系统仍是连续的。

目前,NAND坏块管理方法可分为如下几类:

  • 基于FTL芯片的坏块管理

    它使用一个额外的 FTL (Flash Translation Layer)芯片对 NAND 进行管理,对外部屏蔽了坏块信息,U 盘、SD 卡、MMC 卡以及固态硬盘都使用这种管理方法。这种方式简化了 NAND 操作,但也使坏块信息对外部而言不可见,如果系统中出现了可能和坏块相关的问题,定位和调试变得困难,另外,FTL 芯片也需要额外的硬件成本。

  • 基于NAND文件系统的坏块管理

    JFFS2、 YAFFS2、 FlashFx 这些专门针对 NAND 的文件系统可以对坏块进行管理。

  • NAND管理中间件

    有一些中间件(Middleware)专门用于 NAND 管理,比如 UBI。

  • 轻量级NAND坏块管理

    轻量级的坏块管理只专注于坏块,并不提供擦写负载平均的支持,而且,它也不依赖于任何第三方的库。因此,轻量级的坏块管理方式降低了系统的复杂度,而且免去了加载文件系统或初始化中间件的时间,在嵌入式系统中有着广泛的应用

下图为通过文件系统读写Nandflash的结构:

这里对于轻量级NAND坏块管理进行分析,也就是通过软件FTL进行Nand的存储管理。

2、管理技术

坏块管理技术通过映射表、坏块表、查找表(LUT)实现(也有简单的办法,但是不稳定),从管理的角度讲存储空间划分为三种:

  • 数据区:用于数据存储
  • 备用区:
    • 改写数据时,不用擦除原来的块,进行重新映射(这样的好处是防止掉电,附带平衡磨损)
    • 替换使用过过程中的坏块
  • 坏块区:用于存放初次上电扫描发现的坏块及使用过程中出现的坏块。

3、实现方法

映射表可以是block-to-block的映射,也可以是page-to-page的映射,page-to-page虽然管理方面但是FTL中维护大量的映射关系。

映射表的基本单位base:

  • 物理块地址要占9个bit
  • 标识好坏块
  • 块中page已使用情况
  • 块是否已映射等

一个映射表由N个base组成,另外包函了指向数据区、备用区、坏块区的指针,映射表的信息。

  • nand初始化
  • 扫描nand的映射表与坏块表
    • 会存放到一个固定的好block中,比如物理顺序上的第一个好block(以下三种方法均可):通过扫描所有page的obb区的标志位预留第一个好的page进行记录;预留一个page的obb区进行记录,如:MT29F4G08的obb位数等于一个block的page个数。
    • 没有找到,则扫描所有的block重新建立坏块表和映射表,因为在page的obb区存储校验数据、标记坏块、映射信息,也方便反向建立映射表
    • 第一次建立存储管理用如下流程:
      • 调用坏块表,计算该Zone坏块数量
      • 初始化映射表
      • 根据obb每个块的好块、空闲等状态,根据坏块状态情况,将坏块扔到坏块区,并在obb区写入映射情况
      • 将最后几二个映射的空块作为交换块,并在obb区写入映射情况
      • 更新逻辑物理映射表,写入某个block
  • 将映射表与坏块表放入RAM
  • 当系统要对一个已用块进行该写操作时,根据该块物理地址选择一个交换块(可以介入磨损均衡),将该已用块的数据发送到交换块上,最后擦除该已用块,将其作为新的块。最后当写完一个块时,更新RAM中的映射表,达到动态的映射地址的更新,在更新nandflash的映射表时,也是通过交换块,先将旧的映射表存进交换块后,再将更新后的映射表写进nandflash,最后擦除旧的映射表,达到防止掉电映射表被破坏后丢失的情况。

四、磨损均衡技术

1、背景

可以将block-page分为有效页、脏页、空闲页。有效页中存放有效数据,脏页中存放无效数据,空闲页是经过擦除后可以直接用于写入数据的页。

我们常用的操作就是读、写、改,其中读的操作不会影响Nand的寿命,写空闲块其实不需要擦除,改需要擦除操作,每个块擦除次数是有限的,那如何延长寿命呢?

  • 改数据后重新写入擦除较小的块中,不擦除
  • 当一个block的脏页太多时去擦除(可以结合映射表统计使用空闲情况和数据量)
  • 写入新数据找到擦除数较小的块中、或者要存满的block中

2、技术

磨损均衡涉及的技术,主要为垃圾回收(脏页回收)与block擦除数的最小计数统计(参考LUT查找表)的结合,资料比较少,相识的原理可以查看LRU算法(最近最少使用算法,这个应用超级广泛)。

在之前的流程上加上统计算法,更新LUT查找表,将新写入的内容更新到另一page上,重新建立映射

Nand的新的改写数据的流程:

  1. 读取page中的数据的指令
  2. 通过映射表映射到物理地址,获取数据
  3. 校验读取的数据(如果与obb区不一致,看能不能修复,不能修复则判定为坏块)
  4. 读取LUT查找表,选中新的page
  5. 计算更改后数据的校验值
  6. 写入新数据和校验值
  7. 更行映射信息
  8. 更新LUT查找表
  9. 判断原block是否要回收

五、MCU上Nand管理方法总结

项目开发中,能使用接口插件就尽量使用吧,学习一些原理便于debug。我目前的处理方法如下:

首选EMMC,EMMC集成了NandFlash+管理芯片,使用SDIO口就可以进行读写。

filex+levelx

rl-flashfs

littlefs

现在stm32cube里面也有nand管理的库

参考:

nandflash坏块管理机制_flash跳坏块-CSDN博客

【重要】NAND Flash基础知识简介_帅德布耀德的博客-CSDN博客

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐