这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 啸风的MID拆解进程——“妖怪”现形了,却缺少了那份妩媚

共9条 1/1 1 跳转至

啸风的MID拆解进程——“妖怪”现形了,却缺少了那份妩媚

专家
2012-11-11 16:32:40     打赏
啸风MID的拆解进程

还是把这个拆解活动做成一个进程的形式,先做一个总的进程,便于阅读浏览。

时间 进程名                                               位置
 2012-11-11  MID拆解进程内容规划                                               2
 2012-11-11  初始MID                                               3
 2012-11-11  简单的拆解                                               4
 2012-11-11  显示屏                                                5
 2012-11-23   “妖怪”现形了,却缺少了那份妩媚                                               6
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
 




       




关键词: 啸风     拆解     进程     妖怪     现形     缺少     那份     妩媚    

专家
2012-11-11 16:33:11     打赏
2楼

此次活动主要是对MID进行拆解,我将整个MID里面的模块用框图展示如下图,主要模块有:CPU、WIFI、GPS、3G、电源、重力、影音、存储等模块。后续进程将对这些模块及其他部分进行分析。



专家
2012-11-11 16:51:31     打赏
3楼
 

初识MID

2012-11-09 中午,接到了优速快递的短信,心中甚是欢喜。这一天我们这刚好下着毛毛的细雨,骑着学弟的自行车穿梭在大街小巷,终于来到了这个离我学校3公里的快递公司。签收完快递后,立马打开了包装,看到了跟论坛帖子里一样漂亮的MID,按着电源键,啥反应都没有。算了吧,肯定是没电,回去再弄。

这货拿回来,试用了几分钟就出现了故障,时而白屏,时而没反应。故此就进入了此次活动的主题,果断的拿起工具拆了


白屏咯!!!




复位重启




专家
2012-11-11 18:44:04     打赏
4楼


初步拆解:

好嘛,这家伙,刚还没找到螺丝孔。仔细找找,找到了,卸下螺丝。
话说现在的电子产品的外部包装的机械设计越来越好,如果不要螺丝给固定,还是可以的。

给大家上图,看看里面的部分




这一打开,你啥芯片都别想看见(左边的刚也封起来了)。做的不错啊。看了网友shangziyun的帖子,怎么着,我的跟他还不一样了? 我仔细瞧了瞧,这厮是一个外壳,可以打开的,如下图:


好家伙,里面还有等着我呢!给它来几个特写









好了图也不多贴了,后续对各个模块分析的时候将一一奉上。

现在就是要把这跟窗户式的家伙去除掉。


专家
2012-11-11 19:03:59     打赏
5楼
显示屏

关于大部分模块,shangziyun在他的帖子中都有介绍。遗憾的是他的MID屏烂了。还好,我的没坏,先给大家看看我的屏。

正面:


反面:



此屏为奇美5寸高分屏40pin带触摸,淘宝有卖。具体的datasheet如下:LW500AC9001.pdf
这屏可以找到datasheet,以后可以运用到其他的地方

专家
2012-11-23 13:40:13     打赏
6楼
“妖怪”现形了,却缺少了那份妩媚

        临近毕业了,工作还没着落。EEPW的活动进度也落了不少。 工作也不是一时半会就能找好的先更新下进程再说。

        终于把MID板子的保护罩卸下来了,用烙铁一点一点的翘开的。或许是俺这个莽汉暴力点了,东西倒是卸下来了。再次通电后,MID却没了它原本的功能。害羞了,少了那份妩媚,毕竟俺把它的衣服“脱”掉了。这该是咋好呢? 


先上图看看这“妖怪”:




通电后的没反应,让我很是。先测试下看看,能不能唤醒它沉睡的“记忆”。实在不行,就不要怪我下狠手了。

院士
2012-11-23 15:06:03     打赏
7楼

别灰心~~~


专家
2012-11-23 15:35:45     打赏
8楼
三星NAND Flash K9F2G0800A

MID使用的是三星的NAND Flash K9F2G0800A,见图:




关于NAND Flash  ,我在百度上找到相关的信息:

Nand flash

Nand-flash内存是flash内存的一种,其内部采用非线性宏单元模式,为固态大容量内存的实现提供了廉价有效的解决方案。Nand-flash存储器具有容量较大,改写速度快等优点,适用于大量数据的存储,因而在业界得到了越来越广泛的应用,如嵌入式产品中包括数码相机、MP3随身听记忆卡、体积小巧的U盘等。

简介   NOR和NAND是现在市场上两种主要的非易失闪存技术。Intel于1988年首先开发出NOR flash技术,彻底改变了原先由EPROM和EEPROM一统天下的局面。紧接着,1989年,东芝公司发表了NAND flash结构,强调降低每比特的成本,更高的性能,并且象磁盘一样可以通过接口轻松升级。但是经过了十多年之后,仍然有相当多的硬件工程师分不清NOR和NAND闪存。     相“NAND存储器”经常可以与相“NOR存储器”互换使用。许多业内人士也搞不清 楚NAND闪存技术相对于NOR技术的优越之处,因 为大多数情况下闪存只是用来存储少量的代码并且需要多次擦写,这时NOR闪存更适合一些。而NAND则是高数据存储密度的理想解决方案。     NOR的特点是芯片内执行(XIP, eXecute In Place),这样应用程序可以直接在flash 闪存内运行,不必再把代码读到系统RAM中。NOR的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除 速度大大影响了它的性能。     NAND结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。应用NAND的困难在于flash的管理和需要特殊的系统接口。   NOR与NAND的区别 性能比较   flash闪存是非易失存储器,可以对称为块的存储器单元块进行擦写和再编程。任何 flash器件的写入操作只能在空或已擦除的单元内进行,所以大多数情况下,在进行写入操作之前必须先执行擦除。NAND器件执行擦除 操作是十分简单的,而NOR则要求在进行擦除前 先要将目标块内所有的位都写为1。     由于擦除NOR器件时是以64~128KB的块进行的,执行一个写入/擦除操作的时间为5s ,与此相反,擦除NAND器件是以8~32KB的块进 行的,执行相同的操作最多只需要4ms。     执行擦除时块尺寸的不同进一步拉大了NOR和NAND之间的性能差距,统计表明,对于给定的一套写入操作(尤其是更新小文件时), 更多的擦除操作必须在基于NOR的单元中进行。这样,当选择存储解决方案时,设计师必 须权衡以下的各项因素。     ● NOR的读速度比NAND稍快一些。     ● NAND的写入速度比NOR快很多。     ● NAND的擦除速度远比NOR快。     ● NAND的擦除单元更小,相应的擦除电路更加简单。     ● NAND的实际应用方式要比NOR复杂的多。     ● NOR可以直接使用,并在上面直接运行代码,而NAND需要I/O接口,因此使用时需要驱动。 接口差别   NOR flash带有SRAM接口,有足够的地址引脚来寻址,可以很容易地存取其内部的每 一个字节。     NAND器件使用复杂的I/O口来串行地存取数据,各个产品或厂商的方法可能各不相同 。8个引脚用来传送控制、地址和数据信息。     NAND读和写操作采用512字节的块,这一点有点像硬盘管理此类操作,很自然地,基于NAND的存储器就可以取代硬盘或其他块设备。NOR的特点是芯片内执行(XIP, eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中。     NOR的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响了它的性能。     NAND结构能提供极高的单元密度,可以达到高存储密度,并且写入和擦除的速度也很快。应用NAND的困难在于flash的管理需要特殊的系统接口。   NAND特点 容量和成本   NAND flash的单元尺寸几乎是NOR器件的一半,由于生产过程更为简单,NAND结构可 以在给定的模具尺寸内提供更高的容量,也就 相应地降低了价格。     NOR flash占据了容量为1~16MB闪存市场的大部分,而NAND flash只是用在8~128M B的产品当中,这也说明NOR主要应用在代码存 储介质中,NAND适合于数据存储,NAND在CompactFlash、Secure Digital、PC Cards和M MC存储卡市场上所占份额最大。 物理构成   NAND Flash 的数据是以bit的方式保存在memory cell,一般来说,一个cell 中只能存储一个bit。这些cell 以8个或者16个为单位,连成bit line,形成所谓的byte(x8)/word(x16),这就是NAND Device的位宽。这些Line会再组成Page,(NAND Flash 有多种结构,我使用的NAND Flash 是K9F1208,下面内容针对三星的K9F1208U0M),每页528Bytes(512byte(Main Area)+16byte(Spare Area)),每32个page形成一个Block(32*528B)。具体一片flash上有多少个Block视需要所定。我所使用的三星k9f1208U0M具有4096个block,故总容量为4096*(32*528B)=66MB,但是其中的2MB是用来保存ECC校验码等额外数据的,故实际中可使用的为64MB。     NAND flash以页为单位读写数据,而以块为单位擦除数据。按照这样的组织方式可以形成所谓的三类地址:     Column Address:Starting Address of the Register. 翻成中文为列地址,地址的低8位     Page Address :页地址     Block Address :块地址     对于NAND Flash来讲,地址和命令只能在I/O[7:0]上传递,数据宽度是8位。 可靠耐用性   采用flash介质时一个需要重点考虑的问题是可靠性。对于需要扩展MTBF的系统来说 ,Flash是非常合适的存储方案。可以从寿命(耐用性)、位交换和坏块处理三个方面来比较NOR和NAND的可靠性。     寿命(耐用性)     在NAND闪存中每个块的最大擦写次数是一百万次,而NOR的擦写次数是十万次。NAND     存储器除了具有10比1的块擦除周期优势,典型 的NAND块尺寸要比NOR器件小8倍,每个NAND存储器块在给定的时间内的删除次数要少一 些。     位交换     所有flash器件都受位交换现象的困扰。在某些情况下(很少见,NAND发生的次数要比NOR多),一个比特位会发生反转或被报告反转了。     一位的变化可能不很明显,但是如果发生在一个关键文件上,这个小小的故障可能 导致系统停机。如果只是报告有问题,多读几次 就可能解决了。     当然,如果这个位真的改变了,就必须采用错误探测/错误更正(EDC/ECC)算法。位 反转的问题更多见于NAND闪存,NAND的供应商建 议使用NAND闪存的时候,同时使用EDC/ECC算法。     这个问题对于用NAND存储多媒体信息时倒不是致命的。当然,如果用本地存储设备来存储操作系统、配置文件或其他敏感信息时, 必须使用EDC/ECC系统以确保可靠性。     坏块处理     NAND器件中的坏块是随机分布的。以前也曾有过消除坏块的努力,但发现成品率太低,代价太高,根本不划算。     NAND器件需要对介质进行初始化扫描以发现坏块,并将坏块标记为不可用。在已制 成的器件中,如果通过可靠的方法不能进行这项 处理,将导致高故障率。 易于使用   可以非常直接地使用基于NOR的闪存,可以像其他存储器那样连接,并可以在上面直 接运行代码。     由于需要I/O接口,NAND要复杂得多。各种NAND器件的存取方法因厂家而异。     在使用NAND器件时,必须先写入驱动程序,才能继续执行其他操作。向NAND器件写 入信息需要相当的技巧,因为设计师绝不能向坏 块写入,这就意味着在NAND器件上自始至终都必须进行虚拟映射。 软件支持   当讨论软件支持的时候,应该区别基本的读/写/擦操作和高一级的用于磁盘仿真和 闪存管理算法的软件,包括性能优化。     在NOR器件上运行代码不需要任何的软件支持,在NAND器件上进行同样操作时,通常 需要驱动程序,也就是内存技术驱动程序(MTD ),NAND和NOR器件在进行写入和擦除操作时都需要MTD。     使用NOR器件时所需要的MTD要相对少一些,许多厂商都提供用于NOR器件的更高级软 件,这其中包括M-System的TrueFFS驱动,该驱 动被Wind River System、Microsoft、QNX Software System、Symbian和Intel等厂商所采用。     驱动还用于对DiskOnChip产品进行仿真和NAND闪存的管理,包括纠错、坏块处理和 损耗平衡。(纠正一点:NOR擦除时,是全部写1,不是写0,而且,NOR FLASH SECTOR擦除时间视品牌、 大小不同而不同,比如,4M FLASH,有的SECTOR擦除时间为60ms,而有的需要最大6S。)NOR FLASH的主要供应商是INTEL ,MICRO等厂商,曾经是FLASH的主流产品,但现在被 NAND FLASH挤的比较难受。它的优点是可以直接从FLASH中运行程序,但是工艺复杂,价格比 较贵。     NAND FLASH的主要供应商是SAMSUNG和东芝,在U盘、各种存储卡、MP3播放器里面的都是这种 FLASH,由于工艺上的不同,它比NOR FLASH拥有更大存储容量,而且便宜。但也有缺点,就是     无法寻址直接运行程序,只能存储数据。另外NAND FLASH 非常容易出现坏区,所以需要有校验     的算法。     在掌上电脑里要使用NAND FLASH 存储数据和程序,但是必须有NOR FLASH来启动。除了     SAMSUNG处理器,其他用在掌上电脑的主流处理器还不支持直接由NAND FLASH 启动程序。因此,     必须先用一片小的NOR FLASH 启动机器,在把OS等软件从NAND FLASH 载入SDRAM中运行才行,     挺麻烦的。   相关信息   NAND型闪存以块为单位进行擦除操作。闪存的写入操作必须在空白区域进行,如果目标区域已经有数据,必须先擦除后写入,因此擦除操作是闪存的基本操作。     而SRAM (Static RAM,静态随机存储器) - 此类静态RAM的运行速度非常快,也非常昂贵,其体积相对来说也比较大。今天我们常说的CPU内的一级、二级缓存就是使用了此SRAM。英特尔的 Pentium III Coppermine CPU中结合有256KB的全速二级缓存,这实际上就是一种SRAM。非常不幸得就是 此种SRAM与其"伙伴"DRAM相比非常地昂贵,因此在CPU内只能使用少量的SRAM,以降低处理器的生产成本;不过由于SRAM的特点---高速 度,因此对提高系统性能非常有帮助。处理器内的一级缓存,其运行频率与CPU的时钟同步;而二级缓存可以整合在CPU中,也可以位于如一些Slot-1 CPU的边上。

专家
2012-11-23 15:41:23     打赏
9楼

关于NAND flash K9F2G0800A的操作

转自网友Idle man

S3C2440Nand Flash操作和电路原理(基于K9F2G08U0A)

S3C2440内部集成了一个Nand flash控制器。S3C2440的Nand flash控制器包含了如下的特性:

l 一个引导启动单元

l Nand Flash存储器接口,支持8位或16位的每页大小为256字,512字节,1K字和2K字节的Nand flash

l 软件模式:用户可以直接访问Nand Flash存储器,此特性可以用于Nand Flash存储器的读、擦除和编程。

l S3C2440支持8/16位的Nand Flash存储器接口总线

l 硬件ECC生成,检测和指示(软件纠错)。

l Steppingstone接口,支持大/小端模式的按字节/半字/字访问。

我用的开发板是天嵌的TQ2440,板子用到的Nand Flash是Samsung公司的K9F2G08U0A,它是8位的Nand flash。本文只介绍Nand Flash的电路原理和Nand Flash的读、写、擦除等基本操作,暂不涉及Nand Flash启动程序的问题。

Nand Flash的电路连接如图 1所示:

图 1 Nand Flash电路原理

上图的左边为K9F2G08U0A与2440的连接图,原理方面就不多介绍,去看看datasheet估计就懂得了,右边的部分是S3C2440的Nand控制器的配置。配置引脚NCON,GPG13,GPG14和GPG15用来设置Nand Flash的基本信息,Nand控制器通过读取配置引脚的状态获取外接的Nand Flash的配置信息,图 2是这四个配置引脚的定义:

图 2 Nand控制配置引脚信息

由于K9F2G08U0A的总线宽度为8位,页大小为2048字节,需要5个寻址命令,所以NCON、GPG13和GPG14应该接高电平,GPG15应该接低电平。

K9F2G08U0A没有地址或数据总线,只有8个IO口,这8个IO口用于传输命令、地址和数据。K9F2G08U0A主要以page(页)为单位进行读写,以block(块)为单位进行擦除。每一页中又分为main区和spare区,main区用于正常数据的存储,spare区用于存储一些附加信息,如块好坏的标记、块的逻辑地址、页内数据的ECC校验和等。K9F2G08U0A的存储阵列如图 3所示:

图 3 K9F2G08U0A内部存储阵列

由上图,我们可以知道:K9F2G08U0A的一页为(2K+64)字节(2K表示的是main区容量, 64表示的是spare区容量),它的一块为64页,而整个设备包括了2048个块。这样算下来一共有2112M位容量,如果只算main区容量则有256M字节(即256M×8位)。

图 4 K9F2G08U0A地址序列

要实现用8个IO口来要访问这么大的容量,如图 4所示:K9F2G08U0A规定了用5个周期来实现。第一个周期访问的地址为A0~A7;第二个周期访问的地址为A8~A11,它作用在IO0~IO3上,而此时IO4~IO7必须为低电平;第三个周期访问的地址为A12~A19;第四个周期访问的地址为A20~A27;第五个周期访问的地址为A28,它作用在IO0上,而此时IO1~IO7必须为低电平。前两个周期传输的是列地址,后三个周期传输的是行地址。通过分析可知,列地址是用于寻址页内空间,行地址用于寻址页,如果要直接访问块,则需要从地址A18开始。由于所有的命令、地址和数据全部从8位IO口传输,所以Nand flash定义了一个命令集来完成各种操作。有的操作只需要一个命令(即一个周期)即可,而有的操作则需要两个命令(即两个周期)来实现。K9F2G08U0A的命令说明如图 5所示:

图 5 K9F2G08U0A命令表

为了方便使用,我们宏定义了K9F2G08U0A的常用命令

#define CMD_READ1 0x00 //页读命令周期1

#define CMD_READ2 0x30 //页读命令周期2

#define CMD_READID 0x90 //读ID命令

#define CMD_WRITE1 0x80 //页写命令周期1

#define CMD_WRITE2 0x10 //页写命令周期2

#define CMD_ERASE1 0x60 //块擦除命令周期1

#define CMD_ERASE2 0xd0 //块擦除命令周期2

#define CMD_STATUS 0x70 //读状态命令

#define CMD_RESET 0xff //复位

#define CMD_RANDOMREAD1 0x05 //随意读命令周期1

#define CMD_RANDOMREAD2 0xE0 //随意读命令周期2

#define CMD_RANDOMWRITE 0x85 //随意写命令

接下来介绍几个Nand Flash控制器的寄存器。Nand Flash控制器的寄存器主要有NFCONF(Nand Flash配置寄存器),NFCONT(Nand Flash控制寄存器),NFCMMD(Nand Flash命令集寄存器),NFADDR(Nand Flash地址集寄存器),NFDATA(Nand Flash数据寄存器),NFMECCD0/1(Nand Flash的main区ECC寄存器),NFSECCD(Nand Flash的spare区ECC寄存器),NFSTAT(Nand Flash操作状态寄存器),NFESTAT0/1(Nand Flash的ECC状态寄存器),NFMECC0/1(Nand Flash用于数据的ECC寄存器),以及NFSECC(Nand Flash用于IO的ECC寄存器)。

(1)NFCONF:2440的NFCONF寄存器是用来设置NAND Flash的时序参数TACLS、TWRPH0、TWRPH1。配置寄存器的[3:0]是只读位,用来指示外部所接的Nand Flash的配置信息,它们是由配置引脚NCON,GPG13,GPG14和GPG15所决定的(比如说K9F2G08U0A的配置为NCON、GPG13和GPG14接高电平,GPG15接低电平,所以[3:0]位状态应该是1110)。

(2)NFCONT:用来使能/禁止NAND Flash控制器、使能/禁止控制引脚信号nFCE、初始化ECC。它还有其他功能,在一般的应用中用不到,比如锁定NAND Flash。

(3)NFCMMD:对于不同型号的Flash,操作命令一般不一样。参考前面介绍的K9F2G08U0A命令序列。

(4)NFADDR:当写这个寄存器时,它将对Flash发出地址信号。只用到低8位来传输,所以需要分次来写入一个完整的32位地址,K9F2G08U0A的地址序列在图4已经做了详细说明。

(5)NFDATA:只用到低8位,读、写此寄存器将启动对NAND Flash的读数据、写数据操作。

(6)NFSTAT:只用到位0,用来检测NAND是否准备好。0:busy,1:ready。

NFCONF寄存器使用TACLS、TWRPH0、TWRPH1这3个参数来控制NAND Flash信号线CLE/ALE与写控制信号nWE的时序关系,它们之间的关系如图6和图7所示:

图6 CLE/ALE时序图

图7 nWE和nRE时序图

TACLS为CLE/ALE有效到nWE有效之间的持续时间,TWRPH0为nWE的有效持续时间,TWRPH1为nWE无效到CLE/ALE无效之间的持续时间,这些时间都是以HCLK为单位的。通过查阅K9F2G08U0A的数据手册,我们可以找到并计算与S3C2440相对应的时序:K9F2G08U0A中的Twp与TWRPH0相对应,Tclh与TWRPH1相对应, TACLS应该是与Tcls相对应。K9F2G08U0A给出的都是最小时间, 2440只要满足它的最小时间即可。TACLS、TWRPH0、TWRPH1这三个变量取值大一些会更保险,在这里,这三个值分别取1,2和0。

下面就开始详细介绍K9F2G08U0A的基本操作,包括复位,读ID,页读、写数据,随意读、写数据,块擦除等。

为了更好地应用ECC和使能Nand Flash片选,我们还需要一些宏定义:

#define NF_nFCE_L() {rNFCONT &= ~(1<<1); }

#define NF_CE_L() NF_nFCE_L() //打开nandflash片选

#define NF_nFCE_H() {rNFCONT |= (1<<1); }

#define NF_CE_H() NF_nFCE_H() //关闭nandflash片选

#define NF_RSTECC() {rNFCONT |= (1<<4); } //复位ECC

#define NF_MECC_UnLock() {rNFCONT &= ~(1<<5); } //解锁main区ECC

#define NF_MECC_Lock() {rNFCONT |= (1<<5); } //锁定main区ECC

#define NF_SECC_UnLock() {rNFCONT &= ~(1<<6); } //解锁spare区ECC

#define NF_SECC_Lock() {rNFCONT |= (1<<6); } //锁定spare区ECC

NFSTAT是另一个比较重要的寄存器,它的第0位可以用于判断nandflash是否在忙,第2位用于检测RnB引脚信号:

#define NF_WAITRB() {while(!(rNFSTAT&(1<<0)));} //等待Nand Flash不忙

#define NF_CLEAR_RB() {rNFSTAT |= (1<<2); } //清除RnB信号

#define NF_DETECT_RB() {while(!(rNFSTAT&(1<<2)));}

//等待RnB信号变高,即不忙

NFCMMD,NFADDR和NFDATA分别用于传输命令,地址和数据,为了方便起见,我们可以定义一些宏定义用于完成上述操作:

#define NF_CMD(data) {rNFCMD = (data); } //传输命令

#define NF_ADDR(addr) {rNFADDR = (addr); } //传输地址

#define NF_RDDATA() rNFDATA) //读32位数据

#define NF_RDDATA8() (rNFDATA8) //读8位数据

#define NF_WRDATA(data) {rNFDATA = (data); } //写32位数据

#define NF_WRDATA8(data) {rNFDATA8 = (data); } //写8位数据

首先,是初始化操作

void rNF_Init(void)

{

rNFCONF = (TACLS<<12)|(TWRPH0<<8)|( TWRPH1<<4)|(0<<0);//初始化时序参数

rNFCONT =

(0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0); //非锁定,屏蔽nandflash中断,初始化ECC及锁定main区和spare区ECC,使能nandflash片选及控制器

rNF_Reset();//复位芯片

}

复位操作,写入复位命令

static void rNF_Reset()

{

NF_CE_L(); //打开nandflash片选

NF_CLEAR_RB(); //清除RnB信号

NF_CMD(CMD_RESET); //写入复位命令

NF_DETECT_RB(); //等待RnB信号变高,即不忙

NF_CE_H(); //关闭nandflash片选

}

读取K9F2G08U0A芯片ID的操作如下:时序图在datasheet的figure18。首先需要写入读ID命令(0x90),然后再写入0x00地址,并等待芯片就绪,就可以读取到一共五个周期的芯片ID,第一个周期为厂商ID,第二个周期为设备ID,第三个周期至第五个周期包括了一些具体的该芯片信息,函数如下

static char rNF_ReadID()

{

char pMID;

char pDID;

char cyc3, cyc4, cyc5;

 

NF_nFCE_L(); //打开nandflash片选

NF_CLEAR_RB(); //清RnB信号

NF_CMD(CMD_READID); //读ID命令

NF_ADDR(0x0); //写0x00地址

for ( i = 0; i < 100; i++ );等一段时间

//读五个周期的ID

pMID = NF_RDDATA8(); //厂商ID:0xEC

pDID = NF_RDDATA8(); //设备ID:0xDA

cyc3 = NF_RDDATA8(); //0x10

cyc4 = NF_RDDATA8(); //0x95

cyc5 = NF_RDDATA8(); //0x44

NF_nFCE_H(); //关闭nandflash片选

return (pDID);

}

下面介绍Nand Flash读操作,读操作是以页为单位进行的。如果在读取数据的过程中不进行ECC校验判断,则读操作比较简单,在写入读命令的两个周期之间写入要读取的页地址,然后读取数据即可。如果为了更准确地读取数据,则在读取完数据之后还要进行ECC校验判断,以确定所读取的数据是否正确。

在上文中已经介绍过,Nand Flash的每一页有两区:main区和spare区,main区用于存储正常的数据,spare区用于存储其他附加信息,其中就包括ECC校验码。当我们在写入数据的时候,我们就计算这一页数据的ECC校验码,然后把校验码存储到spare区的特定位置中,在下次读取这一页数据的时候,同样我们也计算ECC校验码,然后与spare区中的ECC校验码比较,如果一致则说明读取的数据正确,如果不一致则不正确。ECC的算法较为复杂,好在S3C2440能够硬件产生ECC校验码,这样就省去了不少的麻烦事。S3C2440既可以产生main区的ECC校验码,也可以产生spare区的ECC校验码。因为K9F2G08U0A是8位IO口,因此S3C2440共产生4个字节的main区ECC码和2个字节的spare区ECC码。在这里我们规定,在每一页的spare区的第0个地址到第3个地址存储main区ECC,第4个地址和第5个地址存储spare区ECC。

产生ECC校验码的过程为:在读取或写入哪个区的数据之前,先解锁该区的ECC,以便产生该区的ECC。在读取或写入完数据之后,再锁定该区的ECC,这样系统就会把产生的ECC码保存到相应的寄存器中。main区的ECC保存到NFMECC0/1中(因为K9F2G08U0A是8位IO口,因此这里只用到了NFMECC0),spare区的ECC保存到NFSECC中。对于读操作来说,我们还要继续读取spare区的相应地址内容,以得到上次写操作时所存储的main区和spare区的ECC,并把这些数据分别放入NFMECCD0/1和NFSECCD的相应位置中。最后我们就可以通过读取NFESTAT0/1(因为K9F2G08U0A是8位IO口,因此这里只用到了NFESTAT0)中的低4位来判断读取的数据是否正确,其中第0位和第1位为main区指示错误,第2位和第3位为spare区指示错误。

下面是一段具体的页读操作程序:

U8 rNF_ReadPage( U32 page_number )

{

U32 i, mecc0, secc;

 

NF_RSTECC(); //复位ECC

NF_MECC_UnLock(); //解锁main区ECC

 

NF_nFCE_L();//使能芯片

NF_CLEAR_RB();//清除RnB

 

NF_CMD(CMD_READ1); //页读命令周期1,0x00

//写入5个地址周期

NF_ADDR(0x00); //列地址A0-A7

NF_ADDR(0x00); //列地址A8-A11

NF_ADDR((addr) & 0xff); //行地址A12-A19

NF_ADDR((addr >> 8) & 0xff); //行地址A20-A27

NF_ADDR((addr >> 16) & 0xff); //行地址A28

 

NF_CMD(CMD_READ2); //页读命令周期2,0x30

 

NF_DETECT_RB(); ////等待RnB信号变高,即不忙

 

for (i = 0; i < 2048; i++)

{

buf[i] = NF_RDDATA8();//读取一页数据内容

}

 

NF_MECC_Lock(); //锁定main区ECC值

NF_SECC_UnLock(); //解锁spare区ECC

 

mecc0=NF_RDDATA(); //读spare区的前4个地址内容,即第2048~2051地址,这4个字节为main区的ECC

//把读取到的main区的ECC校验码放入NFMECCD0/1的相应位置内

rNFMECCD0=((mecc0&0xff00)<<8)|(mecc0&0xff);

rNFMECCD1=((mecc0&0xff000000)>>8)|((mecc0&0xff0000)>>16);

 

NF_SECC_Lock(); //锁定spare区的ECC值

 

secc=NF_RDDATA(); //继续读spare区的4个地址内容,即第2052~2055地址,其中前2个字节为spare区的ECC值

//把读取到的spare区的ECC校验码放入NFSECCD的相应位置内

rNFSECCD=((secc&0xff00)<<8)|(secc&0xff);

NF_nFCE_H(); //关闭nandflash片选

 

//判断所读取到的数据是否正确

if ((rNFESTAT0&0xf) == 0x0)

return 0x66; //正确

else

return 0x44; //错误

}

这段程序是把某一页的内容读取到全局变量数组buffer中。该程序的输入参数直接就为K9F2G08U0A的第几页,例如我们要读取第128064页中的内容,可以调用该程序为:rNF_ReadPage(128064)。由于第128064页是第2001块中的第0页(128064=2001×64+0),所以为了更清楚地表示页与块之间的关系,也可以写为:rNF_ReadPage(2001*64)。

页写操作的大致流程为:在两个写命令周期之间分别写入页地址和数据,当然如果为了保证下次读取该数据时的正确性,还需要把main区的ECC值和spare区的ECC值写入到该页的spare区内。然后我们还需要读取状态寄存器,以判断这次写操作是否正确。下面就给出一段具体的页写操作程序,其中输入参数也是要写入数据到第几页:

U8 rNF_WritePage(U32 page_number)

{

U32 i, mecc0, secc;

U8 stat, temp;

temp = rNF_IsBadBlock(page_number>>6); //判断该块是否为坏块

if(temp == 0x33)

return 0x42; //是坏块,返回

NF_RSTECC(); //复位ECC

NF_MECC_UnLock(); //解锁main区的ECC

NF_nFCE_L(); //打开nandflash片选

NF_CLEAR_RB(); //清RnB信号

 

NF_CMD(CMD_WRITE1); //页写命令周期1

//写入5个地址周期

NF_ADDR(0x00); //列地址A0~A7

NF_ADDR(0x00); //列地址A8~A11

NF_ADDR((page_number) & 0xff); //行地址A12~A19

NF_ADDR((page_number >> 8) & 0xff); //行地址A20~A27

NF_ADDR((page_number >> 16) & 0xff); //行地址A28

 

for (i = 0; i < 2048; i++)//写入一页数据

{

NF_WRDATA8((char)(i+6));

}

NF_MECC_Lock(); //锁定main区的ECC值

mecc0=rNFMECC0; //读取main区的ECC校验码

//把ECC校验码由字型转换为字节型,并保存到全局变量数组ECCBuf中

ECCBuf[0]=(U8)(mecc0&0xff);

ECCBuf[1]=(U8)((mecc0>>8) & 0xff);

ECCBuf[2]=(U8)((mecc0>>16) & 0xff);

ECCBuf[3]=(U8)((mecc0>>24) & 0xff);

NF_SECC_UnLock(); //解锁spare区的ECC

//把main区的ECC值写入到spare区的前4个字节地址内,即第2048~2051地址

for(i=0;i<4;i++)

{

NF_WRDATA8(ECCBuf[i]);

}

NF_SECC_Lock(); //锁定spare区的ECC值

secc=rNFSECC; //读取spare区的ECC校验码

//把ECC校验码保存到全局变量数组ECCBuf中

ECCBuf[4]=(U8)(secc&0xff);

ECCBuf[5]=(U8)((secc>>8) & 0xff);

//把spare区的ECC值继续写入到spare区的第2052~2053地址内

for(i=4;i<6;i++)

{

NF_WRDATA8(ECCBuf[i]);

}

NF_CMD(CMD_WRITE2); //页写命令周期2

delay(1000); //延时一段时间,以等待写操作完成

NF_CMD(CMD_STATUS); //读状态命令

//判断状态值的第6位是否为1,即是否在忙,该语句的作用与NF_DETECT_RB();相同

do{

stat = NF_RDDATA8();

}while(!(stat&0x40));

NF_nFCE_H(); //关闭Nand Flash片选

//判断状态值的第0位是否为0,为0则写操作正确,否则错误

if (stat & 0x1)

{

temp = rNF_MarkBadBlock(page_number>>6);//标注该页所在的块为坏块

if (temp == 0x21)

return 0x43 //标注坏块失败

else

return 0x44; //写操作失败

}

else

return 0x66; //写操作成功

}

该段程序先判断该页所在的坏是否为坏块,如果是则退出。在最后写操作失败后,还要标注该页所在的块为坏块,其中所用到的函数rNF_IsBadBlock和rNF_MarkBadBlock,我们在后面介绍。我们再总结一下该程序所返回数值的含义,0x42:表示该页所在的块为坏块;0x43:表示写操作失败,并且在标注该页所在的块为坏块时也失败;0x44:表示写操作失败,但是标注坏块成功;0x66:写操作成功。

擦除是以块为单位进行的,因此在写地址周期是,只需写三个行周期,并且要从A18开始写起。与写操作一样,在擦除结束前还要判断是否擦除操作成功,另外同样也存在需要判断是否为坏块以及要标注坏块的问题。下面就给出一段具体的块擦除操作程序:

U8 rNF_EraseBlock(U32 block_number)

{

char stat, temp;

 

temp = rNF_IsBadBlock(block_number); //判断该块是否为坏块

if(temp == 0x33)

return 0x42; //是坏块,返回

NF_nFCE_L(); //打开片选

NF_CLEAR_RB(); //清RnB信号

 

NF_CMD(CMD_ERASE1); //擦除命令周期1

//写入3个地址周期,从A18开始写起

NF_ADDR((block_number << 6) & 0xff); //行地址A18~A19

NF_ADDR((block_number >> 2) & 0xff); //行地址A20~A27

NF_ADDR((block_number >> 10) & 0xff); //行地址A28

NF_CMD(CMD_ERASE2); //擦除命令周期2

delay(1000); //延时一段时间

NF_CMD(CMD_STATUS); //读状态命令

//判断状态值的第6位是否为1,即是否在忙,该语句的作用与NF_DETECT_RB();相同

do{

stat = NF_RDDATA8();

}while(!(stat&0x40));

NF_nFCE_H(); //关闭Nand Flash片选

 

//判断状态值的第0位是否为0,为0则擦除操作正确,否则错误

if (stat & 0x1)

{

temp = rNF_MarkBadBlock(page_number>>6); //标注该块为坏块

if (temp == 0x21)

return 0x43 //标注坏块失败

else

return 0x44; //擦除操作失败

}

else

return 0x66; //擦除操作成功

}

该程序的输入参数为K9F2G08U0A的第几块,例如我们要擦除第2001块,则调用该函数为:rNF_EraseBlock(2001)。

K9F2G08U0A除了提供了页读和页写功能外,还提供了页内地址随意读、写功能。页读和页写是从页的首地址开始读、写,而随意读、写实现了在一页范围内任意地址的读、写。随意读操作是在页读操作后输入随意读命令和页内列地址,这样就可以读取到列地址所指定地址的数据。随意写操作是在页写操作的第二个页写命令周期前,输入随意写命令和页内列地址,以及要写入的数据,这样就可以把数据写入到列地址所指定的地址内。下面两段程序实现了随意读和随意写功能,其中随意读程序的输入参数分别为页地址和页内地址,输出参数为所读取到的数据,随意写程序的输入参数分别为页地址,页内地址,以及要写入的数据。

U8 rNF_RamdomRead(U32 page_number, U32 add)

{

NF_nFCE_L(); //打开Nand Flash片选

NF_CLEAR_RB(); //清RnB信号

NF_CMD(CMD_READ1); //页读命令周期1

//写入5个地址周期

NF_ADDR(0x00); //列地址A0~A7

NF_ADDR(0x00); //列地址A8~A11

NF_ADDR((page_number) & 0xff); //行地址A12~A19

NF_ADDR((page_number >> 8) & 0xff); //行地址A20~A27

NF_ADDR((page_number >> 16) & 0xff); //行地址A28

 

NF_CMD(CMD_READ2); //页读命令周期2

NF_DETECT_RB(); //等待RnB信号变高,即不忙

NF_CMD(CMD_RANDOMREAD1); //随意读命令周期1

//页内地址

NF_ADDR((char)(add&0xff)); //列地址A0~A7

NF_ADDR((char)((add>>8)&0x0f)); //列地址A8~A11

NF_CMD(CMD_RANDOMREAD2); //随意读命令周期2

return NF_RDDATA8(); //读取数据

}

U8 rNF_RamdomWrite(U32 page_number, U32 add, U8 dat)

{

U8 temp,stat;

NF_nFCE_L(); //打开Nand Flash片选

NF_CLEAR_RB(); //清RnB信号

NF_CMD(CMD_WRITE1); //页写命令周期1

//写入5个地址周期

NF_ADDR(0x00); //列地址A0~A7

NF_ADDR(0x00); //列地址A8~A11

NF_ADDR((page_number) & 0xff); //行地址A12~A19

NF_ADDR((page_number >> 8) & 0xff); //行地址A20~A27

NF_ADDR((page_number >> 16) & 0xff); //行地址A28

NF_CMD(CMD_RANDOMWRITE); //随意写命令

//页内地址

NF_ADDR((char)(add&0xff)); //列地址A0~A7

NF_ADDR((char)((add>>8)&0x0f)); //列地址A8~A11

 

NF_WRDATA8(dat); //写入数据

NF_CMD(CMD_WRITE2); //页写命令周期2

delay(1000); //延时一段时间

NF_CMD(CMD_STATUS); //读状态命令

//判断状态值的第6位是否为1,即是否在忙,该语句的作用与NF_DETECT_RB();相同

do{

stat = NF_RDDATA8();

}while(!(stat&0x40));

NF_nFCE_H(); //关闭Nand Flash片选

//判断状态值的第0位是否为0,为0则写操作正确,否则错误

if (stat & 0x1)

return 0x44; //失败

else

return 0x66; //成功

}

下面介绍上文中提到的判断坏块以及标注坏块的那两个程序:rNF_IsBadBlock和rNF_MarkBadBlock。在这里,我们定义在spare区的第6个地址(即每页的第2054地址)用来标注坏块,0x44表示该块为坏块。要判断坏块时,利用随意读命令来读取2054地址的内容是否为0x44,要标注坏块时,利用随意写命令来向2054地址写0x33。下面就给出这两个程序,它们的输入参数都为块地址,也就是即使仅仅一页出现问题,我们也标注整个块为坏块。

U8 rNF_IsBadBlock(U32 block)

{

return rNF_RamdomRead(block*64, 2054);

}

U8 rNF_MarkBadBlock(U32 block)

{

U8 result;

result = rNF_RamdomWrite(block*64, 2054, 0x33);

if(result == 0x44)

return 0x21; //写坏块标注失败

else

return 0x60; //写坏块标注成功

}


共9条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]