NandFlash驱动移植基础知识

文章借鉴博文:http://blog.csdn.net/leibniz_zsu/article/details/4977842

博文写的不错,谢谢分享

MTD 驱动程序是专门针对嵌入式 Linux 的一种驱动程序,相对于常规块设备驱动程序(比如PC 中的 IDE 硬盘)而言, MTD 驱动程序能更好的支持和管理闪存设备,因为它本身就是专为闪存设备而设计的。

具体地讲,基于 MTD 的 FLASH 驱动,承上可以很好地支持 cramfs , jffs2 和 yaffs 等文件系统,启下也能对 FLASH 的擦除,读写, FLASH 坏块以及损耗平衡进行很好的管理。所谓损耗平衡,是指对 NAND 的擦写不能总是集中在某一个或某几个 block 中,这是由 NAND 芯片有限的擦写次数的特性决定的。

总之,在现阶段,要为 FLASH 设备开发 Linux 下的驱动程序,那么基于 MTD 的开发将几乎是省时又省力的唯一选择!

一、NAND 和 NOR 的区别
简单点说,主要的区别就是:
1、 NAND 比NOR 便宜;NAND 的容量比NOR 大(指相同成本);NAND 的擦写次数是NOR 的十倍;NAND 的擦除和写入速度比NOR 快,读取速度比NOR 稍慢;
2、 NAND 和NOR 的读都可以以字节为单位,但NAND 的写以page 为单位,而NOR 可以随机写每一个字节。NAND 和NOR 的擦除都以block 为单位,但一般NAND 的block 比NOR 的block 小。另外,不管是NAND 还是NOR ,在写入前,都必须先进行擦除操作,但是NOR 在擦除前要先写0 ;
3、 NAND 不能在片内运行程序,而NOR 可以。但目前很多CPU 都可以在上电时,以硬件的方式先将NAND 的第一个block 中的内容(一般是程序代码,且也许不足一个block ,如2KB 大小)自动copy 到ram 中,然后再运行,因此只要CPU 支持,NAND 也可以当成启动设备;
4、 NAND 和NOR 都可能发生比特位反转(但NAND 反转的几率远大于NOR ),因此这两者都必须进行ECC 操作;NAND 可能会有坏块(出厂时厂家会对坏块做标记),在使用过程中也还有可能会出现新的坏块,因此NAND 驱动必须对坏块进行管理。

二、 内核树中基于 MTD 的 NAND 驱动代码的布局
在Linux 内核中,MTD 源代码放在driver/mtd 目录中,该目录中包含chips 、devices、maps 、nand 、onenand 和ubi 六个子目录。
其中只有nand 和onenand 目录中的代码才与NAND 驱动相关,不过nand 目录中的代码比较通用,而onenand 目录中的代码相对于nand 中 的代码而言则简化了很多,它是针对三星公司开发的另一类Flash芯片,即OneNAND Flash。我尚未对OneNand FLASH有过研究,只是通过网上资料得知,OneNand FLASH克服了传统NAND Flash接口复杂的缺点,具有接口简单、读写速度快、容量大、寿命长、成本低等优点。
因此,若只是开发基于MTD 的NAND 驱动程序,那么我们需要关注的代码就基本上全在drivers/mtd/nand 目录中了,而该目录中也不是所有的代码文件都与我们将要开发的NAND驱动有关,除了Makefile 和Kconfig 之外,其中真正与NAND 驱动有关的代码文件只有6 个,即:
1、 nand_base.c :
定义了NAND 驱动中对NAND 芯片最基本的操作函数和操作流程,如擦除、读写page 、读写oob等。当然这些函数都只是进行一些default 的操作,若你的系统在对NAND 操作时有一些特殊的动作,则需要在你自己的驱动代码中进行定义,然后Replace 这些default 的函数。
2、 nand_bbt.c :
定义了NAND 驱动中与坏块管理有关的函数和结构体。
3、 nand_ids.c :
定义了两个全局类型的结构体:struct nand_flash_dev nand_flash_ids[ ] 和struct nand_manufacturers nand_manuf_ids[ ] 。其中前者定义了一些NAND 芯片的类型,后者定义了NAND 芯片的几个厂商。NAND 芯片的ID 至少包含两项内容:厂商ID 和厂商为自己的NAND 芯片定义的芯片ID 。当NAND 驱动被加载的时候,它会去读取具体NAND 芯片的ID ,然后根据读取的内容到上述定义的nand_manuf_ids[ ] 和nand_flash_ids[ ] 两个结构体中去查找,以此判断该NAND 芯片是那个厂商的产品,以及该NAND 芯片的类型。若查找不到,则NAND 驱动就会加载失败,因此在开发NAND 驱动前必须事先将你的NAND 芯片添加到这两个结构体中去(其实这两个结构体中已经定义了市场上绝大多数的NAND 芯片,所以除非你的NAND 芯片实在比较特殊,否则一般不需要额外添加)。值得一提的是,nand_flash_ids[ ] 中有三项属性比较重要,即pagesize 、chipsize 和erasesize ,驱动就是依据这三项属性来决定对NAND 芯片进行擦除,读写等操作时的大小的。其中pagesize 即NAND 芯片的页大小,一般为256 、512 或2048 ;chipsize 即NAND 芯片的容量;erasesize 即每次擦除操作的大小,通常就是NAND 芯片的block 大小。
4、 nand_ecc.c :
定义了NAND 驱动中与softeware ECC 有关的函数和结构体,若你的系统支持hardware ECC ,且不需要software ECC ,则该文件也不需理会。
5、 nandsim.c :
定义了Nokia 开发的模拟NAND 设备,默认是Toshiba NAND 8MiB 1,8V 8-bit (根据ManufactureID),开发普通NAND 驱动时不用理会。
6、 diskonchip.c :
定义了片上磁盘(DOC) 相关的一些函数,开发普通NAND 驱动时不用理会。

除了上述六个文件之外,nand 目录中其他文件基本都是特定系统的NAND 驱动程序例子,但本人看来真正有参考价值的只有cafe_nand.c 和s3c2410.c 两个,而其中又尤以cafe_nand.c 更为详细,另外,nand 目录中也似乎只有cafe_nand.c 中的驱动程序在读写NAND 芯片时用到了DMA 操作。

综上所述,若要研究基于MTD 的NAND 驱动,其实所需阅读的代码量也不是很大。

另外,在动手写NAND 驱动之前,也许需要读一下以下文档:
1、 Linux MTD 源代码分析:

该文档可以让我们对MTD 有一个直观而又相对具体的认识,但它似乎主要是针对NOR FLASH 的,对于实际开发NAND 驱动的帮助并不是很大。
2、 MTD NAND Driver Programming Interface :

http://www.linux-mtd.infradead.org/tech/mtdnand/
该文档中关于ECC 的说明很有帮助。
3、 MTD 的官方网站:

http://www.linux-mtd.infradead.org/

三、NAND 相关原理

在我们开始NAND 驱动编写之前,至少应该知道:数据在NAND 中是怎样存储的,以及以怎样的方式从NAND 中读写数据时。
1、 NAND 的存储结构和操作方式
这方面的资料可以从任意一种NAND 的datasheet 中得到,因为基本上每一种NAND 的datasheet 都会介绍NAND 的组成结构和操作命令,而且事实上,大多数的NAND datasheet 都大同小异,所不同的大概只是该NAND 芯片的容量大小和读写速度等基本特性。

这里以每页512 字节的NAND FLASH 为例简单说明一下:每一块NAND 芯片由n 个block 组成-> 每一个block 由m 个page 组成-> 每一个page 由256 字节大小的column1( 也称1st half page) 、256 字节大小的column2( 也称2nd half page) 和16 字节大小的oob(out-of-band ,也称spare area) 组成。至于m 和n 的大小可以查看特定NAND 的datasheet 。相应的,若给定NAND 中的一个字节的地址,我们可以根据这个地址算出block 地址( 即第几个block) 、page 地址( 即该block 中的第几个page) 和column 地址( 即1st half page ,或2nd half page ,或oob 中的第几个字节) 。

在擦除NAND 时,必须每次至少擦除1 个block ;在写NAND 时,必须每次写1 个page( 有些NAND 也支持写不足一个page 大小的数据) ;在读NAND 时,分为三种情况( 对应三种不同的NAND 命令) ,即读column1 、读column2 和读oob ,那么为什么要分这三种情况呢?假如知道NAND 怎样根据给定的地址确定它的存储单元,那么自然也就能明白原因了,其实也并不复杂,主要是因为给定地址中的A8 并不在NAND 的视野范围之内( 也许表达并不准确) 。

事实上,在写基于MTD 的NAND 驱动时,我们并不需要实现精确到读写某一个byte 地址的函数( 除了读oob 之外) ,这是因为:
基于MTD 的NAND 驱动在读写NAND 时,可以分两种情况,即:(1) 不进行ECC 检测时,一次读写一整个page 中的MAIN 部分( 也就是那真实存储数据的512 字节) ;(2) 进行ECC 检测时( 不管是hardware ECC 还是software ECC) ,一次读写一整个page( 包括16 字节的oob 部分) 。所以部分NAND 所支持的写不足一个page 大小数据的功能,对MTD 来说是用不着的。
那么,如果只需要读写不足一个page 大小的数据怎么办?这是MTD 更上层的部分需要处理的事。也就是说,对于NAND 驱动来说,它只会读写整整一个page 的数据!
最后值得一提的是,NAND 驱动有可能只去读oob 部分,这是因为除了ECC 信息之外,坏块信息也存储在oob 之中,NAND 驱动需要读取oob 中描述坏块的那个字节( 通常是每个block 的第一个page 的oob 中的第六个字节) 来判断该block 是不是一个坏块。所以,我们只有在读oob 时,才需要实现精确到读某一个byte 地址的函数。
由此,我们也可以额外知道一件事,那就是NAND 驱动中用到的column 地址只在读oob 时才有用,而在其他情况下,column 地址都为0 。

2、 ECC 相关的结构体
struct nand_ecclayout {undefined
uint32_t eccbytes;
uint32_t eccpos[64];
uint32_t oobavail;
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
};
这是用来定义ECC 在oob 中布局的一个结构体。

前面已经提及过,oob 中主要存储两种信息:坏块信息和ECC 数据。对与small page 的NAND 芯片来说,其中坏块信息占据1 个字节( 一般固定在第六个字节) ,ECC 数据占据三个字节。所以sturct nand_ecclayout 这个结构体,也就是用来告诉那些与ECC 操作无关的函数,Nand 芯片的oob 部分中,哪些字节是用来存储ECC 的( 即不可用作它用的) ,哪些字节是空闲的,即可用的。
其实之所以有这个结构体,主要是因为硬件ECC 的缘故。以写数据为例,在使用硬件ECC 的情况下,那三个字节的ECC 数据是由硬件计算得到,并且写到NAND 芯片的oob 中去的,同时也是由硬件决定写到oob 的哪三个字节中去。这些都是由硬件做的,而NAND 驱动并不知道,所以就需要用这个结构体来告诉驱动了。
所以,在写NAND 驱动时,就有可能需要对这个结构体进行赋值。这里说“有可能”,是因为MTD 对这个结构体有一个默认的赋值,假如这个赋值所定义的ECC 位置与你的硬件一致的话,那就不必在你的驱动中手动赋值了。其实对大多数硬件( 这里所说的硬件,不是指NAND 芯片,而是NAND 控制器) 来说,是不必手动赋值的,但也有许多例外。
值得一提的是,这个结构体不仅仅用来定义ECC 布局,也可以用来将你的驱动在oob 中需要额外用到的字节位置保护起来。
现在对struct nand_ecclayout 这个结构体进行一下说明。

uint32_t eccbytes :ECC 的字节数,对于512B-per-page 的NAND 来说,eccbytes = 3 ,如果你需要额外用到oob 中的数据,那么也可以大于3.
uint32_t eccpos[64] :ECC 数据在oob 中的位置,这里之所以是个64 字节的数组,是因为对于2048-per-page 的NAND 来说,它的oob 有64 个字节。而对于512B-per-page 的NAND 来说,可以而且只可以定义它的前16 个字节。
uint32_t oobavail :oob 中可用的字节数,这个值不用赋值,MTD 会根据其它三个变量自动计算得到。
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES] :显示定义空闲的oob 字节。

对nandflash存储芯片进行操作,必须通过nandflash的控制器才能完成,而不能通过nandflash尽心总线操作,对于nandflash的写操作只能以块方式进行写,对于nandflash的读操作可以按字节进行读

nandflash命令的执行过程是通过将命令发送到nandflash控制器的命令寄存器来执行的。其命令的执行是分周期的,每条命令有一个或多个执行周期,每个执行周期有相应代码表示该周期将要执行的动作,nandflash命令主要包括:Read1,Read2,ReadID,Reset,PageProgram,BlockErase,ReadStatus等。

MTD简单介绍:

MTD(memory technology device内存技术设备)是用于访问memory设备(ROM、flash)的Linux的子系统。MTD的主要目的是为了使新的memory设备的驱动更加简单,为此它在硬件和上层之间提供了一个抽象的接口。MTD的所有源代码在/drivers/mtd子目录下。我将CFI接口的MTD设备分为四层(从设备节点直到底层硬件驱动),这四层从上到下依次是:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。

一、Flash硬件驱动层:硬件驱动层负责在init时驱动Flash硬件,Linux MTD设备的NOR Flash芯片驱动遵循CFI接口标准,其驱动程序位于drivers/mtd/chips子目录下。NAND型Flash的驱动程序则位于/drivers/mtd/nand子目录下

二、MTD原始设备:原始设备层有两部分组成,一部分是MTD原始设备的通用代码,另一部分是各个特定的Flash的数据,例如分区。

用于描述MTD原始设备的数据结构是mtd_info,这其中定义了大量的关于MTD的数据和操作函数。mtd_table(mtdcore.c)则是所有MTD原始设备的列表,mtd_part(mtd_part.c)是用于表示MTD原始设备分区的结构,其中包含了mtd_info,因为每一个分区都是被看成一个MTD原始设备加在mtd_table中的,mtd_part.mtd_info中的大部分数据都从该分区的主分区mtd_part->master中获得。

在drivers/mtd/maps/子目录下存放的是特定的flash的数据,每一个文件都描述了一块板子上的flash。其中调用add_mtd_device()、del_mtd_device()建立/删除mtd_info结构并将其加入/删除mtd_table(或者调用add_mtd_partition()、del_mtd_partition()(mtdpart.c)建立/删除mtd_part结构并将mtd_part.mtd_info加入/删除mtd_table 中)。

三、MTD设备层:基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。MTD字符设备的定义在mtdchar.c中实现,通过注册一系列file operation函数(lseek、open、close、read、write)。MTD块设备则是定义了一个描述MTD块设备的结构mtdblk_dev,并声明了一个名为mtdblks的指针数组,这数组中的每一个mtdblk_dev和mtd_table中的每一个mtd_info一一对应。

四、设备节点:通过mknod在/dev子目录下建立MTD字符设备节点(主设备号为90)和MTD块设备节点(主设备号为31),通过访问此设备节点即可访问MTD字符设备和块设备。

mtd-utils工具只能应用与/dev/mtdN的MTD字符设备


http://www.taodudu.cc/news/show-6082668.html

相关文章:

  • SPI Flash/Nor Flash/Nand Flash
  • mini2440硬件篇之Nand Flash
  • FPGA 控制 nand flash读写
  • 网卡 promiscuous mode 与 MAC 的一些 filter 功能
  • Device Tree(七)NAND FLASH
  • 45.帧缓冲设备(Framebuffer),LCD
  • 3D软件中怎么绘制杯子?
  • 球在哪个杯子里2
  • 面试题:检测杯子的质量
  • 如何测试一个一次性水杯
  • 杯子测试例子
  • 一个杯子的测试思路
  • [软件测试]怎么测试一个杯子
  • 逻辑推理:翻杯子
  • 如何测一个杯子
  • 牛奶杯和水杯
  • 关于一个杯子的测试用例
  • 两个杯子倒水问题
  • 一个纸杯子的测试用例
  • 如何测试一个杯子
  • 茶杯:N个杯子排成一排,第X个杯子藏有球,交换任意两个杯子K次后,找出藏球杯子位置。
  • 给你一个杯子,你如何测试
  • 经典测试用例,一个水杯的测试
  • 经典的杯子测试题
  • 画好了一个杯子,哈哈!
  • c++题目 杯子
  • 杯子题解
  • python3爬虫
  • 华为领衔,“5G+摄像头”拿下双影帝,多家国产手机凭借拍照入围MWC最佳演员...
  • 华为领衔,“5G+摄像头”拿下双影帝,多家国产手机凭借拍照入围MWC最佳演员...

NandFlash驱动移植基础知识相关推荐

  1. VxWorks驱动移植基础知识

    VxWorks驱动架构: 一.在最新发布的VxWorks6.x版本中,devicedriver可以通过两种方式来实现 1. VxBus-enabled devicedrivers 这种架构下编写的dr ...

  2. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之Pinctrl子系统和GPIO子系统的使用

    文章目录 前言 1.Pinctrl子系统 1.1.为什么有Pinctrl子系统 1.2.重要的概念 1.3.代码中怎么引用pinctrl 2.GPIO子系统 2.1.为什么有GPIO子系统 2.2.在 ...

  3. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之按键驱动框架

    文章目录 前言 1.APP怎么读取按键值 1.1.查询方式 1.2.休眠-唤醒方式 1.3.poll方式 1.3.异步通知方式 1.5. 驱动程序提供能力,不提供策略 2.按键驱动程序框架--查询方式 ...

  4. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED模板驱动程序的改造:设备树

    文章目录 前言 1.驱动的三种编写方法 2.怎么使用设备树写驱动程序 2.1.设备树节点要与platform_driver能匹配 2.2.修改platform_driver的源码 3.实验和调试技巧 ...

  5. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之设备树模型

    文章目录 前言 1.设备树的作用 2.设备树的语法 2.1.设备树的逻辑图和dts文件.dtb文件 2.1.1.1Devicetree格式 1DTS文件的格式 node的格式 properties的格 ...

  6. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之总线设备驱动模型

    文章目录 前言 1.驱动编写的三种方法 1.1.传统写法 1.2.总线驱动模型 1.3.设备树驱动模型 2.Linux实现分离:Bus/Dev/Drv模型 2.1.Bus/Dev/Drv模型 2.2. ...

  7. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之驱动设计的思想:面向对象/分层/分离

    文章目录 前言 1.分离设计 驱动程序分析---程序分层 通用驱动程序---面向对象 个性化驱动程序---分离 APP 程序分析 前言 韦东山嵌入式Linux驱动开发基础知识学习笔记 文章中大多内容来 ...

  8. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之LED驱动框架--面向对象、分层设计思想

    文章目录 前言 1.LED驱动程序框架 1.1.对于LED驱动,我们想要什么样的接口? 1.2.LED驱动要怎么写,才能支持多个板子?分层写 1.3.程序分析 驱动程序 应用程序 Makefile 1 ...

  9. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之第一个驱动

    文章目录 前言 1.Hello驱动 1.1.APP打开的文件在内核中如何表示? 1.2.打开字符设备节点时,内核中也有对应的struct file 1.3.如何编写驱动程序? 1.4.驱动程序代码 1 ...

最新文章

  1. Apache Httpd 2.2 配置CA证书,实现Https加密通讯
  2. SSH-jar包相应作用
  3. 用aspect在springboot中记录操作日志至数据库的详细过程
  4. linux权限746,linux文件权限学习笔一
  5. shell-awk详细笔记
  6. php链接mysql编码错误_php 操作 mysql 数据库 编码 错误
  7. 许志安刘强东倪震:结构性中年危机下的男人们
  8. linux反汇编时乱码,Linux反汇编代码理解 标准例子 很好
  9. Audition生成扫频信号(四十)
  10. java 静态方法区别_Java 中 静态方法与非静态方法的区别
  11. matlab对两组数据画图,matlab两列数据画图
  12. 基于onnxruntime的YOLOv5单张图片检测实现
  13. 免费、无版权约束、可商用的优质图片素材网站合集
  14. 计算机实验报告双绞线制作,双绞线的制作实验报告.docx
  15. open wrt 跟换主题_openwrt 更改默认主题
  16. 女生适合学软件开发吗?
  17. 淘口令解析api接口/淘口令解密还原api接口/淘口令短链接搜索商品详情接口,API接口获取方案
  18. 几种常用的特征选择方法
  19. 《算法笔记》10.5小节——图算法专题->最小生成树
  20. 智能可视化门铃方案调研报告

热门文章

  1. CMD(命令提示符)命令大全及网络安全课程中所用到的命令
  2. Windows10下Tensorflow启用GPU加速,显卡GTX1060,踩坑记录
  3. 2022开源社区app源码多端圈子社区论坛系统
  4. 陈学贤华南理工大学计算机专业,张见威 - 华南理工大学 - 计算机科学与工程学院...
  5. 瑞吉外卖项目——瑞吉外卖
  6. 揭秘:男人什么时候最想结婚
  7. 高仿淘宝购物车分分钟让你集成
  8. 自动写字成图5款有趣实用的AIGC工具分享
  9. 主元排序法c语言写法,快速排序隨即主元法
  10. 计算机二级 MS office(Excel)常用函数