NandFlash驱动移植基础知识
NandFlash驱动移植基础知识 文章借鉴博文:http://www.voidcn.com/article/p-gfsxvqsf-bkn.html 博文写的不错,谢谢分享 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 驱动之前,也许需要读一下以下文档: 该文档可以让我们对MTD 有一个直观而又相对具体的认识,但它似乎主要是针对NOR FLASH 的,对于实际开发NAND 驱动的帮助并不是很大。 http://www.linux-mtd.infradead.org/tech/mtdnand/ http://www.linux-mtd.infradead.org/ 这里以每页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 的视野范围之内( 也许表达并不准确) 。 对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字符设备和块设备。 五、根文件系统:在Bootloader中将JFFS(或JFFS2)的文件系统映像jffs.image(或jffs2.img)烧到flash的某一个分区中,在/arch/arm/mach-your/arch.c文件的your_fixup函数中将该分区作为根文件系统挂载。 六、文件系统:内核启动后,通过mount 命令可以将flash中的其余分区作为文件系统挂载到mountpoint上。 设备层和原始设备层的函数调用关系(红色部分需要我们实现): 一个MTD原始设备可以通过mtd_part分割成数个MTD原始设备注册进mtd_table,mtd_table中的每个MTD原始设备都可以被注册成一个MTD设备,其中字符设备的主设备号为90,次设备号为0、2、4、6…(奇数次设备号为只读设备),块设备的主设备号为31,次设备号为0、1、2、3… NOR型Flash芯片驱动与MTD原始设备所有的NOR型Flash的驱动(探测probe)程序都放在drivers/mtd/chips下,一个MTD原始设备可以由一块或者数块相同的Flash芯片组成。假设由4块devicetype为x8的Flash,每块大小为8M,interleave为2,起始地址为0x01000000,地址相连,则构成一个MTD原始设备(0x01000000-0x03000000),其中两块interleave成一个chip,其地址从0x01000000到0x02000000,另两块interleave成一个chip,其地址从0x02000000到0x03000000。 请注意,所有组成一个MTD原始设备的Flash芯片必须是同类型的(无论是interleave还是地址相连),在描述MTD原始设备的数据结构中也只是采用了同一个结构来描述组成它的Flash芯片。 每个MTD原始设备都有一个mtd_info结构,其中的priv指针指向一个map_info结构,map_info结构中的fldrv_priv指向一个cfi_private结构,cfi_private结构的cfiq指针指向一个cfi_ident结构,chips指针指向一个flchip结构的数组。其中mtd_info、map_info和cfi_private结构用于描述MTD原始设备;因为组成MTD原始设备的NOR型Flash相同,cfi_ident结构用于描述Flash芯片的信息;而flchip结构用于描述每个Flash芯片的专有信息(比如说起始地址) NAND和NOR的比较 NOR和NAND是现在市场上两种主要的非易失闪存技术。Intel于1988年首先开发出NOR flash技术,彻底改变了原先由EPROM和EEPROM一统天下的局面。紧接着,1989年,东芝公司发表了NAND flash结构,强调降低每比特的成本,更高的性能,并且象磁盘一样可以通过接口轻松升级。但是经过了十多年之后,仍然有相当多的硬件工程师分不清NOR和NAND闪存。 性能比较 flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。NAND器件执行擦除操作是十分简单的,而NOR则要求在进行擦除前先要将目标块内所有的位都写为0。
——From M-system公司Arie TAL 待续。。。。。(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |