为什么80%的码农都做不了架构师?>>>   

由于NAND Flash的现有工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此在NAND芯片出厂的时候,厂家只能保证block 0不是坏块,对于其它block,则均有可能存在坏块,而且NAND芯片在使用的过程中也很容易产生坏块。因此,我们在读写NAND FLASH 的时候,需要检测坏块,同时还需在NAND驱动中加入坏块管理的功能。 
  
NAND驱动在加载的时候,会调用nand_scan函数,对bad block table的搜寻,建立等操作就是在这个函数的第二部分,即nand_scan_tail函数中完成的。

在nand_scan_tail函数中,会首先检查struct nand_chip结构体中的options成员变量是否被赋上了NAND_SKIP_BBTSCAN,这个宏表示跳过扫描bbt。所以,只有当你的driver中没有为options定义NAND_SKIP_BBTSCAN时,MTD才会继续与bbt相关工作,即调用struct nand_chip中的scan_bbt函数指针所指向的函数,在MTD中,这个函数指针指向nand_default_bbt函数。

bbt有两种存储方式,一种是把bbt存储在NAND芯片中,另一种是把bbt存储在内存中。对于前者,好处是驱动加载更快,因为它只会在第一次加载NAND驱动时扫描整个NAND芯片,然后在NAND芯片的某个block中建立bbt,坏处是需要至少消耗NAND芯片一个block的存储容量;而对于后者,好处是不会耗用NAND芯片的容量,坏处是驱动加载稍慢,因为存储在内存中的bbt每次断电后都不会保存,所以在每次加载NAND驱动时,都会扫描整个NAND芯片,以便建立bbt。

如果你系统中的NAND芯片容量不是太大的话,我建议还是把bbt存储在内存中比较好,因为根据本人的使用经验,对一块容量为2G bits的NAND芯片,分别采用这两种存储方式的驱动的加载速度相差不大,甚至几乎感觉不出来。

建立bbt后,以后在做擦除等操作时,就不用每次都去验证当前block是否是个坏块了,因为从bbt中就可以得到这个信息。另外,若在读写等操作时,发现产生了新的坏块,那么除了标志这个block是个坏块外,也还需更新bbt。

接下来,介绍一下MTD是如何查找或者建立bbt的。

1、MTD中与bbt相关的结构体

struct nand_chip中的scan_bbt函数指针所指向的函数,即nand_default_bbt函数会首先检查struct nand_chip中options成员变量,如果当前NAND芯片是AG-AND类型的,会强制把bbt存储在NAND芯片中,因为这种类型的NAND芯片中含有厂家标注的“好块”信息,擦除这些block时会导致丢失坏块信息。

接着nand_default_bbt函数会再次检查struct nand_chip中options成员变量,根据它是否定义了NAND_USE_FLASH_BBT,而为struct nand_chip中3个与bbt相关的结构体附上不同的值,然后再统一调用nand_scan_bbt函数,nand_scan_bbt函数会那3个结构体的不同的值做不同的动作,或者把bbt存储在NAND芯片中,或者把bbt存储在内存中。

在struct nand_chip中与bbt相关的结构体如下:

struct nand_chip {
    ……
    uint8_t     *bbt
    struct nand_bbt_descr    *bbt_td;
    struct nand_bbt_descr    *bbt_md;
    struct nand_bbt_descr    *badblock_pattern;
    ……

};

bbt指向一块在nand_default_bbt函数中分配的内存,若options中没有定义NAND_USE_FLASH_BBT,MTD就直接在bbt指向的内存中建立bbt,否则就会先从NAND芯片中查找bbt是否存在,若存在,就把bbt的内容读出来并保存到bbt指向的内存中,若不存在,则在bbt指向的内存中建立bbt,最后把它写入到NAND芯片中去。

bbt_td、bbt_md和badblock_pattern就是在nand_default_bbt函数中赋值的3个结构体。它们虽然是相同的结构体类型,但却有不同的作用和含义。
其中bbt_td和bbt_md是主bbt和镜像bbt的描述符(镜像bbt主要用来对bbt的update和备份),它们只在把bbt存储在NAND芯片的情况下使用,用来从NAND芯片中查找bbt。若bbt存储在内存中,bbt_td和bbt_md将会被赋值为NULL。

badblock_pattern就是坏块信息的pattern,其中定义了坏块信息在oob中的存储位置,以及内容(即用什么值表示这个block是个坏块)。

通常用1或2个字节来标志一个block是否为坏块,这1或2个字节就是坏块信息,如果这1或2个字节的内容是0xff,那就说明这个block是好的,否则就是坏块。对于坏块信息在NAND芯片中的存储位置,small page(每页512 Byte)和big page(每页2048 Byte)的两种NAND芯片不尽相同。一般来说,small page的NAND芯片,坏块信息存储在每个block的第一个page的oob的第六个字节中,而big page的NAND芯片,坏块信息存储在每个block的第一个page的oob的第1和第2个字节中。

我不能确定是否所有的NAND芯片都是如此布局,但应该绝大多数NAND芯片是这样的,不过,即使某种NAND芯片的坏块信息不是这样的存储方式也没关系,因为我们可以在badblock_pattern中自己指定坏块信息的存储位置,以及用什么值来标志坏块(其实这个值表示的应该是“好块”,因为MTD会把从oob中坏块信息存储位置读出的内容与这个值做比较,若相等,则表示是个“好块”,否则就是坏块)。

bbt_td、bbt_md和badblock_pattern的结构体类型定义如下:

struct nand_bbt_descr {
    int    options;
    int    pages[NAND_MAX_CHIPS];
    int    offs;
    int    veroffs;
    uint8_t    version[NAND_MAX_CHIPS];
    int    len;
    int    maxblocks;
    int    reserved_block_code;
    uint8_t    *pattern;

};

options:bad block table或者bad block的选项,可用的选择以及各选项具体表示什么含义,可以参考<linux/mtd/nand.h>。

pages:bbt专用。在查找bbt的时候,若找到了bbt,就把bbt所在的page号保存在这个成员变量中。若没找到bbt,就会把新建立的bbt的保存位置赋值给它。因为系统中可能会有多个NAND芯片,我们可以为每一片NAND芯片建立一个bbt,也可以只在其中一片NAND芯片中建立唯一的一个bbt,所以这里的pages是个维数为NAND_MAX_CHIPS的数值,用来保存每一片NAND芯片的bbt位置。当然,若只建立了一个bbt,那么就只使用pages[0]。

offs、len和pattern:MTD会从oob的offs中读出len长度的内容,然后与pattern指针指向的内容做比较,若相等,则表示找到了bbt,或者表示这个block是好的。

veroffs和version:bbt专用。MTD会从oob的veroffs中读出一个字节的内容,作为bbt的版本值保存在version中。

maxblocks:bbt专用。MTD在查找bbt的时候,不会查找NAND芯片中所有的block,而是最多查找maxblocks个block。

2、bbt存储在内存中时的工作流程

前文说过,不管bbt是存储在NAND芯片中,还是存储在内存中,nand_default_bbt函数都会调用nand_scan_bbt函数。

nand_scan_bbt函数会判断bbt_td的值,若是NULL,则表示bbt存储在内存中,它就在调用nand_memory_bbt函数后返回。nand_memory_bbt函数的主要工作就是在内存中建立bbt,其实就是调用了create_bbt函数。

create_bbt函数的工作方式很简单,就是扫描NAND芯片所有的block,读取每个block中第一个page的oob内容,然后根据oob中的坏块信息建立起bbt,可以参见上节关于struct nand_bbt_descr中的offs、len和pattern成员变量的解释。

3、bbt存储在NAND芯片时的工作流程

相对于把bbt存储在内存中,这种方式的工作流程稍显复杂一点。

nand_scan_bbt函数首先从NAND芯片中读取bbt的内容,它读取的方式分为两种:

其一是调用read_abs_bbts函数直接从给定的page地址读取,那么这个page地址在什么时候指定呢?就是在你的NAND driver中指定。前文说过,在struct nand_chip结构体中有两个成员变量,分别是bbt_td和bbt_md,MTD为它们附上了default的值,但是你也可以根据你的需要为它们附上你自己定义的值。假如你为bbt_td和bbt_md的options成员变量定义了NAND_BBT_ABSPAGE,同时又把你的bbt所在的page地址保存在bbt_td和bbt_md的pages成员变量中,MTD就可以直接在这个page地址中读取bbt了。值得一提的是,在实际使用时一般不这么干,因为你不能保证你保存bbt的那个block就永远不会坏,而且这样也不灵活;

其二是调用那个search_read_bbts函数试着在NAND芯片的maxblocks(请见上文关于struct nand_bbt_descr中maxblocks的说明)个block中查找bbt是否存在,若找到,就可以读取bbt了。

MTD查找bbt的过程为:如果你在bbt_td和bbt_md的options 成员变量中定义了 NAND_BBT_LASTBLOCK,那么MTD就会从NAND芯片的最后一个block开始查找(在default情况下,MTD就是这么干的),否则就从第一个block开始查找。

与查找oob中的坏块信息时类似,MTD会从所查找block的第一个page的oob中读取内容,然后与bbt_td或bbt_md中patter指向的内容做比较,若相等,则表示找到了bbt,否则就继续查找下一个block。顺利的情况下,只需查找一个block中就可以找到bbt,否则MTD最多会查找maxblocks个block。
若找到了bbt,就把该bbt所在的page地址保存到bbt_td或bbt_md的pages成员变量中,否则pages的值为-1。

如果系统中有多片NAND芯片,并且为每一片NAND芯片都建立一个bbt,那么就会在每片NAND芯片上重复以上过程。

接着,nand_scan_bbt函数会调用check_create函数,该函数会判断是否找到了bbt,其实就是判断bbt_td或者bbt_md中pages成员变量的值是否有效。若找到了bbt,就会把bbt从NAND芯片中读取出来,并保存到struct nand_chip中bbt指针指向的内存中;若没找到,就会调用create_bbt函数建立bbt(与bbt存储在内存中时情况一样),同时把bbt写入到NAND芯片中去。

转载于:https://my.oschina.net/armsky/blog/15328

MTD的坏块管理(一)-快速了解MTD的坏块管理相关推荐

  1. 企业级管理软件快速开发平台-完整的权限管理设计

    前几篇博介绍了极致业务基础平台的框架及一些开发效果详细见下面的地址 极致业务基础平台简要介绍: http://www.cnblogs.com/Jeez_JBF/archive/2010/07/29/J ...

  2. html快速创建块,CAD怎么快速创建带编号的块?

    本经验以CAD2007版本为例,介绍如何创建可编辑编号的块 1.正常启动CAD2007.先打开正交命令.(正交命令在CAD2007正下角,点击一下,即可打开,打开成功的图形呈嵌入样子).然后在命令框输 ...

  3. 企业级管理软件快速开发平台-在同一个数据库上进行多个系统开发

    前几篇博介绍了极致业务基础平台的框架及一些开发效果详细见下面的地址 极致业务基础平台简要介绍: http://www.cnblogs.com/Jeez_JBF/archive/2010/07/29/J ...

  4. linux nand 坏块_linux内核中对nand的坏块管理

    闲来无事,追踪了下linux内核中对nand的坏块管理代码.大致记录一下. 内核中对nand的坏块管理是在nand的驱动中实现的,一般情况下,我们在实现nand控制器的驱动时不用考虑坏块的管理,这些机 ...

  5. 基于华为云区块链服务快速部署和搭建链上应用

    华为云区块链服务的整体架构 华为云区块链服务BCS是面向企业及开发者的高性能.高可用和高安全的区块链技术平台服务,可以帮助企业和开发人员在华为云上快速.低成本的创建.部署和管理区块链应用. BCS基于 ...

  6. SAP 物料在启用序列号管理或者不启用序列号管理之间快速切换?

    SAP 物料在启用序列号管理或者不启用序列号管理之间快速切换? 如下物料号 74000043,在HKCS工厂下启用了序列号管理,其序列号参数文件字段值是Z002, Z002这个序列号参数文件的配置, ...

  7. linux 软件 web管理系统,如何快速安装Webmin(linux系统web管理配置工具)

    如何快速安装Webmin(linux系统web管理配置工具) 简介: Webmin是目前功能最强大的基于Web的Unix系统管理工具.管理员通过浏览器访问Webmin的各种管理功能并完成相应的管理动作 ...

  8. python软件怎么使用-Python快速入门—如何选择使用包管理工具?

    原标题:Python快速入门-如何选择使用包管理工具? 源 | cnblogs文 | 包子 在Python环境中已经有很多成熟的包,可以通过安装这些包来扩展我们的程序. 例如,很多时候Python开发 ...

  9. linux mtd 块设备,Linux系统中/dev/mtd与/dev/mtdblock的区别,即MTD字符设备和块设备的区别...

    转:http://www.crifan.com/linux_system_in__dev__mtd_and__dev__mtdblock_distinction_character_devices_a ...

最新文章

  1. html5 的a标签是可以拨电话的,通过其Href属性来实现
  2. 清华自动驾驶前沿报告!解密六大关键技术,全球人才分布【附下载】| 智东西内参...
  3. java 64位 默认分配内存大小_查看你机器中Java程序堆内存的默认初始大小和最大大小...
  4. function收集
  5. 世界级版本控制工具Vault v10.0发布,多项功能改进|附下载
  6. sdut2784cf 126b Good Luck!(next数组)
  7. linux C语言 文件相关知识01
  8. conda安装特定版本的包
  9. 深入理解JAVA中的注解
  10. 二.因子图优化学习---董靖博士在深蓝学院的公开课学习(2)
  11. 怎样防止程序重复开启?
  12. Golang实践录:静态资源文件整合:初步使用
  13. 数据分析/数据挖掘 入门级选手建议
  14. 智能小车之电源板电路设计分析
  15. c语言注释部分两侧的分界符号分别是,单片机C语言练习题
  16. scipy模块_misc模块,imread,imresize, imsave / imshow/ imrotate
  17. 信创办公--基于WPS的Word最佳实践系列(利用项目符号及编号条理化文本)
  18. python进程间通信之管道通信
  19. 弗洛伊德的乌龟和兔子(循环检测
  20. vim 删除行首指定数量字符

热门文章

  1. 7.1 pdo 宝塔面板php_宝塔面板配置阿里云服务器步骤和教程
  2. zabbix4.0添加mysql报警_部署监控三剑客 Zabbix4.0 监控以及告警机制
  3. matlab数据无量纲化_MATLAB数据预处理——归一化和标准化
  4. sql镶嵌查询_sql数据库的嵌套查询
  5. Flask-Login一些使用解释(根据官网和个人查找资料的理解并解释)
  6. python实现socket编程,客户端和服务端之间互相对话(二)
  7. 2021牛客暑期多校训练营3 I-Kuriyama Mirai and Exclusive Or (差分+位运算)
  8. [NC23486]小A与小B 双向广搜
  9. Codeforce DIV2 614 SZU的cf集训round1 C ~ D
  10. mysql中groupby会用到索引吗_开发人员不得不知的MySQL索引和查询优化