liux nand坏块管理

来源:互联网 发布:ubuntu terminal打不开 编辑:程序博客网 时间:2024/05/16 19:11

转载地址 http://www.ibm.com/developerworks/cn/linux/1309_gaozp_nand/

NAND 及其坏块

NAND Flash 是一种高密度低成本的存储体,它在各种各样的嵌入式系统中获得了广泛的应用, USB 存储设备、SD 卡、手机、相机和固态硬盘等各种设备中使用的都是 NAND 芯片。其内部结构是按照块/页进行组织的,一个 NAND 芯片包含若干个块,而块内部又是由若干个页构成的。NAND 芯片出厂时就可能包含若干个坏块,在使用过程中也可能会产生新的坏块,当一个块被标记为坏块后,不应再对其写入数据,以免出现数据丢失。由于 NAND 擦写次数是有限的,而且会在使用过程中产生新的坏块,一般都需要额外的软件或硬件来配合它进行使用。

NAND 坏块管理方法分类

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

  • 基于 FTL 芯片的坏块管理

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

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

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

  • NAND 管理中间件

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

  • 轻量级 NAND 坏块管理

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

图 1 展示了几种典型的嵌入式系统中 NAND 内部的内容布局。如果需要频繁地对 NAND 写入各种数据,最好使用 NAND 文件系统或者 NAND 管理中间件对需要写入的区域进行管理。而那些很少需要更新的区域,比如 bootloader、VPD 和 Kernel,只需进行轻量级的坏块管理,不需要进行负载平均。很多的嵌入式系统中,需要写入 NAND 的数据量很少,频度也较低,比如路由器、打印机、PLC 等,这些系统完全可以仅使用轻量级的坏块管理方式。

图 1.典型嵌入式系统的 Nand Memory Map
典型嵌入式系统的 Nand Memory Map

Uboot 的轻量级坏块管理方法

NAND 坏块管理都是基于坏块表(BBT)的,通过这张表来标识系统中的所有坏块。所以,不同的管理方法之间的差异可以通过以下几个问题来找到答案。

  • 如何初始化和读取坏块表?
  • 产生新的坏块时,如何标记并更新坏块表?
  • 如何保存坏块表?是否有保存时断电保护机制?
  • 对 NAND 写入数据时,如果当前块是坏块,如何找到可替换的好块?

Uboot 是目前使用最为广泛的 bootloader,它提供了两种轻量级坏块管理方法,可称之为基本型和改进型。通过下表,我们可以看到两者的差异。

表 1. Uboot 的两种坏块管理方法对比
 基本型改进型初始化、读取 BBT系统每次初始化时,扫描整个 NAND,读取所有块的出厂坏块标志,建立 BBT,占用较多启动时间。系统第一次初始化时,扫描整清单 1. BBM 头信个 NAND 建立 BBT。之后每次初始化时,扫描 BBT 所在区域,如果发现当前块的签名和坏块表的签名(一个特定的字符串)相符,就读取当前块的数据作为 BBT。更新 BBT擦写操作产生新的坏块时,更新内存中的 BBT,同时将坏块的出厂坏块标记从 0xFF 改为 0x00。
擦写出错后仍然对坏块进行操作—更改出厂坏块标记,存在安全风险。而且,也无法区分哪些是出厂坏块,哪些是使用过程中产生的坏块。擦写操作产生新的坏块时,更新内存中的 BBT,同时将更新后的 BBT 立刻写入 NAND 或其他 NVRAM 中。保存 BBT不保存在 NAND 或其他 NVRAM 中保存一份,无掉电保护机制。坏块替换方法如果当前块是坏块,将数据写入下一个块。如果当前块是坏块,将数据写入下一个块。

虽然 uboot 的改进型坏块管理方法的做了一些改进,但它仍然有三个主要的缺点。

  1. 出现坏块,则将数据顺序写入下一个好块。如果 NAND 中存放了多个软件模块,则每个模块都需要预留一个较大的空间作为备用的好块,这会浪费较多的 NAND 空间。通常,每个模块预留的备用好块数为 NAND 芯片所允许的最大坏块数,该值因不同的芯片而有所不同,典型值为 20 或 80。假设 NAND 是大页类型,总共有 N 个模块,则总共需要预留的空间大小为 N*80*128KB。
  2. 读取 BBT 时仅检查签名,没有对 BBT 的数据做校验。
  3. 没有掉电保护机制。如果在保存 BBT 时断电,BBT 将丢失。

改进的轻量级坏块管理方法

针对现有管理方法的缺陷,本文提出了一种更加安全高效的管理方法,将从以下三个方面阐述其实现原理。

共用好块池机制

首先,使用一个统一的备用好块池,为所有存放在 NAND 中的模块提供可替换的好块。这样,就不需要在每个模块后面放置一个保留区,提高了 NAND 的空间利用率。

图 2. 共用好块池示意图
共用好块池示意图

为了实现共用好块池,需要建立一个从坏块到好块的映射,所以,除了 BBT 之外,还需定义一个替换表(SBT)。这样一来,当读第 i 个块的数据时,如果发现 BBT 中记录该块为坏块,就去 SBT 中查询其替换块;如果写第 i 个块出错,需要在 BBT 中标记该块为坏块,同时从好块池中获取一个新的好块,假设其序号为 j,然后将此好块的序号 j 写入 SBT 中的第 i 个字节,而且 SBT 的第 j 个字节写序号 i。SBT 中的这种双向映射可确保数据的可靠性。此外,好块池中的块也有可能成为坏块,如果扫描时发现是坏块,则将 SBT 中的对应位置标记为 0x00,如果是在写的过程中出错,则除了在 SBT 对应位置标记 0x00 之外,还要更新双向映射数据。

图 3. BBT/SBT 映射示意图
BBT/SBT 映射示意图

安全的 BBT/SBT 数据校验机制

传统方法仅检查 BBT 所在块的签名,将读到的前几个字节和一个特征字符串进行比较,如果一致,就认为当前块的数据为 BBT,然后读取接下来的 BBT 数据,但并不对 BBT 的数据做校验。如果 BBT 保存在 NAND 中,数据的有效性是可以得到验证的,因为 NAND 控制器或驱动一般都会对数据做 ECC 校验。但是,大多数控制器使用的 ECC 算法也仅仅能纠正一个 bit、发现 2 两个 bit 的错误。如果 BBT 保存在其他的没有 ECC 校验机制的存储体中,比如 NOR Flash,没有对 BBT 的数据进行校验显然是不安全的。

为了更加可靠和灵活地验证 BBT/SBT 数据,定义下面这个结构体来描述 BBM 信息。

清单 1. BBM 头信息
typedef struct {UINT8     acSignature[4];/* BBM 签名 */UINT32    ulBBToffset;/* BBT 偏移 */UINT32    ulSBToffset;/* SBT 偏移 */UINT16    usBlockNum;/* BBM 管理的 block 数目 */    UINT16    usSBTstart;/* SBT 所在位置的起始 block 序号 */UINT16    usSBtop;/* SBT top block */UINT16    usSBnum;/* SBT number */UINT32    ulBBTcrc;/* BBT 数据 CRC 校验码 */UINT32    ulSBTcrc;/* SBT 数据 CRC 校验码 */UINT32    ulHeadcrc;/* BBM 头信息 CRC 校验码 */} BBM_HEAD
图 4. BBT/SBT 的保存形式
BBT/SBT 的保存形式

使用三重 CRC 校验机制,无论 BBT 保存在哪种存储体中,都可以更加严格地验证数据的有效性。

安全的掉电保存机制

传统的方法仅保存一份 BBT 数据,如果在写 BBT 时系统掉电,则 BBT 丢失,系统将可能无法正常启动或工作。为安全起见,本文所述方法将同时保留三个备份,如果在写某个备份时掉电,则还有两个完好的备份。最坏的情况是,如果在写第一个备份时掉电,则当前最新的一个坏块信息丢失。

读取坏块表时,顺序读取三个备份,如果发现三个备份的数据不一致,用记录的坏块数最多的备份为当前的有效备份,同时立刻更新另外两备份。

总结

本文介绍了几类 NAND 坏块管理方法,指出了 uboot 的轻量级管理方法的缺陷,提出了一种改进的方法,提高了 NAND 的利用率及坏块管理的安全性,可对嵌入式开发起到有很好的借鉴作用。

0 0
原创粉丝点击