K9F2808U0A的存储结构如图所示:
图1
K9F1208U0A 的数据是以bit 的方式保存在cell,这些cell 以8 个为单位连成column也是该器件的位宽,这些column每528个为组组成Page.每32page形成block。(如图1)。而528个column又被分为1st half、2nd half和3rd 三部分,其中1st half共256个column,2nd half共256个column,3rd 16个column。
正因为如此K9F2808U0A的地址分为三级:
--Block Address -- Page Address --Column Address
Nand flash 以页为单位读写数据,而以块为单位擦除数据。地址和命令只能在I/O[7:0]上传递,数据宽度是8 位。
A8不参与抵制译码
A[13:9],用来确定page地址
A[23:14]用来确定block地址
地址传送顺序是Column Address,Page Address,Block Address。
由于地址只能在I/O[7:0]上传递,因此,必须采用移位的方式进行。 例如,对于128Mbit的NAND flash,地址范围是0~0xFF_FFFF,只要是这个范围内的数值表示的地址都是有效的。
操作 第1 步是传递column address,就是A[7:0],不需移位即可传递到I/O[7:0]上,而halfpage pointer 即bit8 是由操作指令决定的,即指令决定在哪个halfpage 上进行读写。第2 步就是将NAND_ADDR 右移9 位(因为bit8不参与地址译码),将A[13:9]传到I/O[7:0]上 第3 步将A[23:14]放到I/O 上.因此,整个地址传递过程需要3 步才能完成,即3-step addressing。对于存储空间大于128Mbit的nandflash则需要四步完成,第四步传动地址为A[XX:24].我的板子引脚链接如图2和图3所示.
图2
图3
根据这个可以定义访问地址如下:
#define Nand_RB (0x0400)
#define Nand_CE (0x4000)
#define Nand_CLE (0x04)
#define Nand_ALE (0x08)
#define Nand_IO_DAT (*(volatile unsigned char *)0x02000000)
#define Nand_IO_CMD (*(volatile unsigned char *)(0x02000000|Nand_CLE)) #define Nand_IO_ADR (*(volatile unsigned char *)(0x02000000|Nand_ALE))
下面是程序的源码:
复位:
void Flash_Reset()
{
int i;
NAND_CMD();
Nand_IO_CMD = 0xff;
for (i=0;i<0x3ff;i++);
}
读ID
unsigned int Check_Flash_Id(void)
{
int i;
unsigned int id;
NAND_CMD();
Nand_IO_CMD = 0x90;
NAND_INVALID();//这句不是必须的
NAND_ADR();
Nand_IO_ADR = 0;
NAND_INVALID();
NAND_DAT();
for(i=0;i<10;i++);
id = Nand_IO_DAT<<8;//连续读出两个字节
id += Nand_IO_DAT;
NAND_INVALID();
return id;
}
块擦除:
unsigned char Erase_Cluster(unsigned int block)
{
unsigned int blockPage = (block<<5);
int i;
NAND_CMD();
Nand_IO_CMD = 0x60;
NAND_ADR();
Nand_IO_ADR = blockPage & 0xff;
Nand_IO_ADR = (blockPage>>8) & 0xff;
for(i=0;i<2;i++);
NAND_CMD();
Nand_IO_CMD = 0xd0;
for(i=0;i<3;i++);
NAND_DAT();
WAIT_RB();
NAND_CMD();
Nand_IO_CMD= 0x70;
NAND_DAT();
if (Nand_IO_DAT & 0x1)
{
NAND_INVALID();
return 0;
}
else
{
NAND_INVALID();
return 1;
}
}
页写int WritePage(unsigned int block,unsigned int page,unsigned char *buffer)
{
unsigned int blockPage = (block<<5) + page;
int i;
NAND_CMD();
Nand_IO_CMD = 0x80;
NAND_ADR();
Nand_IO_ADR = 0;
Nand_IO_ADR = blockPage & 0xff;
Nand_IO_ADR = (blockPage>>8) & 0xff;
NAND_DAT();
for(i=0;i<528;i++)
{
Nand_IO_DAT=*buffer++;
}
//WritePage(buffer);
NAND_CMD();
Nand_IO_CMD= 0x10;
for(i=0;i<10;i++);
WAIT_RB(); ////////////
Nand_IO_CMD = 0x70; ///////////////////////////
NAND_DAT();
for(i=0;i<3;i++);
if((Nand_IO_DAT & 0x1))
{
NAND_INVALID();
return 0;
}
else
{
NAND_INVALID();
return 1;
}
}
测试函数如下:
void Read_ID(void)
{
unsigned short id;
id = Check_Flash_Id();
uart_printf("\nNandFLASH Chip's ID is 0x%4x\n",id);
}
void Erase_test(void)
{
uart_printf("\nBegin to erase the last block...");
if(Erase_Cluster(LASTBLOCK))
uart_printf("\nOK! Compeleted.");
else
uart_printf("\nErase error!");
}
void Write_test(void)
{
int i;
unsigned char buffer[528];
for(i=0;i<528;i++)
buffer[i]=0xaa;
uart_printf("\nBegin to Write the first Page of the last block...");
if(WritePage(LASTBLOCK,0,buffer))
uart_printf("\nOK! Compeleted.");
else
uart_printf("\nWrite error!");
}
void Read_test(void)
{
int i,j=0;
unsigned char buffer[528];
uart_printf("\nBegin to Read the first Page of the last block...");
ReadPage(LASTBLOCK,0,buffer);
for(i=0;i<528;i++)
{
if(buffer[i]==0xaa)
j++;
}
uart_printf("\n%4d Bytes verify match!",j);
}
注:由于读写以页为单位,所以选定页后一次可以读写528个字节,但是不建议对第三块进行读写