网站首页  |   业界社区  |  电信社区  |  技术社区   |  极客社区  |  游戏社区  |  生活社区   |   科技博客  |   同事录
TechWeb-技术社区


标题: [转贴] NandFlash读取操作
bika
TW金牌会员
Rank: 6Rank: 6



UID 138192
精华 27
积分 1720
帖子 941
阅读权限 70
注册 2008-7-23
状态 离线
发表于 2008-8-25 16:34 资料 短消息 加为好友 添加 bika 为MSN好友 通过MSN和 bika 交谈
NandFlash读取操作

我的板子上使用的是SAMSUNG的K9F1208U0B,下面我将对此型号的NandFlash读取操作做一个讲解。
6^,h,{*x+|1M&|(R$E4fTechWeb-技术社区首先我们先从物理结构上来了解这颗芯片,结构图如下所示TechWeb-技术社区4\ p t1M"P

&`8]9o4x9V%I正如硬盘的盘片被分为磁道,每个磁道又被分为若干扇区,一块Nand Flash被分为若干Block,每个Block又被分为若干Page。由上图我们可以知道flash中
$W+p"U*f'N-Otech.techweb.com.cnByte(字节),Page(页),Block(块)3个单位之间的关系为 :
,[9G5j(b9e)[1{1 Page =512 Bytes Data Field+ 16 Bytes Spare Field tech.techweb.com.cn)o2H,U2}6]1b:R
1 Blcok=32 Pages"o3p;H(z1K)F)b2V
我们讨论的K9F1208U0B总共有4096 个Blocks,故我们可以知道这块flash的容量为4096 *(32 *528)= 69206016 Bytes = 66 MB
5f5?*F:p(q0A+E7V4D但事实上每个Page上的最后16Bytes是用于存贮检验码用的,并不能存放实际的数据,所以实际上我们可以操作的芯片容量为4096 *(32 *512) = 67108864 Bytes = 64 MB由上图所示,1个Page总共由528 Bytes组成,这528个字节按顺序由上而下以列为单位进行排列(1列代表一个Byte。第0行为第0 Byte ,第1行为第1 Byte,以此类推,每个行又由8个位组成,每个位表示1个Byte里面的1bit)。这528Bytes按功能分为两大部分,分别是Data Field和Spare Field,其中Spare Field占528Bytes里的16Bytes,这16Bytes是用于在读写操作的时候存放校验码用的,一般不用做普通数据的存储区,除去这 16Bytes,剩下的512Bytes便是我们用于存放数据用的Data Field,所以一个Page上虽然有528个Bytes,但我们只按512Bytes进行容量的计算。
1E;z(P7h&W#YData Field按位置关系又可分为两个部分,分别称为1st half与2nd half,每个half各占256个bytes。或许你会感到纳闷,为什么要把DataField分为两个部分?把他们看做一个整体进行操作不就好了吗?呵呵,凡事都有因果,这么分块自然有它的道理所在,但现在还不是告诉你答案的时候。我们还是先讨论一下它的操作吧。对K9F1208U0B的操作是通过向 Nand Flash命令寄存器(对于s3c2410来说此寄存器为NFCMD,内存映射地址为0x4e000004)发送命令队列进行的,为什么说是命令队列?就是因为要完成某个操作的时候发送的不是一条命令,而是连续几条命令或是一条命令加几个参数$z2N4];{$P(x1h"N2E:n
下面是K9F1208U0B的操作命令集:
"c+?7R2N*u!k#B.Q
.v.v)a3b3j,A&} ?TechWeb-技术社区读命令有两个,分别是 Read1,Read2其中Read1用于读取Data Field的数据,而Read2则是用于读取Spare Field的数据。对于Nand Flash来说,读操作的最小操作单位为Page,也就是说当我们给定了读取的起始位置后,读操作将从该位置开始,连续读取到本Page的最后一个 Byte为止(可以包括Spare Field)Nand Flash的寻址Nand Flash的地址寄存器把一个完整的Nand Flash地址分解成Column Address与Page Address.进行寻址/F&T"y,u0Q.B
Column Address: 列地址。Column Address其实就是指定Page上的某个Byte,指定这个Byte其实也就是指定此页的读写起始地址。
9^2P/t0R#o4s9B"J4CPaage Address:页地址。由于页地址总是以512Bytes对齐的,所以它的低9位总是0。确定读写操作是在Flash上的哪个页进行的。
5U$R*K/X*t程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛Read1命令
2i6?;A9p:O&p#OTechWeb-技术社区当我们得到一个Nand Flash地址src_addr时我们可以这样分解出Column Address和Page Address)Y$m4_,d"O*z/E)g&A2j
column_addr=src_addr%512;                         // column address
2X$m2M*l#V'`tech.techweb.com.cnpage_address=(src_addr>>9);                       // page addresstech.techweb.com.cn3s;G$T*h.K1B7~2p!^
也可以这么认为,一个Nand Flash地址的A0~A7是它的column_addr,A9~A25是它的Page Address。(注意地址位A8并没有出现,也就是A8被忽略,在下面你将了解到这是什么原因)9E+W9P%X.s0C
Read1命令的操作分为4个Cycle,发送完读命令00h或01h(00h与01h的区别请见下文描述)之后将分4个Cycle发送参数, 1st.Cycle是发送Column Address。2nd.Cycle ,3rd.Cycle和4th.Cycle则是指定Page Address(每次向地址寄存器发送的数据只能是8位,所以17位的Page Address必须分成3次进行发送.4个Cycle见下图所示程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛5_/Y5c4}5?"i-X+r:Z

0J#s:Q5g;{6k.y0@TechWeb-技术社区你是否还记得我上文提到过的Data Field被分为1st half 和2end half两个部分?而从上面的命令集我们看到Read1的命令里面出现了两个命令选项,分别是00h和01h。这里出现了两个读命是否令你意识到什么呢?是的,00h是用于读写1st half的命令,而01h是用于读取2nd half的命令。现在我可以结合上图给你说明为什么K9F1208U0B的DataField被分为2个half了。
.a7i2{-c.}tech.techweb.com.cn如上文我所提及的,Read1的1st.Cycle是发送Column Address,假设我现在指定的Column Address是0,那么读操作将从此页的第0号Byte开始一直读取到此页的最后一个Byte(包括Spare Field),如果我指定的Column Address是127,情况也与前面一样,但不知道你发现没有,用于传递Column Address的数据线有8条(I/O0~I/O7,对应A0~A7,这也是A8为什么不出现在我们传递的地址位中),也就是说我们能够指定的 Column Address范围为0~255,但不要忘了,1个Page的DataField是由512个Byte组成的,假设现在我要指定读命令从第256个字节处开始读取此页,那将会发生什么情景?我必须把Column Address设置为256,但Column Address最大只能是255,这就造成数据溢出。。。正是因为这个原因我们才把Data Field分为两个半区,当要读取的起始地址(Column Address)在0~255内时我们用00h命令,当读取的起始地址是在256~511时,则使用01h命令.假设现在我要指定从第256个byte开始读取此页,那么我将这样发送命令串tech.techweb.com.cn;j8I/|6P9f
column_addr=256;
%C.J"F$o&o1o9P ~ RNF_CMD=0x01;                                        从2nd half开始读取
)Z-Y9c8d3M,B'D(e"P程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛NF_ADDR=column_addr&0xff;                       1st Cycle
1^5R1s3M:?;C8C8YNF_ADDR=page_address&0xff;                      2nd.Cycle程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛2a-c4A+_-~/h;j"H0I0A
NF_ADDR=(page_address>>8)&0xff;             3rd.CycleTechWeb-技术社区:})M!}9Z+G6t"u4{7a7y)M
NF_ADDR=(page_address>>16)&0xff;           4th.Cycle$}:^.f3m%x6K-l*\7q0?)m
其中NF_CMD和NF_ADDR分别是NandFlash的命令寄存器和地址寄存器的地址解引用,我一般这样定义它们,TechWeb-技术社区;[8J:G:}-q%t!}
#define rNFCMD        (*(volatile unsigned char *)0x4e000004)        //NADD Flash command
2W%Y/j)c3i*_1nTechWeb-技术社区#define rNFADDR        (*(volatile unsigned char *)0x4e000008)        //NAND Flash address/V7G'm!{5j+e0E#` O&C
事实上,当NF_CMD=0x01时,地址寄存器中的第8位(A8)将被设置为1(如上文分析,A8位不在我们传递的地址中,这个位其实就是硬件电路根据 01h或是00h这两个命令来置高位或是置低位),这样我们传递column_addr的值256随然由于数据溢出变为1,但A8位已经由于NF_CMD =0x01的关系被置为1了,所以我们传到地址寄存器里的值变成了
!n4r)K6a)v程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛A0  A1  A2  A3  A4  A5  A6  A7  A8+M.m;b)x;o
1     0    0    0    0     0    0    0    1
&Y8h0g9b%_(E7J0}3MTechWeb-技术社区这8个位所表示的正好是256,这样读操作将从此页的第256号byte(2nd half的第0号byte)开始读取数据。
8P)@1Y"q/~&O7F)lRead21g1{1S#^.k
Read2则是指定读取Spare Field的内容-j&E*z.\1P&J'R8Y'f.Z
其实Read1和Read2都是读命令,他们的区别相当于对一个读指针进行不同区域的定位。如图所示
+~&n1q:H1L,}+h*j$O(u%}-vtech.techweb.com.cn
)B(t(`"E;F/^$y程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛nand_flash.c中包含3个函数tech.techweb.com.cn,y(D*F'O/W2H#I
void nf_reset(void);
L6\1|$?)^4N.g程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛void nf_init(void);tech.techweb.com.cn-s!^#w/p;b&b
void nf_read(unsigned int src_addr,unsigned  char *desc_addr,int size);TechWeb-技术社区+D,a%Y,d1H'}1b;?
nf_reset()将被nf_init()调用。nf_init()是nand_flash的初始化函数,在对nand flash进行任何操作之前,nf_init()必须被调用。:f.V5D/L+q3G
nf_read(unsigned int src_addr,unsigned  char *desc_addr,int size);为读函数,src_addr是nand flash上的地址,desc_addr是内存地址,size是读取文件的长度。+K+{4y2r6H3u/[/d,B1A2M
在nf_reset和nf_read函数中存在两个宏TechWeb-技术社区1W&I5a1b;k7^&[
NF_nFCE_L();
.i(r$H6]0X4f.RNF_nFCE_H();
9a9y.l$M!Ktech.techweb.com.cn你可以看到当每次对Nand Flash进行操作之前NF_nFCE_L()必定被调用,操作结束之时NF_nFCE_H()必定被调用。这两个宏用于启动和关闭Flash芯片的工作(片选/取消片选)。至于nf_reset()中的!{1J4M9[!b
rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);;W)M8m1B3X.x+z.H#S/b9F
这一行代码是对NandFlash的控制寄存器进行初始化配置,rNFCONF是Nand Flash的配置寄存器,各个位的具体功能请参阅s3c2410数据手册。
+P4k%r6D"g {"x:Jtech.techweb.com.cn现在举一个例子,假设我要从Nand Flash中的第5000字节处开始读取1024个字节到内存的0x30000000处,我们这样调用read函数
"j%z0E$^;P(u5C1Etech.techweb.com.cnnf_read(5000, 0x30000000,1024);
,}*l#O$?'i#M+j:?,X我们来分析5000这个src_addr.
,g;i#L9z+R根据tech.techweb.com.cn"x!U4k M&G3?
column_addr=src_addr%512;        
1R)s#v#t6q-utech.techweb.com.cnpage_address=(src_addr>>9);      
&u7b(K'\+R%z'm3A7N8j I;W2hTechWeb-技术社区我们可得出column_addr=5000%512=392程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛+K;@9\1K#L6]
page_address=(5000>>9)=9
1O*|*f)R0^1c4d于是我们可以知道5000这个地址是在第9页的第392个字节处,于是我们的nf_read函数将这样发送命令和参数-f1Q*A0J!x1@
column_addr=5000%512;
0d/Y0^;n,R1z!p"\>page_address=(5000>>9);!T4w(C%g!p1w%{7?+h-x
NF_CMD=0x01;                                           从2nd half开始读取程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛2w*l9i#_-n/D%l3b9E:C)C
NF_ADDR= column_addr &0xff;                     1st Cycle
%Z.?$W4l1^(|-GNF_ADDR=page_address&0xff;                      2nd.Cycletech.techweb.com.cn9~"P,\*_!i7o
NF_ADDR=(page_address>>8)&0xff;             3rd.Cycle'[6a g3I6u"[2x'q
NF_ADDR=(page_address>>16)&0xff;           4th.Cycle
#I.M$H8j7n1qtech.techweb.com.cn向NandFlash的命令寄存器和地址寄存器发送完以上命令和参数之后,我们就可以从rNFDATA寄存器(NandFlash数据寄存器)读取数据了.
0Z/\8\/n)C7M(|,r我用下面的代码进行数据的读取.
0R1P5^*i K$u*Sfor(i=column_addr;i<512;i++)
6r2h:Y8E/p-m4|'h.q3]程序开发,操作系统,服务器,源码下载,Linux,Unix,BSD,PHP,Apach,asp,下载,源码,黑客,安全,技术社区,技术论坛{2c,r:V9y1h(n"m4c8H-l
        *buf++=NF_RDDATA();
#n*v*c-W,|3V}tech.techweb.com.cn8y$@3V J+E+W,_
每当读取完一个Page之后,数据指针会落在下一个Page的0号Column(0号Byte).

引用 回复 顶部
查看积分策略说明快速回复主题
选项 标题 Smilies
禁用 URL 识别
禁用 Smilies
禁用 Discuz!代码
使用匿名发帖
使用个人签名
接收新回复邮件通知
内容





当前时区 GMT+8, 现在时间是 2008-11-23 08:20
京ICP证060517号

本论坛支付平台由支付宝提供
携手打造安全诚信的交易社区 Powered by Discuz! 5.5.0 © 2001-2008 Comsenz Inc.
Processed in 0.036751 second(s), 7 queries

清除 Cookies - 联系我们 - TechWeb.com.cn - Archiver - WAP