一般对于某一类的NAND FLASH,在其内部都会保存自身相关的一些信息,如制造商码,产品码以及产品内部信息(如页大小)等。在一般系统设计过程中,就是根据这些信息来设计驱动程序。例如,先读取产品码,根据不同的产品码调用不同的驱动程序,也就是所谓的支持多种NAND FLASH启动。
这些信息一般在数据手册上会有相关的数据。基本流程:
(1)发送读ID命令。(2)发送地址0。 (3)延时一会儿。(4)读取5个字节的ID即可。
点击(此处)折叠或打开
- void NF_ReadID(unsigned char *buf)
- {
- int i;
- NF_Enable();
- NF_Enable_RB();
- NF_Send_Cmd(CMD_READID);// read id command
- NF_Send_Addr(0x0);
- for ( i = 0; i < 100; i++ );//延时,有个时间tAR
- *buf = NF_Read_Byte();
- *(buf+1)= NF_Read_Byte();
- *(buf+2)= NF_Read_Byte();
- *(buf+3)= NF_Read_Byte();
- *(buf+4)= NF_Read_Byte();
- NF_Disable();
- }
NAND FLASH的型号K9F2G08U0B就支持随机读写,也就是支持单字节读写。随机写操作基本流程:
(1)发送页写入命令0x80。(2)发送页地址。(3)发送随机写发起命令0x85。(4)发送页内地址。(5)发送随机写确认命令0x10,NAND FLASH收到该命令。(6)检测忙信号,等待数据写入完成。
注意:因为页地址指的是该页距离第0块第0页的绝对地址,所以需要5个地址周期(NAND FLASH 5地址周期)。页的绝对地址的计算方法与前文讲的一致,即页的绝对地址=块号*64+页号,第2次发送地址时,该地址是所写入的数据在该页中的地址,因为每一页大小是2K+64字节,所以,地址线需要A0~A11,因此需要2个地址周期。
随机读操作基本流程:
随机读操作基本流程:
(1)发送页读取命令0x00。
(2)发送页地址。
(3)发送页读取确认命令0x30,NAND FLASH会自动将该页数据读取到内部的数据寄存器中。
(4)发送随机读发起命令0x05。
(5)发送页内地址。
(6)发送随机读确认命令0xE0。
(7) 检测忙信号,等待数据写入完成。
在nand.h中增加随机读,写操作命令的宏定义,同时增加对随机读,写函数的声明:
点击(此处)折叠或打开
- #define CMD_RANDOMREAD1 0x05 //随意读命令周期1
- #define CMD_RANDOMREAD2 0xE0 //随意读命令周期2
- #define CMD_RANDOMWRITE 0x85 //随意写命令
- extern unsigned char NF_RamdomRead(unsigned int block,unsigned int page,unsigned int add);
- extern unsigned char NF_RamdomWrite(unsigned int block,unsigned int page,unsigned int add,unsigned char dat) ;
在nand.c文件中增加上述两个函数:
点击(此处)折叠或打开
- unsigned char NF_RamdomRead(unsigned int block, unsigned int page, unsigned int add)
- {
- unsigned char buf ;
- unsigned int page_number = (block<<6) + page;
- NF_Reset();
- NF_Enable();
- NF_Enable_RB();
- NF_Send_Cmd(CMD_READ1);
- NF_Send_Addr(0x00);
- NF_Send_Addr(0x00);
- NF_Send_Addr((page_number) & 0xff);
- NF_Send_Addr((page_number >> 8) & 0xff);
- NF_Send_Addr((page_number >> 16) & 0xff);
- NF_Send_Cmd(CMD_READ2); //页读命令周期2:0x30
- NF_Check_Busy();
- NF_Send_Cmd(CMD_RANDOMREAD1);
-
- NF_Send_Addr((char)(add&0xff));
- NF_Send_Addr((char)((add>>8)&0x0f));
- NF_Send_Cmd(CMD_RANDOMREAD2);
- NF_Check_Busy();
- buf = NF_Read_Byte() ;
- NF_Disable(); //关闭片选
- return buf; //读取数据
- }
- unsigned char NF_RamdomWrite(unsigned int block,unsigned int page, unsigned int add, unsigned char dat)
- {
- unsigned int page_number = (block<<6)+page;//计算页的绝对地址
- NF_Enable();//打开NAND FLASH
- NF_Enable_RB(); //开启忙信号检测功能
-
- NF_Send_Cmd(CMD_WRITE1);//发送页写入命令0x80
- NF_Send_Addr(0x00); //发送页绝对地址
- NF_Send_Addr(0x00);
- NF_Send_Addr((page_number) & 0xff);
- NF_Send_Addr((page_number >> 8) & 0xff);
- NF_Send_Addr((page_number >> 16) & 0xff);
- NF_Send_Cmd(CMD_RANDOMWRITE);
- NF_Send_Addr((char)(add&0xff));
- NF_Send_Addr((char)((add>>8)&0x0f));
- NF_Send_Data(dat);
- NF_Send_Cmd(CMD_WRITE2);
- NF_Check_Busy();
- NF_Disable();
- }