用IO模拟方式读写三星系列的NAND FLASH
时间:03-04
来源:超前科技开发网
点击:
三星系列的NAND FLASH芯片容量从8MB到256MB(最近听说有1G容量的了),对于需要大容量数据存储的嵌入式系统是一个很好的选择,尤其是其接近1MB/元的高性价比,更是普通nor flash无法比拟的。本文以K9F2808U0C为例,采用AVR芯片连接,进行了初步的读写试验,完成了芯片的ID读出功能。
电路连接如下图:
左边是所使用的AVR芯片ATmega16L的局部电路,右边是K9F2808芯片的连接图,数据/地址总线使用ATmega16的PORTB端口连接,其它全部所需信号线使用IO连接,组成了IO模拟方式。
K9F2808芯片的全部命令字如下:
其中,Read1读取的是普通数据存储区域的数据,Read2读取的是每页存储器附加的16Bytes区域的数据;Page Program可以编程一页最大528Bytes的数据,Block Erase擦除指定页面数据,Read Status可以读取芯片状态。
芯片的整个读写时序可以分解为4个基本步骤,即1、命令写入,2、数据写入,3、数据读出,4、地址写入。
1、命令写入时序如下:
对应函数为:
void WriteCmd(unsigned char cmd)
{
nandPortD = 0xFF;
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnCE);
SetLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandnWE);
nandPortO = cmd;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
SetLine(nandSPortO,nandALE);
}
2、数据写入时序如下:
对应函数为:
void WriteByte(unsigned char Wdata)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
nandPortO = Wdata;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
SetLine(nandSPortO,nandnWE);
}
3、数据读出时序如下:
对应函数为:
unsigned char ReadByte(void)
{
unsigned char Rdata;
nandPortD = 0x00;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandnRE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
Rdata = nandPortI;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
SetLine(nandSPortO,nandnRE);
return Rdata;
}
4、地址写入时序如下:
对应函数为:
void WriteByteAdd(unsigned char Add)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandCLE);
SetLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
nandPortO = Add;
SetLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
ClsLine(nandSPortO,nandALE);
}
其余操作方式均从这四种基本操作组合变化而来,适当调用或者重新编写其中的某些语句就能完成全部的K9F2808芯片读写操作。
下面以读K9F2808芯片ID为例调用以上函数完成。
读芯片ID的时序如下图:
实现函数编写为:
void ReadId(unsigned char *ptr)
{
WriteCmd(0x90);
WriteByteAdd(0x00);
*ptr++ = ReadByte();
*ptr = ReadByte();
SetLine(nandSPortO,nandnCE);
}
函数调用后,*ptr的值为0xEC,即厂家代码;*(ptr+1)的值为0x73,即设备代码。
实际在芯片的读写操作中,还要注意对坏扇区进行检错,并将检错结果存入芯片的第一个块中,以确保数据的读写地址均为有效地址。
电路连接如下图:
左边是所使用的AVR芯片ATmega16L的局部电路,右边是K9F2808芯片的连接图,数据/地址总线使用ATmega16的PORTB端口连接,其它全部所需信号线使用IO连接,组成了IO模拟方式。
K9F2808芯片的全部命令字如下:
其中,Read1读取的是普通数据存储区域的数据,Read2读取的是每页存储器附加的16Bytes区域的数据;Page Program可以编程一页最大528Bytes的数据,Block Erase擦除指定页面数据,Read Status可以读取芯片状态。
芯片的整个读写时序可以分解为4个基本步骤,即1、命令写入,2、数据写入,3、数据读出,4、地址写入。
1、命令写入时序如下:
对应函数为:
void WriteCmd(unsigned char cmd)
{
nandPortD = 0xFF;
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnCE);
SetLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandnWE);
nandPortO = cmd;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
SetLine(nandSPortO,nandALE);
}
2、数据写入时序如下:
对应函数为:
void WriteByte(unsigned char Wdata)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
nandPortO = Wdata;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
SetLine(nandSPortO,nandnWE);
}
3、数据读出时序如下:
对应函数为:
unsigned char ReadByte(void)
{
unsigned char Rdata;
nandPortD = 0x00;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandCLE);
ClsLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandnRE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
Rdata = nandPortI;
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
SetLine(nandSPortO,nandnRE);
return Rdata;
}
4、地址写入时序如下:
对应函数为:
void WriteByteAdd(unsigned char Add)
{
nandPortD = 0xFF;
SetLine(nandSPortO,nandnWE);
ClsLine(nandSPortO,nandnCE);
ClsLine(nandSPortO,nandCLE);
SetLine(nandSPortO,nandALE);
ClsLine(nandSPortO,nandnWE);
nandPortO = Add;
SetLine(nandSPortO,nandnWE);
while((nandSPortI & nandRnB) != nandRnB); // wait busy end
ClsLine(nandSPortO,nandALE);
}
其余操作方式均从这四种基本操作组合变化而来,适当调用或者重新编写其中的某些语句就能完成全部的K9F2808芯片读写操作。
下面以读K9F2808芯片ID为例调用以上函数完成。
读芯片ID的时序如下图:
实现函数编写为:
void ReadId(unsigned char *ptr)
{
WriteCmd(0x90);
WriteByteAdd(0x00);
*ptr++ = ReadByte();
*ptr = ReadByte();
SetLine(nandSPortO,nandnCE);
}
函数调用后,*ptr的值为0xEC,即厂家代码;*(ptr+1)的值为0x73,即设备代码。
实际在芯片的读写操作中,还要注意对坏扇区进行检错,并将检错结果存入芯片的第一个块中,以确保数据的读写地址均为有效地址。
- NAND Flash上均匀损耗与掉电恢复在线测试(04-27)
- 基于ClearNAND闪存的系统设计改进方案(01-25)
- NAND Flash管理算法的设计及实现(01-28)
- 基于NAND Flash的转译层的设计(03-11)
- 从Nand特性谈其烧录关键点(05-07)
- 存储器分类汇总,DRAM/EPROM/NAND FLASH这些行业名词你真的知道吗?(07-03)