好文档 - 专业文书写作范文服务资料分享网站

NAND FLASH 内存详解与读写寻址方式

天下 分享 时间: 加入收藏 我要投稿 点赞

#define rNFCMD (*(volatile unsigned char *)0x4e000004) //NADD Flash command

#define rNFADDR (*(volatile unsigned char *)0x4e000008) //NAND Flash address

事实上,当NF_CMD=0x01时,地址寄存器中的第8位(A8)将被设置为1(如上文分 析,A8位不在我们传递的地址中,这个位其实就是硬件电路根据 01h或是00h这两个命令来置高位或是置低位),这样我们传递column_addr的值256随然由于数据溢出变为1,但A8位已经由于NF_CMD =0x01的关系被置为1了,所以我们传到地址寄存器里的值变成了

A0 A1 A2 A3 A4 A5 A6 A7 A8 1 0 0 0 0 0 0 0 1

这8个位所表示的正好是256,这样读操作将从此页的第256号byte(2nd half的第0号byte)开始读取数据。 nand_flash.c中包含3个函数

void nf_reset(void); void nf_init(void);

void nf_read(unsigned int src_addr,unsigned char *desc_addr,int size);

nf_reset()将被nf_init()调用。nf_init()是nand_flash的初始化函数,在对nand flash进行任何操作之前,nf_init()必须被调用。

nf_read(unsigned int src_addr,unsigned char *desc_addr,int size);为读函数,src_addr是nand flash上的地址,desc_addr是内存地址,size是读取文件的长度。

在nf_reset和nf_read函数中存在两个宏 NF_nFCE_L(); NF_nFCE_H();

你可以看到当每次对Nand Flash进行操作之前NF_nFCE_L()必定被调用,操作结束之时NF_nFCE_H()必定被调用。这两个宏用于启动和关闭Flash芯片的工作(片选/取消片选)。至于nf_reset()中的

rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

这一行代码是对NandFlash的控制寄存器进行初始化配置,rNFCONF是Nand Flash的配置寄存器,各个位的具体功能请参阅s3c2410数据手册。

现在举一个例子,假设我要从Nand Flash中的第5000字节处开始读取1024个字节到内存的0x30000000处,我们这样调用read函数

nf_read(5000, 0x30000000,1024); 我们来分析5000这个src_addr. 根据

column_addr=src_addrQ2; page_address=(src_addr>>9); 我们可得出column_addr=5000Q2=392 page_address=(5000>>9)=9

于是我们可以知道5000这个地址是在第9页的第392个字节处,于是我们的nf_read函数将这样发送命令和参数

column_addr=5000Q2; >page_address=(5000>>9);

NF_CMD=0x01; 从2nd half开始读取

NF_ADDR= column_addr &0xff; 1st Cycle NF_ADDR=page_address&0xff; 2nd.Cycle NF_ADDR=(page_address>>8)&0xff; 3rd.Cycle NF_ADDR=(page_address>>16)&0xff; 4th.Cycle

向NandFlash的命令寄存器和地址寄存器发送完以上命令和参数之后,我们就可以从rNFDATA寄存器(NandFlash数据寄存器)读取数据了.

我用下面的代码进行数据的读取. for(i=column_addr;i<512;i++) {

*buf++=NF_RDDATA(); }

每当读取完一个Page之后,数据指针会落在下一个Page的0号Column(0号Byte).

下面是源代码: /*

http://www.another-prj.com/ author: caiyuqing

本代码只属于交流学习,不得用于商业开发 */

#include \#include \

static unsigned char seBuf[16]={0xff};

//--------------------------------------------------------------------------------------

unsigned short nf_checkId(void) {

int i;

unsigned short id;

NF_nFCE_L(); //chip enable

NF_CMD(0x90); //Read ID NF_ADDR(0x0);

for(i=0;i<10;i++); //wait tWB(100ns)

id=\ id|=NF_RDDATA(); // Devide code(K9S1208V:0x76)

NF_nFCE_H(); //chip enable return id; }

//--------------------------------------------------------------------------------------

static void nf_reset(void) {

int i;

NF_nFCE_L(); //chip enable NF_CMD(0xFF); //reset command for(i=0;i<10;i++); //tWB = 100ns. NF_WAITRB(); //wait 200~500us; NF_nFCE_H(); //chip disable }

//--------------------------------------------------------------------------------------

void nf_init(void) {

rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

// 1 1 1 1 1 xxx r xxx, r xxx

// En r r ECCR nFCE=\tACLS tWRPH0 tWRPH1

nf_reset(); }

//--------------------------------------------------------------------------------------

void nf_read(unsigned int src_addr,unsigned char *desc_addr,int size)

{

int i;

unsigned int column_addr = src_addr % 512; // column address

unsigned int page_address = (src_addr >> 9); // page addrress

unsigned char *buf = desc_addr;

while((unsigned int)buf < (unsigned int)(desc_addr) + size) {

NF_nFCE_L(); // enable chip

/*NF_ADDR和NF_CMD为nand_flash的地址和命令寄存器的解引用*/

if(column_addr > 255) // 2end halft NF_CMD(0x01); // Read2 command. cmd 0x01: Read command(start from 2end half page)

else

NAND FLASH 内存详解与读写寻址方式

#definerNFCMD(*(volatileunsignedchar*)0x4e000004)//NADDFlashcommand#definerNFADDR(*(volatileunsignedchar*)0x4e000008)//NANDFlashaddress事实
推荐度:
点击下载文档文档为doc格式
6s86y9brlh9jajr89mbv
领取福利

微信扫码领取福利

微信扫码分享