【简介】如何编写linux下nand flash驱动-2【转载】

来源:互联网 发布:icmp的端口号 编辑:程序博客网 时间:2024/04/27 21:37

【简介】如何编写linuxnand flash驱动-2

version: 1.0

date:20090721

Authorcrifan

Mail:green-waste(At)163.com

 

上接:【简介】如何编写linux下nand flash驱动-1

http://green-waste.blog.163.com/blog/static/3267767820096221127554/

 

【读(read)操作过程详解】

以最简单的read操作为例,解释如何理解时序图,以及将时序图

中的要求,转化为代码。

 

解释时序图之前,让我们先要搞清楚,我们要做的事情:那就是,要从nand flash某个页里面,读取我们要的数据。

要实现此功能,会涉及到几部分的知识,至少很容易想到的就是:需要用到哪些命令,怎么发这些命令,怎么计算所需要的地址,怎么读取我们要的数据等等。

下面,就一步步的解释,需要做什么,以及如何去做:

1.需要使用何种命令

首先,是要了解,对于读取数据,要用什么命令。

下面是datasheet中的命令集合:

【简介】如何编写linux下nand flash驱动-2 - green-waste - 活着,生存,状态,不虚度。。。

5.Nand Flash K9K8G08U0A的命令集合

很容易看出,我们要读取数据,要用到Read命令,该命令需要2个周期,第一个周期发0x00,第二个周期发0x30

 

2.发送命令前的准备工作以及时序图各个信号的具体含义

知道了用何命令后,再去了解如何发送这些命令。

 [小常识]

在开始解释前,多罗嗦一下使能这个词,以便有些读者和我以前一样,在听这类虽然对于某些专业人士说是属于最基本的词汇了,但是对于初次接触,或者接触不多的人来说,听多了,容易被搞得一头雾水:使能(Enable),是指使其(某个信号)有效,使其生效的意思,“使其”“能够”怎么怎么样。。。。比如,上面图中的CLE线号,是高电平有效,如果此时将其设为高电平,我们就叫做,将CLE使能,也就是使其生效的意思。

 

【简介】如何编写linux下nand flash驱动-2 - green-waste - 活着,生存,状态,不虚度。。。

6.Nand Flash数据读取操作的时序图

注:此图来自三星的型号K9K8G08U0Anand flash的数据手册(datasheet)

 

我们来一起看看,我在图6中的特意标注的①边上的黄色竖线。

黄色竖线所处的时刻,是在发送读操作的第一个周期的命令0x00之前的那一刻。

让我们看看,在那一刻,其所穿过好几行都对应什么值,以及进一步理解,为何要那个值。

1)黄色竖线穿过的第一行,是CLE。还记得前面介绍命令所存使能(CLE)那个引脚吧?CLE,将CLE1,就说明你将要通过I/O复用端口发送进入Nand Flash的,是命令,而不是地址或者其他类型的数据。只有这样将CLE1,使其有效,才能去通知了内部硬件逻辑,你接下来将收到的是命令,内部硬件逻辑,才会将受到的命令,放到命令寄存器中,才能实现后面正确的操作,否则,不去将CLE1使其有效,硬件会无所适从,不知道你传入的到底是数据还是命令了。

2)而第二行,是CE#,那一刻的值是0。这个道理很简单,你既然要向Nand Flash发命令,那么先要选中它,所以,要保证CE#为低电平,使其有效,也就是片选有效。

3)第三行是WE#,意思是写使能。因为接下来是往nand Flash里面写命令,所以,要使得WE#有效,所以设为低电平。

4)第四行,是ALE是低电平,而ALE是高电平有效,此时意思就是使其无效。而对应地,前面介绍的,使CLE有效,因为将要数据的是命令,而不是地址。如果在其他某些场合,比如接下来的要输入地址的时候,就要使其有效,而使CLE无效了。

5)第五行,RE#,此时是高电平,无效。可以看到,知道后面低6阶段,才变成低电平,才有效,因为那时候,要发生读取命令,去读取数据。

6)第六行,就是我们重点要介绍的,复用的输入输出I/O端口了,此刻,还没有输入数据,接下来,在不同的阶段,会输入或输出不同的数据/地址。

7)第七行,R/B#,高电平,表示RReady/就绪,因为到了后面的第5阶段,硬件内部,在第四阶段,接受了外界的读取命令后,把该页的数据一点点送到页寄存器中,这段时间,属于系统在忙着干活,属于忙的阶段,所以,R/B#才变成低,表示Busy忙的状态的。

介绍了时刻①的各个信号的值,以及为何是这个值之后,相信,后面的各个时刻,对应的不同信号的各个值,大家就会自己慢慢分析了,也就容易理解具体的操作顺序和原理了。

 

3.如何计算出,我们要传入的地址

在介绍具体读取数据的详细流程之前,还要做一件事,那就是,先要搞懂我们要访问的地址,以及这些地址,如何分解后,一点点传入进去,使得硬件能识别才行。

此处还是以K9K8G08U0A为例,此nand flash,一共有8192个块,每个块内有64页,每个页是2K+64 Bytes,假设,我们要访问其中的第7000个块中的第25页中的1208字节处的地址,此时,我们就要先把具体的地址算出来:

物理地址=块大小×块号+页大小×页号+页内地址=7000×128K+64×2K+1208=0x36B204B8,接下来,我们就看看,怎么才能把这个实际的物理地址,转化为nand Flash所要求的格式。

在解释地址组成之前,先要来看看其datasheet中关于地址周期的介绍:

【简介】如何编写linux下nand flash驱动-2 - green-waste - 活着,生存,状态,不虚度。。。

7 Nand Flash的地址周期组成

结合图7和图5中的23阶段,我们可以看出,此nand flash地址周期共有5个,2个列(Column)周期,3个行(Row)周期。而对于对应地,我们可以看出,实际上,列地址A0~A10,就是页内地址,地址范围是从02047,而对出的A11,理论上可以表示20484095,但是实际上,我们最多也只用到了20482011,用于表示页内的oob区域,其大小是64字节。

对应地,A12A30,称作页号,页的号码,可以定位到具体是哪一个页。而其中,A18A30,表示对应的块号,即属于哪个块。

简单解释完了地址组成,那么就很容易分析上面例子中的地址了:

0x36B204B8 = 0011 0110 1011 0010 0000 0100 1011 1000,分别分配到5个地址周期就是:

1st 周期,A7A0        1011 1000 = 0x B8

2nd周期,A11A8       0000 0100 = 0x04

3rd周期,A19A12     0010 0000 = 0x20

4th周期,A27A20     0110 1011 = 0x6B

5th周期,A30A28     0000 0011 = 0x03

注意,与图7中对应的,*L,意思是地电平,由于未用到那些位,datasheet中强制要求设为0,所以,才有上面的2nd周期中的高4位是0000.其他的A30之后的位也是类似原理,都是0

因此,接下来要介绍的,我们要访问第7000个块中的第25页中的1208字节处的话,所要传入的地址就是分5个周期,分别传入两个列地址的:0xB80x04,然后再传3个行地址的:0x200x6B0x03,这样硬件才能识别。

 

4.读操作过程的解释

准备工作终于完了,下面就可以开始解释说明,对于读操作的,上面图中标出来的,1-6个阶段,具体是什么含义。

(1)      操作准备阶段:此处是读(Read)操作,所以,先发一个图5中读命令的第一个阶段的0x00,表示,让硬件先准备一下,接下来的操作是读。

(2)      发送两个周期的列地址。也就是页内地址,表示,我要从一个页的什么位置开始读取数据。

(3)      接下来再传入三个行地址。对应的也就是页号。

(4)      然后再发一个读操作的第二个周期的命令0x30。接下来,就是硬件内部自己的事情了。

(5)      Nand Flash内部硬件逻辑,负责去按照你的要求,根据传入的地址,找到哪个块中的哪个页,然后把整个这一页的数据,都一点点搬运到页缓存中去。而在此期间,你所能做的事,也就只需要去读取状态寄存器,看看对应的位的值,也就是R/B#那一位,是1还是00的话,就表示,系统是busy,仍在忙“(着读取数据),如果是1,就说系统活干完了,忙清了,已经把整个页的数据都搬运到页缓存里去了,你可以接下来读取你要的数据了。

对于这里。估计有人会问了,这一个页一共2048+64字节,如果我传入的页内地址,就像上面给的1208一类的值,只是想读取10282011这部分数据,而不是页开始的0地址整个页的数据,那么内部硬件却读取整个页的数据出来,岂不是很浪费吗?答案是,的确很浪费,效率看起来不高,但是实际就是这么做的,而且本身读取整个页的数据,相对时间并不长,而且读出来之后,内部数据指针会定位到你刚才所制定的1208的那个位置。

(6)      接下来,就是你“窃取“系统忙了半天之后的劳动成果的时候了,呵呵。通过先去Nand Flash的控制器中的数据寄存器中写入你要读取多少个字节(byte)/(word),然后就可以去Nand Flash的控制器的FIFO中,一点点读取你要的数据了。

至此,整个Nand Flash的读操作就完成了。

对于其他操作,可以根据我上面的分析,一点点自己去看datasheet,根据里面的时序图去分析具体的操作过程,然后对照代码,会更加清楚具体是如何实现的。

 

Flash的类型】

Flash的类型主要分两种,nand flashnor flash

除了网上最流行的这个解释之外:

NANDNOR的比较

再多说几句:

1.nor的成本相对高,具体读写数据时候,不容易出错。总体上,比较适合应用于存储少量的代码。

2.Nand flash相对成本低。使用中数据读写容易出错,所以一般都需要有对应的软件或者硬件的数据校验算法,统称为ECC。由于相对来说,容量大,价格便宜,因此适合用来存储大量的数据。其在嵌入式系统中的作用,相当于PC上的硬盘,用于存储大量数据。

所以,一个常见的应用组合就是,用小容量的Nor Flash存储启动代码,比如uboot,系统启动后,初始化对应的硬件,包括SDRAM等,然后将Nand Flash上的Linux 内核读取到内存中,做好该做的事情后,就跳转到SDRAM中去执行内核了,然后内核解压(如果是压缩内核的话,否则就直接运行了)后,开始运行,在Linux内核启动最后,去Nand Flash上,挂载根文件,比如jffs2yaffs2等,挂载完成,运行初始化脚本,启动consle交互,才运行你通过console和内核交互。至此完成整个系统启动过程。

Nor Flash就分别存放的是UbootNand Flash存放的是Linux的内核镜像和根文件系统,以及余下的空间分成一个数据区。

 

Nor flash,有类似于dram之类的地址总线,因此可以直接和CPU相连,CPU可以直接通过地址总线对nor flash进行访问,而nand flash没有这类的总线,只有IO接口,只能通过IO接口发送命令和地址,对nand flash内部数据进行访问。相比之下,nor flash就像是并行访问,nand flash就是串行访问,所以相对来说,前者的速度更快些。

但是由于物理制程/制造方面的原因,导致nor nand在一些具体操作方面的特性不同:

 

NOR

NAND

(备注)

接口

总线

I/O接口

这个两者最大的区别

单个cell大小

 

单个Cell成本

 

读耗时

 

单字节的编程时间

 

多字节的编程时间

 

擦除时间

 

功耗

低,但是需要额外的RAM

 

是否可以执行代码

不行, 但是一些新的芯片,可以在第一页之外执行一些小的loader1

即是否允许,芯片内执行(XIP, eXecute In Place) (2)

位反转(Bit twiddling/bit flip)

几乎无限制

1-4次,也称作 “部分页编程限制”

也就是数据错误,0->11->0

在芯片出厂时候是否允许坏块

不允许

允许

 

3 Nand Flash Nor Flash的区别

1.       理论上是可以的,而且也是有人验证过可以的,只不过由于nand flash的物理特性,不能完全保证所读取的数据/代码是正确的,实际上,很少这么用而已。因为,如果真是要用到nand flashXIP,那么除了读出速度慢之外,还要保证有数据的校验,以保证读出来的,将要执行的代码/数据,是正确的。否则,系统很容易就跑飞了。。。

2.       芯片内执行(XIP, eXecute In Place):

http://hi.baidu.com/serial_story/blog/item/adb20a2a3f8ffe3c5243c1df.html

 

Nand Flash的种类】

具体再分,又可以分为

1)Bare NAND chips:裸片,单独的nand 芯片

2)SmartMediaCards =裸片+一层薄塑料,常用于数码相机和MP3播放器中。之所以称smart,是由于其软件smart,而不是硬件本身有啥smart之处。^_^

3)DiskOnChip:裸片+glue logicglue logic=硬件ECC产生器+用于静态的nand 芯片控制的寄存器+直接访问一小片地址窗口,那块地址中包含了引导代码的stub桩,其可以从nand flash中拷贝真正的引导代码。

 

spare area/oob

Nand由于最初硬件设计时候考虑到,额外的错误校验等需要空间,专门对应每个页,额外设计了叫做spare area空区域,在其他地方,比如jffs2文件系统中,也叫做oobout of band)数据。

其具体用途,总结起来有:

1.       标记是否是坏快

2.       存储ECC数据

3.       存储一些和文件系统相关的数据,如jffs2就会用到这些空间存储一些特定信息,yaffs2文件系统,会在oob中,存放很多和自己文件系统相关的信息。

 

2.       软件方面

如果想要在Linux下编写Nand Flash驱动,那么就先要搞清楚Linux下,关于此部分的整个框架。弄明白,系统是如何管理你的nand flash的,以及,系统都帮你做了那些准备工作,而剩下的,驱动底层实现部分,你要去实现哪些功能,才能使得硬件正常工作起来。

 

【内存技术设备,MTDMemory Technology Device)】

MTD,是Linux的存储设备中的一个子系统。其设计此系统的目的是,对于内存类的设备,提供一个抽象层,一个接口,使得对于硬件驱动设计者来说,可以尽量少的去关心存储格式,比如FTLFFS2等,而只需要去提供最简单的底层硬件设备的读//擦除函数就可以了。而对于数据对于上层使用者来说是如何表示的,硬件驱动设计者可以不关心,而MTD存储设备子系统都帮你做好了。

对于MTD字系统的好处,简单解释就是,他帮助你实现了,很多对于以前或者其他系统来说,本来也是你驱动设计者要去实现的很多功能。换句话说,有了MTD,使得你设计Nand Flash的驱动,所要做的事情,要少很多很多,因为大部分工作,都由MTD帮你做好了。

当然,这个好处的一个“副作用”就是,使得我们不了解的人去理解整个Linux驱动架构,以及MTD,变得更加复杂。但是,总的说,觉得是利远远大于弊,否则,就不仅需要你理解,而且还是做更多的工作,实现更多的功能了。

此外,还有一个重要的原因,那就是,前面提到的nand flash和普通硬盘等设备的特殊性:

有限的通过出复用来实现输入输出命令和地址/数据等的IO接口,最小单位是页而不是常见的bit,写前需擦除等,导致了这类设备,不能像平常对待硬盘等操作一样去操作,只能采取一些特殊方法,这就诞生了MTD设备的统一抽象层。

MTD,将nand flashnor flash和其他类型的flash等设备,统一抽象成MTD设备来管理,根据这些设备的特点,上层实现了常见的操作函数封装,底层具体的内部实现,就需要驱动设计者自己来实现了。具体的内部硬件设备的读//擦除函数,那就是你必须实现的了。

HARD drives

MTD device

连续的扇区

连续的可擦除块

扇区都很小(512B,1024B)

可擦除块比较大 (32KB,128KB)

主要通过两个操作对其维护操作:读扇区,写扇区

主要通过三个操作对其维护操作:从擦除块中读,写入擦除块,擦写可擦除块

坏快被重新映射,并且被硬件隐藏起来了(至少是在如今常见的LBA硬盘设备中是如此)

坏的可擦除块没有被隐藏,软件中要处理对应的坏块问题。

HDD扇区没有擦写寿命超出的问题。

可擦除块是有擦除次数限制的,大概是104-105.

4.MTD设备和硬盘设备之间的区别

 

多说一句,关于MTD更多的内容,感兴趣的,去附录中的MTD的主页去看。

关于mtd设备驱动,感兴趣的可以去参考

MTD原始设备与FLASH硬件驱动的对话

MTD原始设备与FLASH硬件驱动的对话-

那里,算是比较详细地介绍了整个流程,方便大家理解整个mtd框架和nand flash驱动。

 

Nand flash驱动工作原理】

在介绍具体如何写Nand Flash驱动之前,我们先要了解,大概的,整个系统,和Nand Flash相关的部分的驱动工作流程,这样,对于后面的驱动实现,才能更加清楚机制,才更容易实现,否则就是,即使写完了代码,也还是没搞懂系统是如何工作的了。

让我们以最常见的,Linux内核中已经有的三星的Nand Flash驱动,来解释Nand Flash驱动具体流程和原理。

 

此处是参考2.6.29版本的Linux源码中的/drivers/mtd/nand/s3c2410.c,以2410为例。

1.       nand flash驱动加载后,第一步,就是去调用对应的init函数,s3c2410_nand_init,去将在nand flash驱动注册到Linux驱动框架中。

2.       驱动本身,真正开始,是从probe函数,s3c2410_nand_probe->s3c24xx_nand_probe,

probe过程中,去用clk_enable打开nand flash控制器的clock时钟,用request_mem_region去申请驱动所需要的一些内存等相关资源。然后,在s3c2410_nand_inithw中,去初始化硬件相关的部分,主要是关于时钟频率的计算,以及启用nand flash控制器,使得硬件初始化好了,后面才能正常工作。

3.       需要多解释一下的,是这部分代码:

       for (setno = 0; setno < nr_sets; setno++, nmtd++) {

              pr_debug("initialising set %d (%p, info %p)/n", setno, nmtd, info);

/* 调用init chip去挂载你的nand 驱动的底层函数到nand flash的结构体中,以及设置对应的ecc mode,挂载ecc相关的函数 */

              s3c2410_nand_init_chip(info, nmtd, sets);

/* scan_ident,扫描nand 设备,设置nand flash的默认函数,获得物理设备的具体型号以及对应各个特性参数,这部分算出来的一些值,对于nand flash来说,是最主要的参数,比如nand falsh的芯片的大小,块大小,页大小等。 */

              nmtd->scan_res = nand_scan_ident(&nmtd->mtd,

                                           (sets) ? sets->nr_chips : 1);

 

              if (nmtd->scan_res == 0) {

                     s3c2410_nand_update_chip(info, nmtd);

/* scan tail,从名字就可以看出来,是扫描的后一阶段,此时,经过前面的scan_ident,我们已经获得对应nand flash的硬件的各个参数,然后就可以在scan tail中,根据这些参数,去设置其他一些重要参数,尤其是ecclayout,即ecc是如何在oob中摆放的,最后,再去进行一些初始化操作,主要是根据你的驱动,如果没有实现一些函数的话,那么就用系统默认的。 */

                     nand_scan_tail(&nmtd->mtd);

/* add partion,根据你的nand flash的分区设置,去分区 */

                     s3c2410_nand_add_partition(info, nmtd, sets);

              }

              if (sets != NULL)

                     sets++;

       }

4.       等所有的参数都计算好了,函数都挂载完毕,系统就可以正常工作了。

上层访问你的nand falsh中的数据的时候,通过MTD层,一层层调用,最后调用到你所实现的那些底层访问硬件数据/缓存的函数中。

 

Linuxnand flash驱动编写步骤简介】

关于上面提到的,在nand_scan_tail的时候,系统会根据你的驱动,如果没有实现一些函数的话,那么就用系统默认的。如果实现了自己的函数,就用你的。

估计很多人就会问了,那么到底我要实现哪些函数呢,而又有哪些是可以不实现,用系统默认的就可以了呢。

此问题的,就是我们下面要介绍的,也就是,你要实现的,你的驱动最少要做哪些工作,才能使整个nand flash工作起来。

 

1.       对于驱动框架部分

其实,要了解,关于驱动框架部分,你所要做的事情的话,只要看看三星的整个nand flash驱动中的这个结构体,就差不多了:

static struct platform_driver s3c2410_nand_driver = {

       .probe            = s3c2410_nand_probe,

       .remove         = s3c2410_nand_remove,

       .suspend = s3c24xx_nand_suspend,

       .resume         = s3c24xx_nand_resume,

       .driver           = {

              .name     = "s3c2410-nand",

              .owner    = THIS_MODULE,

       },

};

 

对于上面这个结构体,没多少要解释的。从名字,就能看出来:

1probe就是系统“探测”,就是前面解释的整个过程,这个过程中的多数步骤,都是和你自己的nand flash相关的,尤其是那些硬件初始化部分,是你必须要自己实现的。

2remove,就是和probe对应的,“反初始化”相关的动作。主要是释放系统相关资源和关闭硬件的时钟等常见操作了。

(3)suspendresume,对于很多没用到电源管理的情况下,至少对于我们刚开始写基本的驱动的时候,可以不用关心,放个空函数即可。

 

2.       对于nand flash底层操作实现部分

而对于底层硬件操作的有些函数,总体上说,都可以在上面提到的s3c2410_nand_init_chip中找到:

static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,

                               struct s3c2410_nand_mtd *nmtd,

                               struct s3c2410_nand_set *set)

{

       struct nand_chip *chip = &nmtd->chip;

       void __iomem *regs = info->regs;

 

       chip->write_buf    = s3c2410_nand_write_buf;

       chip->read_buf     = s3c2410_nand_read_buf;

       chip->select_chip  = s3c2410_nand_select_chip;

       chip->chip_delay   = 50;

       chip->priv         = nmtd;

       chip->options    = 0;

       chip->controller   = &info->controller;

 

       switch (info->cpu_type) {

       case TYPE_S3C2410:

/* nand flash控制器中,一般都有对应的数据寄存器,用于给你往里面写数据,表示将要读取或写入多少个字节(byte,u8)/(word,u32) ,所以,此处,你要给出地址,以便后面的操作所使用 */

              chip->IO_ADDR_W = regs + S3C2410_NFDATA;

              info->sel_reg   = regs + S3C2410_NFCONF;

              info->sel_bit  = S3C2410_NFCONF_nFCE;

              chip->cmd_ctrl  = s3c2410_nand_hwcontrol;

              chip->dev_ready = s3c2410_nand_devready;

              break;

。。。。。。

      }

 

       chip->IO_ADDR_R = chip->IO_ADDR_W;

 

       nmtd->info       = info;

       nmtd->mtd.priv       = chip;

       nmtd->mtd.owner    = THIS_MODULE;

       nmtd->set        = set;

 

       if (hardware_ecc) {

              chip->ecc.calculate = s3c2410_nand_calculate_ecc;

              chip->ecc.correct   = s3c2410_nand_correct_data;

/* 此处,多数情况下,你所用的Nand Flash的控制器,都是支持硬件ECC的,所以,此处设置硬件ECC(HW_ECC) ,也是充分利用硬件的特性,而如果此处不用硬件去做的ECC的话,那么下面也会去设置成NAND_ECC_SOFT,系统会用默认的软件去做ECC校验,相比之下,比硬件ECC的效率就低很多,而你的nand flash的读写,也会相应地要慢不少*/

              chip->ecc.mode         = NAND_ECC_HW;

 

              switch (info->cpu_type) {

              case TYPE_S3C2410:

                     chip->ecc.hwctl         = s3c2410_nand_enable_hwecc;

                     chip->ecc.calculate = s3c2410_nand_calculate_ecc;

                     break;

。。。。。

 

              }

       } else {

              chip->ecc.mode         = NAND_ECC_SOFT;

       }

 

       if (set->ecc_layout != NULL)

              chip->ecc.layout = set->ecc_layout;

 

       if (set->disable_ecc)

              chip->ecc.mode     = NAND_ECC_NONE;

}

 

而我们要实现的底层函数,也就是上面蓝色标出来的一些函数而已:

1s3c2410_nand_write_buf s3c2410_nand_read_buf:这是两个最基本的操作函数,其功能,就是往你的nand flash的控制器中的FIFO读写数据。一般情况下,是MTD上层的操作,比如要读取一页的数据,那么在发送完相关的读命令和等待时间之后,就会调用到你底层的read_buf,去nand FlashFIFO中,一点点把我们要的数据,读取出来,放到我们制定的内存的缓存中去。写操作也是类似,将我们内存中的数据,写到Nand FlashFIFO中去。具体的数据流向,参考上面的图4

2s3c2410_nand_select_chip 实现Nand Flash的片选。

3s3c2410_nand_hwcontrol:给底层发送命令或地址,或者设置具体操作的模式,都是通过此函数。

4s3c2410_nand_devreadyNand Flash的一些操作,比如读一页数据,写入(编程)一页数据,擦除一个块,都是需要一定时间的,在命发送完成后,就是硬件开始忙着工作的时候了,而硬件什么时候完成这些操作,什么时候不忙了,变就绪了,就是通过这个函数去检查状态的。一般具体实现都是去读硬件的一个状态寄存器,其中某一位是否是1,对应着是出于“就绪/不忙”还是“忙”的状态。这个寄存器,也就是我们前面分析时序图中的R/B#

5s3c2410_nand_enable_hwecc 在硬件支持的前提下,前面设置了硬件ECC的话,要实现这个函数,用于每次在读写操作前,通过设置对应的硬件寄存器的某些位,使得启用硬件ECC,这样在读写操作完成后,就可以去读取硬件校验产生出来的ECC数值了。

6s3c2410_nand_calculate_ecc:如果是上面提到的硬件ECC的话,就不用我们用软件去实现校验算法了,而是直接去读取硬件产生的ECC数值就可以了。

7s3c2410_nand_correct_data:当实际操作过程中,读取出来的数据所对应的硬件或软件计算出来的ECC,和从oob中读出来的ECC不一样的时候,就是说明数据有误了,就需要调用此函数去纠正错误。对于现在SLC常见的ECC算法来说,可以发现2位,纠正1位。如果错误大于1位,那么就无法纠正回来了。一般情况下,出错超过1位的,好像几率不大。至少我看到的不是很大。更复杂的情况和更加注重数据安全的情况下,一般是需要另外实现更高效和检错和纠错能力更强的ECC算法的。

 

当然,除了这些你必须实现的函数之外,在你更加熟悉整个框架之后,你可以根据你自己的nand flash的特点,去实现其他一些原先用系统默认但是效率不高的函数,而用自己的更高效率的函数替代他们,以提升你的nand flash的整体性能和效率。

 

【引用文章】

1.Brief Intro of Nand Flash

http://hi.baidu.com/serial_story/blog/item/3f1635d1dc041cd7562c84a1.html

2. Samsung的型号为K9G8G08U0MNand Flash的数据手册

要下载数据手册,可以去这里介绍的网站下载:

samsung 4K pagesize SLC Nand Flash K9F8G08U0M datasheet + 推荐一个datasheet搜索的网站

http://hi.baidu.com/serial_story/blog/item/7f25a03def1de309bba167c8.html

3.Nand Falsh Read Operation

http://hi.baidu.com/serial_story/blog/item/f06db3546eced11a3b29356c.html

4. Memory Technology Device (MTD) Subsystem for Linux.

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

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝店铺没有人问怎么办 淘宝申请退款后店铺关闭怎么办 宝贝详情怎么改不了怎么办 改详情页后被删除宝贝怎么办 淘宝网商贷生意不好还不了怎么办 英国遗失在酒店物品怎么办 班福法则首位是0怎么办 同事能力比你强怎么办 新买的木板床响怎么办 笔记本键盘驱动坏了怎么办 云柜快递超时了怎么办 毕业设计被老师发现抄的怎么办 地板颜色太深了怎么办 皮质鞋子破皮了怎么办 吃了蜘蛛丝会怎么办 南京高二分班不公平怎么办? 高中分班考试没考好怎么办 实木门上的伸缩缝太深怎么办 mac点关机没反应怎么办 被压倒扁的易拉罐怎么办 白色车漏底漆了怎么办 客厅对着卧室门怎么办 老公不上进还懒怎么办 二胡按弦手指分不开怎么办 酷塑做完后疼痛怎么办 冷冻治疗后水泡破了怎么办 冷冻治疗的水泡破了怎么办? 冷冻治疗水泡破了怎么办 脚上冷冻后起泡怎么办 刺猴冷冻后起泡怎么办 隔壁太吵怎么办阴招 楼上有小孩太吵怎么办 捷达小水管睹了怎么办 楼房下水管冻了怎么办 一楼地面很潮湿怎么办 新房子地面有裂缝怎么办 地砖下面的下水管漏水怎么办 速冻饺子冻在一起了怎么办 牛排泡水解冻了怎么办 饺子都粘一起了怎么办 把桃子放冷冻了怎么办