版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、u-boot中NAND flash的MTD驱动移植u-boot中移植了linux中的MTD驱动源码来支持NAND flash擦除、烧写及读的驱动。MTD(memory technology device内存技术设备)是用于访问flash设备的Linux的子系统。MTD的主要目的是为了使新的存储设备的驱动更加简单并有通用接口函数可用。MTD驱动可支持CFI接口的norflash驱动、NAND flash驱动。我们知道NAND flash的访问接口并没有像norflash一样提供了一个标准的CFI访问接口,但是NAND flash生产厂家之间在各品牌、各型号NAND falsh芯片的访问接口方面做
2、了一些约定俗成规定,如命令字、地址序列、命令序列、坏块标记位置、oob区格式等。值得注意的是:在工艺制程方面分NAND flash有两种类型:MLC和SLC。MLC和SLC属于两种不同类型的NAND FLASH存储器。SLC全称是Single-Level Cell,即单层单元闪存,而MLC全称则是Multi-Level Cell,即为多层单元闪存。它们之间的区别,在于SLC每一个单元,只能存储一位数据,MLC每一个单元可以存储两位数据,MLC的数据密度要比SLC 大一倍。在页面容量方面分NAND也有两种类型:大页面NAND flash(如:HY27UF082G2B)和小页面NAND flash
3、(如:K9F1G08U0A)。这两种类型在页面容量,命令序列、地址序列、页内访问、坏块标识方面都有很大的不同,并遵循不同的约定所以在移植驱动时要特别注意。下面以大页面的NAND flash:现代 HY27UF082G2B为例介绍一下NAND flash一些基本情况,再来介绍MTD驱动的基本结构及流程分析,最后介绍u-boot中MTD驱动移植的详细步骤:)NAND flash一些基本情况fl2400开发板上的nandflash芯片型号为:现代 HY27UF082G2B,下面先介绍一下nandflash,及norflash与nandflash之间的区别:NOR和NAND是现在市场上两种主要的非易失
4、闪存技术。Intel于1988年首先开发出NOR flash技术,它最重要得特征是支持片上执行,彻底改变了原先由EPROM和EEPROM一统非易失闪存天下的局面。紧接着,1989年,东芝公司发表了NAND flash结构,每比特更低的成本,更高的容量,并且象磁盘一样可以通过接口轻松升级。NOR flash更适合用来存储少量的关键的代码和数据,而NAND falsh则更适合存储大量的高密度的数据。下表说明了norflash与nandflash之间的差异:性能项目NorflashNandflash容量通常为14MB,最大为32MB8MB512MB片上执行支持,可以直接在其上启动bootloader
5、不支持,读要驱动。仅三星芯片支持steppingstone技术外,其他芯片必须搭配norflash启动bootloader可靠性比较高,位反转机率为nandflash的1/10比较低,位反转很常见,必须要有校验措施。推荐使用EDC/ECC算法进行错误检查和恢复,这也导致了对nandflash的管理和编写驱动程序更为复杂。访问接口与RAM、eeprom相同,地址线和数据线分开,并行访问,可随机访问地址、数据、命令并用I/O线,通过各使能引脚区分地址、数据及命令,串行访问,必须顺序访问块大小(擦除单位)64K128K8K64K块擦除时间5S,很慢3ms,快读写速度烧写慢,读快读、烧写都很快可擦除次
6、数110万次10100万次主要用途保存代码和关键数据保存大量的高密度数据文件系统支持Jffs2yaffs价格高低 下面我们根据HY27UF082G2B的datasheet从以下几个方面详细说明:3.) HY27UF082G2B概述 HY27UF082G2B,48脚TSOP1封装,容量2Gbit(256MB),位宽8位,地址、数据及命令复用I/O07。芯片封装图如下(截图自HY27UF082G2B datasheet): 从上图中可以看出:48个引脚中大部分没有用(NC),由于数据线复用所以HY27UF082G2B的真正需要连接引脚并不多。下表是HY27UF082G2B连接引脚功能表:引脚名称引
7、脚功能I/O0I/O7数据输入/输出CLE命令锁存使能ALE地址锁存使能CE片选使能WE写使能RE读使能WP写保护R/B就绪/忙信号输出VCC电源VSS地NC不接由上表可知,HY27UF082G2B与S3C2440的连线比较少:8个I/O引脚、5个使能引脚(CLE、ALE、CE、WE、RE)、1个写保护引脚(WP)、1个状态引脚(R/B)。地址、数据、命令都是在这些使能信号的配合下,通过8个I/O引脚传输。写地址、数据、命令时,CE、WE信号必须为低电平,他们在WE信号的上升沿被锁存。命令锁存使能信号CLE和地址锁存信号ALE用来区分I/O引脚上传输的是命令还是地址。其他BUS OPERATI
8、ON(总线操作)在datasheet的11页有详细描述,这里不再赘述。由上可知,对芯片的总线操作必须要有各使能信号的配合,但是这些使能信号控制不需要用户的驱动程序干预。S3C2440中的NAND flash控制器将自动根据用户读写NAND falsh控制寄存器(写的是命令寄存器NFCMD,还是地址寄存器NFADDR,还是读的数据寄存器NFDATA等等)的情况在NAND flash控制相关引脚输出正确的使能信号,用户要做的就是将S3C2440上NAND flash控制相关引脚连正确接到HY27UF082G2B的使能引脚上。S3C2440上NAND flash控制相关引脚见下图:除5个使能信号外,
9、HY27UF082G2B的状态引脚也应该连接到s3c2440的NAND flash控制相关引脚FRnB上。NAND flash芯片与S3C2440 硬件连线见下图,该截取至飞凌提供的官方硬件接线原理图:在这里还介绍一下S3C2440的NAND flash控制器相关的寄存器:1、 NFCONF:NAND flash配置寄存器1设置时序参数TACLS、TWRPH0、TWRPH0;2、 NFCONT:NAND flash配置寄存器2使能禁止NAND控制器、使能禁止引脚信号nFCE、初始化ECC;3、 NFCMD:NAND flash命令寄存器写该寄存器时向NAND flash芯片发出命令信号;4、
10、NFADDR:NAND flash地址寄存器写该寄存器时向NAND flash芯片发出地址信号;5、 NFDATA:NAND flash数据寄存器读写该寄存器时向NAND flash芯片读出或写入数据信号;6、 NFSTAT:NAND flash状态寄存器仅用到位0,0:busy,1:ready这里只简单介绍了一些重要的寄存器,还有很多的寄存器没有介绍到。比如:与NAND flash控制器提供的ECC硬件生产功能相关寄存器等,详见S3C2440 datasheet。3.) HY27UF082G2B的存储单元组织结构NAND flash跟norflash不同,NAND Flash的读取和烧录以(
11、page)页为基础, 而NOR却是以字节或字为基础。擦除都是以块为单位。NAND Flash存储器由block (块) 构成, block的基本单元是page (页)。每个页面又包含了一个Data area(数据存储区域)和一个Spare area(备用区域),小页面的NAND Flash器件每个page (页)内包含512个字节的Data area(数据存储区域)和16字节Spare area(备用区域)。大页面的NAND Flash器件每一个page (页)内包含2048个字节的Data area(数据存储区域)和64字节的Spare area(备用区域)。HY27UF082G2B为大页面
12、NAND flash。下图是HY27UF082G2B的存储单元组织结构:图中划红线处为8位宽的的HY27UF082G2B存储单元组织结构。可以看出一个芯片包含了2048个块,一个块包含了64个页,而一个页包含了2048字节的数据存储区和64字节的备用区域。下图形象的表示了HY27UF082G2B的存储单元组织结构(注意:该图中只有1024个块):可以看出一个HY27UF082G2B芯片包括了1Gbit(256MB)的数据存储区和256Mbit(32MB)的备用区。1、 HY27UF082G2B的访问地址序列HY27UF082G2B总共的容量为288MB(256MB+32MB),8位位宽,需要2
13、9位的访问地址。但芯片只提供了8根地址线(复用),明显不足。所以对HY27UF082G2B访问时,访问地址被分割成5个地址序列,这5个地址序列中的前两个为页内地址,后三个为页面地址。两个页内地址序列有效地址位为12位,以满足对页内2048+64字节空间的访问;后三个地址序列有效地址为17位,以满足对一个芯片内共2048(块)*64(页)个页面的访问。HY27UF082G2B地址序列表见下图: 上图中的L表示无效地址设为低电平。在实际驱动程序编程时用户必须严格按照这五个地址序列来向NFADDR寄存器中分别写入每个序列地址。也就是说用户发出一个完整的访问地址必须写5次NFADDR寄存器。值得注意的
14、是:小页面NAND flash仅仅提供了一个地址序列,8个访问地址位来访问512+16字节的页内空间,访问地址位明显足。所以小页面NAND flash将页内地址分割成A、B、C三个区,分别用不同的读命令进行访问,以弥补页内访问地址序列地址位不足的缺陷。相对而言,大页面NAND flash它为页内地址访问提供了足够的地址序列和访问地址位(12位地址访问2048+64字节空间,足够了),所以大页面NAND flash对页内地址的访问也更为简洁。2、 HY27UF082G2B的操作命令序列和操作实现 前面提到过: NAND Flash的读取和烧录以(page)页为基础,擦除以块为单位。那么,在NAN
15、D Flash上有三种基本的操作:读取一个页, 烧录一个页和擦除一个块,这三个基本操作有各自的命令序列。实际上,大多数NAND Flash除提供了这三个基本操作外,还提供了很多其他的操作及操作命令序列,如:HY27UF082G2B就提供了Multi Plane Program(多层烧写)、Multi Plane Erase(多层擦除)、Copy-back Program(同层页复制)、Multi-Plane Copy-Back Program(多层同层页复制)、Multi Plane Erase(多层擦除)、EDC Operation(ECD操作)、reset(复位)等操作。如上涉及到了一个层
16、的概念,什么是层?层就是将芯片各块平均分配到块组,如:块编号为奇数为一组,块编号为偶数的分为一组,这样的块组就叫层。层有这样的特性:用户可对不同层中的块同时进行擦除和烧写甚至复制。HY27UF082G2B中的块分成了2个层,有些NAND flash分成了4个层。明显,分层操作能成倍提高烧写、擦除速度。下图是HY27UF082G2B各操作的命令序列: 红线处为HY27UF082G2B的五种基本操作。下面就这五种基本操作中的读页操作的命令序列和操作方法作出详细说明,其他操作的操作方法具体参见datasheet。4.1) READ1读页读页操作有两个命令序列,命令字分别为00h、30h。读页操作的流
17、程图见下图: 整个流程比较简单,先写读页操作的第一个命令序列的命令字00h,然后写页地址(注意:这里的页地址是指页面的开始地址,此时页内地址A0A11都应为0),然后写第二个命令序列的命令字30h。再读取状态寄存器的位0,为1后就可以从NFDATA连续读出页内数据。注:流程图有一点错误:它没有读取并判断状态寄存器)。值得注意的是:这里的操作流程仅仅是读页操作,如果要在驱动程序中读出页中数据(即读NAND flash)比读页复杂得多,必须先要初始化NAND flash、判断坏块,进行ECC校验等一系列操作。这些操作这里不详述,在后面编写驱动程序时再详细分析。这里只分析读页操作是因为在移植从NAN
18、D flash启动是只需要读页操作,其他的操作在移植NAND flash驱动时再做分析。4.2) PAGE PROGRAM写页写页操作同样也有两个命令序列,命令字分别为:80h、10h。写页操作流程图如下:操作流程为:先写命令字80h再写页地址(注意:这里的页地址是指页面的开始地址,此时页内地址A0A11都应为0),接着将要写的数据写到全部依次NFDATA寄存器(这些数据会写到芯片内的写缓冲区),再通过读取状态寄存器及I/O0判断写页是否正确完成。4.3) BLOCK ERASE擦除块同样也有两个命令序列,命令字分别为60h、D0h,擦除块流程图如下: 操作流程为:写命令字60h后再写块地址(
19、块开始地址)然后写命令字d0h,再读取状态寄存器及I/O0判断是否擦除成功。 4.4) READID读ID 读设备ID只有一个命令字90h,先向命令寄存器写入90h再向地址寄存器写入00h可启动读ID操作,后续连续5次读取数据寄存器操作可以读出5个包含了全部id内容的数据。这5个数据内容如下: 第一个读取的数据为厂商ID,第二个读取的数据为设备ID。第三个读取的数据组织结构见下表:bit0:1为芯片封装类型,bit2:3为芯片制程类型(SLC还是MLC),bit4:5为同时写页数,bit6、7不明。第三个读ID数据反应的内容并不常用。第四个读ID数据组织结构如下图:bit0:1为芯片的页面容量
20、,bit2为oob区大小,bit3、7表征串行访问时间、bit4:5表示芯片块容量、bit6表示芯片位宽。第四个读ID数据给出的信息很重要,请注意。第五个读ID数据组织结构如下图:bit2:3表示芯片的分层数,bit4:6表示芯片单层容量。第五个读ID数据主要反应了芯片的分层信息,在进行分层操作时这个数据比较重要。对一个nandflash而言,读ID获得的数据是个固定值,它反应了芯片的固有特性。HY27UF082G2A的读ID数据如下图:4.5)READ STATUS REGISTER读状态寄存器 读状态寄存器只有一个命令序列70h,向命令寄存器写70h后获取芯片的状态有两种方式:1、读状态寄
21、存器:状态寄存器的bit0指示了芯片的状态,为1时就绪,为0是忙;2、读数据寄存器:I/O07指示状态如下:Bit6指示了芯片的状态,bit0指示了烧写、擦除的状态:0为完成,1为出错。关于这点在烧写、擦除流程图中表述得很清楚。)MTD驱动结构及流程分析MTD的驱动结构是围绕三个重要的数据结构展开的, 分析一个数据结构就包含了三个方面:1、 数据结构的结构声明;2、 数据结构的变量定义;3、 数据结构的操作;下面我们就MTD驱动的三个数据结构在这三方面分别分析。MTD驱动的三个重要数据结构是:struct mtd_info、struct nand_chip、struct nand_flash_
22、dev。1、数据结构struct mtd_info分析该数据结构是MTD设备操作的通用接口,主要针对的是MTD设备。这其中包含了大量的描述MTD设备的基本数据和对MTD设备操作函数的函数指针。要强调的是:包含的这些函数指针指向的函数是MTD驱动提供的接口函数(每一个驱动程序的最终目的就是提供一些接口函数实现对底层硬件设备的操作),这些函数是在整个MTD驱动框架中层次最高的函数,他们可以在应用程序中直接调用实现对MTD设备底层硬件的操作。如:static int nand_read_ecc ()。它实现了对NAND flash的读操作。这些函数一般是都在u-boot源码目录下的driver/na
23、nd/nand_base.c中实现的通用操作函数。MTD驱动保证这些通用的操作函数支持对各种NAND flash芯片的操作。下面就数据结构的三个方面来具体分析struct mtd_info:1) struct mtd_info的结构声明该结构在include/linux/mtd/nand.h中做了结构声明,去掉一些编译选项、无关成员和原有注释后声明,并添加了一些重要成员的住时候,其源码如下:struct mtd_info u_char type; /MTD设备类型,norflash还是NAND flashu_int32_t flags; /MTD设备的性能描述u_int32_t size; /
24、MTD设备的容量u_int32_t erasesize; /擦除单位大小u_int32_t oobblock; /NAND flash 页面容量u_int32_t oobsize; /NAND flash OOB区容量u_int32_t oobavail; /文件系统可用的oobfree区字节数u_int32_t ecctype; /ECC校验类型u_int32_t eccsize;int (*erase) (struct mtd_info *mtd, struct erase_info *instr); /擦除功能函数的函数指针int (*read) (struct mtd_info *mt
25、d, loff_t from, size_t len, size_t *retlen, u_char *buf);/读功能函数的函数指针int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); /写功能函数的函数指针int (*read_ecc) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobin
26、fo *oobsel); /NAND flash特有的读ECC功能函数(实际上NAND flash读操作是在这个函数中完成的)函数指针int (*write_ecc) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);/NAND flash特有的写ECC功能函数(实际上NAND flash写操作是在这个函数中完成的)函数指针int (*read_oob) (struct mtd_info *mt
27、d, loff_t from, size_t len, size_t *retlen, u_char *buf); /NAND flash 读oob区功能函数的函数指针int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);/NAND flash 写oob区功能函数的函数指针./* 坏块管理函数的函数指针 */int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);int (*block_markbad)
28、 (struct mtd_info *mtd, loff_t ofs);void *priv; /这个指针指向MTD驱动中另一个重要的数据结构struct nand_chip; 2) struct mtd_info的变量定义struct mtd_info数据结构的变量在drivers/nand/nand.c中定义为:nand_info_t nand_infoCFG_MAX_NAND_DEVICE;其中有:typedef struct mtd_info nand_info_t 可知nand_info就是mtd_info,CFG_MAX_NAND_DEVICE为在include/configs/f
29、l2440.h中必须配置的参数,它表示开发板上NAND flash的物理片数。这个变量将在nand_init()调用函数static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr)时,作为该函数的第一个实参调用,如下: nand_init_chip(&nand_infoi, &nand_chipi, base_addressi); 在MTD框架内几乎所有的函数都会有一个形参struct mtd_info *mtd,这个形参的实际值就是&nand_info
30、i,所以MTD框架内的函数中mtd指针指向的是在drivers/nand/nand.c中定义的变量nand_infoi的指针。尤其是nand_scan()函数中,大量用到了mtd这个指针来指向变量nand_infoi。如:mtd->write = nand_write;mtd->read_ecc = nand_read_ecc;mtd->write_ecc = nand_write_ecc;等。3)对struct mtd_info操作(初始化)数据结构struct mtd_info是一个简单的结构体,对它的操作比较简单。无非就是对其结构体中的成员变量进行初始化。对struct
31、 mtd_info的初始化都在函数nand_scan()中完成。该函数是初始化MTD设备的核心函数。我们将在后面详细分析它。题外话:对一个数据结构的操作绝不仅仅是初始化,如链表,对它的操作除初始化外还包括了链表管理,如:链表成员的添加、删除等操作。这样的操作更复杂,一般通过专门的函数来实现。2、 数据结构struct nand_chip分析 这个数据结构从结构名nand_chip就可以知道它主要针对MTD设备中NAND flash的描述。在这个数据结构中包含了许多参数和函数指针。其中的成员大致可以分为以下几类:1、 与芯片有关的参数如:page_shift、phys_erase_shift、b
32、bt_erase_shift、chip_shift、chipsize、numchips 2、与坏块管理、ECC校验及oob区管理有关的参数: 如: eccmode、eccsize、eccbyte、eccsteps、calculate_ecc、oob_buf、oobdirty、autooob、bbt、badblockpos、bbt_td、bbt_md、badblock_pattern 3、与NAND flash控制器寄存器操作有关的参数 如:IO_ADDR_R、IO_ADDR_W 4、与NAND flash控制器寄存器操作有关的函数指针 如:read_byte、write_byte、read_w
33、ord、write_word、hwcontrol、dev_ready、cmdfunc、select_chip 5、与NAND flash操作功能有关的函数指针 如:write_buf、read_buf、verify_buf、waitfunc、erase_cmd 6、与坏块管理、ECC校验及oob区管理有关的函数指针: 如:block_bad、block_markbad、calculate_ecc、correct_data、enable_hwecc、scan_bbt综上,nand_chip主要包括了MTD驱动的低层和底层硬件操作函数的函数指针以及坏块管理、ECC校验和oob区管理需要相关函数的函
34、数指针,这些指针指向的函数一部分在u-boot源码目录下的driver/nand/nand_base.c定义为通用函数,一部分需要用户在移植时自行编写。那些需要用户自行编写在后续的分析将会提到。nand_chip还包括了一些参数,这些参数与具体芯片型号及坏块管理策略有关,它们会在nand_scan()函数中被初始化。1)struct nand_chip的结构声明它在include/linux/mtd/nand.h中被声明定义,去掉一些编译选项、无关成员及原有注释,添加一些注释后如下;struct nand_chip void _iomem*IO_ADDR_R; /NAND flash控制器的寄
35、存器读访问指针,void _iomem*IO_ADDR_W; /NAND flash控制器的寄存器写访问指针,u_char(*read_byte)(struct mtd_info *mtd); /写一字节到NAND flash控制器的寄存器函数的函数指针void(*write_byte)(struct mtd_info *mtd, u_char byte); /从NAND flash控制器的寄存器读一字节函数的函数指针u16(*read_word)(struct mtd_info *mtd); /读字函数指针void(*write_word)(struct mtd_info *mtd, u16
36、 word); /写字函数指针 /读写缓冲区函数指针,所谓缓冲区无非就是自行定义的一个数组void(*write_buf)(struct mtd_info *mtd, const u_char *buf, int len);void(*read_buf)(struct mtd_info *mtd, u_char *buf, int len);int(*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len);/缓存校验韩式指针,验证从Flash中读取的内容是否与缓存中一致void(*select_chip)(struct mtd
37、_info *mtd, int chip); /芯片片选函数指针,由于涉及底层寄存器操作该函数在移植时一般要自己编写int(*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip); /读取坏块标记函数指针int(*block_markbad)(struct mtd_info *mtd, loff_t ofs); /标记坏块函数指针void(*hwcontrol)(struct mtd_info *mtd, int cmd); /寄存器访问控制函数指针,该函数根据第二个参数cmd使O_ADDR_R/W指向不同的寄存器int(*dev_
38、ready)(struct mtd_info *mtd); /设备状态读取函数指针,该函数读取NAND flash控制器的NFSTAT的bit0,获取R/B状态void(*cmdfunc)(struct mtd_info *mtd, unsigned command, int column, int page_addr);/向NAND flash写一个命令字,如果形参column、page_addr不都为-1则还向NAND flash写一个地址int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this, int state);/操作超
39、时处理函数指针,该函数根据命令的不同设定不同的超时时间并时刻检查R/B位直到R/B状态进入Ready状态否则为操作超时。int(*calculate_ecc)(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code); /ECC编码计算函数指针,该函数通过软件算法计算256字节的3字节ECC编码int(*correct_data)(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc); /ECC检测纠正函数,该函数检测并纠正256字节块中的1位错误
40、。void(*enable_hwecc)(struct mtd_info *mtd, int mode); /使能硬件计算ECC码函数指针void(*erase_cmd)(struct mtd_info *mtd, int page); /擦除指定块函数的函数指针int(*scan_bbt)(struct mtd_info *mtd); /坏块标记表创建函数指针inteccmode;/ ECC的计算方法, NAND_ECC_SOFT时意指软件运算,即采用calculate_ecc进行运算,利用correct_data进行校正inteccsize;/ ECC校准的数据长度,用calculate_
41、ecc进行校准时,数据长度固定为256字节inteccbytes;/ ECC校验码字节数,软件校准时为3字节inteccsteps;/ ECC校验的步数,当FLASH每页的字节数为512字节,而calculate_ecc每次仅能校验256字节,则需要两步才能校验完成。intchip_delay;/ 等待时间,一般用于等待Flash的R/B管脚intpage_shift;/ 页的地址移位数,当为512(29)字节的空间,其该值为9intphys_erase_shift;/ 块的地址移位数intbbt_erase_shift;/ 在bbt表中,相间隔两个内容之间的地址差的位数,也即是块的地址位数i
42、ntchip_shift;/ 芯片总的地址位数u_char*data_buf; /数据缓冲区指针u_char*oob_buf;/oob缓冲区指针intoobdirty;/ 表示oob_buf内是否有内容,如为0表示oob_buf为空(0xFF),为1表示oob_buf中已有内容u_char*data_poi;/ 指向一个临时使用的数据区unsigned intoptions;/MTD驱动中配置NAND FALSH芯片的扩展功能,如NAND_IS_AND、NAND_USE_FLASH_BBT、NAND_COPYBACK等等和重要参数,如位宽NAND_BUSWIDTH_16。上述的这些宏在incl
43、ude/linux/mtd/nand.h均有定义,这些宏的定义能保证当它们进行或运算是能保证options能同时接受这些扩展功能和参数。及options某bit位为1时则使用对应的扩展功能。如有:#define NAND_COPYBACK0x00000010那么如果options的bit4位为1则使用copyback功能,在MTD中大量使用了这种技巧,需要注意intbadblockpos;/ 坏块标记的位置。当芯片为小页面NAND flashs时值为NAND_SMALL_BADBLOCK_POS(即为5);为大页面时值为NAND_BIG _BADBLOCK_POS(即为0)intnumchip
44、s;/开发板上NAND flash芯片的片数unsigned longchipsize;/ 芯片的容量intpagemask;/页地址掩码intpagebuf;/ 存储Data_buf内的相关的页号struct nand_oobinfo*autooob;/ oob区布局设计结构体指针。从功能上看,oob区和数据存储区一样可以存储数据,但是oob区一般不会用于存储数据,而是做为坏块标记和ECC校验数据存储。其中坏块标记位置一般有约定俗成的位置,而oob区的布局设计有很多不同的设计,MTD使用一个结构体来描述这种设计,oob区布局设计结构体在include/linux/mtd/mtd_abi.h中
45、定义如下:struct nand_oobinfo uint32_t useecc;uint32_t eccbytes;uint32_t oobfree82;uint32_t eccpos32;其中useecc 为使用ECC校验标志,eccbyte为ECC校验的位数,eccpos为ECC校验所存的位号,oobfree为OOB中ECC未使用到的字节(起始地址长度)uint8_t*bbt;/ 指向内存中坏块表的指针struct nand_bbt_descr*bbt_td;/ 用以Flash中坏块表搜索的相关描述struct nand_bbt_descr*bbt_md;/ 上述描述的镜像struct
46、nand_hw_control*controller;/ 用以实现互锁操作,此处并未使用void*priv;/用途不明;2)struct nand_chip的变量定义struct nand_chip数据结构的变量在drivers/nand/nand.c中定义为: static struct nand_chip nand_chipCFG_MAX_NAND_DEVICE;该变量nand_chipi的指针将作为函数static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, ulong base_addr) 被nan
47、d_init()调用时的第二个实参被引用如下:nand_init_chip(&nand_infoi, &nand_chipi, base_addressi);在函数nand_init_chip()中&nand_chipi将被复制给mtd数据结构中的成员priv,如下 mtd->priv = nand;所以,mtd->priv实际上就是数据结构struct nand_chip变量指针。3)struct nand_chip的操作(初始化)对struct nand_chip的初始化操作都在函数nand_scan()中完成。该函数是初始化MTD设备的核心函数。我们将
48、在后面详细分析它。值得注意的是:在nand_scan()中struct nand_chip的函数指针会被初始化为相应的在driver/nand/nand_base.c定义的通用函数,虽说MTD驱动对绝大多数的NAND flash芯片支持都很好但是少部分通用函数可能还是会需要修改,而且涉及到底层硬件操作的函数MTD不可能提供通用的函数,所以要在移植MTD驱动时自行编写,这也是移植的一个重要内容。这些函数包括:hwcontrol、dev_ready、select_chip等。3、 数据结构struct nand_flash_dev分析这个数据结构主要描述的是具体的NAND flash芯片型号。这个
49、数据结构比较简单,它在include/linux/mtd/nand.h中被声明定义为一个结构体: struct nand_flash_dev char *name; /NAND flash的名称int id; /NAND flashd 的设备IDunsigned long pagesize;/页面大小,单位为KBunsigned long chipsize;/芯片容量,单位为MBunsigned long erasesize;/擦除单位大小unsigned long options;/ NAND flashd的扩展功能配置及位宽配置;结构体struct nand_flash_dev在drive
50、rs/mtd/nand_ids.c中这个数据结构被定义为一个结构体数组并被初始化。其中包含的每一个数组元素即为MTD驱动支持的NAND flashd芯片型号。初始化如下:struct nand_flash_dev nand_flash_ids = ."NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16,"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16,/* 1 Gigabit */&quo
51、t;NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR,"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR,/* 2 Gigabit */"NAND 256MiB 1,8V 8-bit", 0xAA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR,&
52、quot;NAND 256MiB 3,3V 8-bit", 0xDA, 0, 256, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR,/* 4 Gigabit */"NAND 512MiB 1,8V 8-bit", 0xAC, 0, 512, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR,/* 8 Gigabit */"NAND 1GiB 1,8V 8-bit", 0xA3, 0, 1024, 0, NAND_SAMSUNG_LP_OPTIONS | N
53、AND_NO_AUTOINCR,/* 16 Gigabit */"NAND 2GiB 1,8V 8-bit", 0xA5, 0, 2048, 0, NAND_SAMSUNG_LP_OPTIONS | NAND_NO_AUTOINCR,NULL,;这里列出来的只有很少的一部分数组元素,其中加粗的元素就是HY27UF082G2B对应的nand_flash_dev结构体。可知HY27UF082G2B的设备ID为DA,芯片容量为256MB,页面大小和擦除单元大小为0表示这些数据需要从芯片中读取。要强调的是:移植MTD驱动时一定要确定要移植的NAND flash芯片在这里有对应的na
54、nd_flash_dev结构体,没有的话要自行添加。在nand_scan()中,会先读出芯片的设备ID再到该结构体数组中逐个对比,如果没有找到匹配项则会导致在nand_scan()初始化失败返回。4)u-boot中MTD对NAND flash的初始化流程及源码分析 对NAND flash初始化的核心内容就是对以上分析的三个数据结构(结构体)进行初始化。注意这三个数据结构均为结构体,且在变量定义的时候都被定义为结构体数组。每一个NAND flash芯片分别对应三个结构体数组中的一个数组元素。对一个NAND flash的初始化就是对三个结构体数组元素初始化。在这三个数组元素(就是结构体)中包含了1
55、、 MTD驱动的接口函数、底层操作函数、坏块管理函数、ECC校验函数的函数指针,这些函数大部分为在nand_base.c中实现的通用函数,少部分涉及底层硬件操作的函数由用户编写;2、 支持这些函数的必要数据结构,如坏块表、读写缓冲区等3、 一些重要的参数,这些参数由flash_dev nand_flash_ids提供或者有ReadID操作直接提供或基于这些参数运算获得。4.1)流程分析 对NAND flash的这些参数和函数指针的初始化由函数nand_init()完成,该函数在lib_arm/board.c中的函数start_armboot()中被调用,调用代码如下:#if (CONFIG_C
56、OMMANDS & CFG_CMD_NAND)puts ("NAND: ");nand_init();/* go init the NAND */#endif由上可知:必须第一好宏开关:CONFIG_COMMANDS & CFG_CMD_NAND(也就是NAND命令的宏定义)nand_init()才会被执行。所以移植时一定要注意。NAND flash的初始化函数nand_init()在drivers/nand/nand.c中被定义,代码如下:void nand_init(void)int i;unsigned int size = 0;for (i = 0; i < CFG_MAX_NAND_DEVICE; i+) nand_init_chip(&nand_infoi, &n
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 师德师风警示教育活动总结6篇
- 工程信息管理体系
- 国开《可编程控制器应用》形考任务五实验1
- 2024年淮南联合大学高职单招职业适应性测试历年参考题库含答案解析
- 2022年6月7日陕西省省直事业单位广播电视局面试真题及答案
- 中国人民大学会计系列教材·第四版《成本会计学》课件-第六章
- 湿纸巾发展趋势分析报告
- 2024年陇西县第一人民医院高层次卫技人才招聘笔试历年参考题库频考点附带答案
- 如何提起证券交易代理合同纠纷诉讼培训讲学
- 2024年泰山护理职业学院高职单招职业适应性测试历年参考题库含答案解析
- 《常见包材工艺简介》课件
- 运输管理与铁路运输
- 宁德时代社招测评题库
- 统编版六年级语文上册专项 专题11文言文阅读-原卷版+解析
- 高中数学笔记总结高一至高三很全
- 011(1)-《社会保险人员减员申报表》
- 电厂C级检修工艺流程
- 函授本科《小学教育》毕业论文范文
- 高考高中英语单词词根词缀大全
- 药用辅料聚乙二醇400特性、用法用量
- 《中小学机器人教育研究(论文)11000字》
评论
0/150
提交评论