NAND FLASH的读写操作(硬件原理图分析)

本文详细解析了NANDFlash的读操作流程,包括硬件原理、读操作步骤、内部结构及代码实现。介绍了如何通过控制信号和数据线完成地址、命令和数据的传输,以及如何判断读写操作的完成状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载:NAND FLASH的读操作及原理

硬件原理

上面是我使用的NAND FLASH的硬件原理图,面对这些引脚,很难明白他们是什么含义,下面直接引用韦东山老师的课程中的提问:

NAND FLASH是一个存储芯片

那么: 这样的操作很合理"读地址A的数据,把数据B写到地址A"

 

问1. 原理图上NAND FLASH和S3C2440之间只有数据线,

怎么传输地址?

答1.在DATA0~DATA7上既传输数据,又传输地址

当ALE为高电平时传输的是地址,

 

问2. 从NAND FLASH芯片手册可知,要操作NAND FLASH需要先发出命令

怎么传入命令?

答2.在DATA0~DATA7上既传输数据,又传输地址,也传输命令

当ALE为高电平时传输的是地址,

当CLE为高电平时传输的是命令

当ALE和CLE都为低电平时传输的是数据

 

问3. 数据线既接到NAND FLASH,也接到NOR FLASH,还接到SDRAM、DM9000等等

那么怎么避免干扰?

答3. 这些设备,要访问之必须"选中",

没有选中的芯片不会工作,相当于没接一样

 

问4. 假设烧写NAND FLASH,把命令、地址、数据发给它之后,

NAND FLASH肯定不可能瞬间完成烧写的,

怎么判断烧写完成?

答4. 通过状态引脚RnB来判断:它为高电平表示就绪,它为低电平表示正忙

读操作步骤

由上图的读操作时序图可以得到这么一个读操作的流程:

     (1)发出命令
     (2)发出地址
     (3)读数据

再结合我们的S3C2440芯片,具体操作读NAND FLASH的步骤如下(芯片是通过NAND FLASH控制器进行读写操作的):

NAND FLASH S3C2440

发命令 选中芯片

CLE设为高电平 NFCMMD=命令值

在DATA0~DATA7上输出命令值

发出一个写脉冲

 

发地址 选中芯片 NFADDR=地址值

ALE设为高电平

在DATA0~DATA7上输出地址值

发出一个写脉冲

 

发数据 选中芯片 NFDATA=数据值

ALE,CLE设为低电平

在DATA0~DATA7上输出数据值

发出一个写脉冲

 

读数据 选中芯片 val=NFDATA

发出读脉冲

读DATA0~DATA7的数据

要注意的是,每次操作之前都要写选中NAND FLASH。

接下来我们先了解一下NAND FLASH的内部结构:

       由上图可以看到,每一页的大小为2KB,而且每一页都有64B的OOB(out of bank,主要用于坏块检测)。如果CPU读取NAND FLASH上的第2048个数据,那么将会访问到的是page 1的第一个字节(从page 0开始数),这一点很重要,OOB对于读写操作来说是透明的。另外,发出的地址给NAND FLASH是分为五个周期进行的:

有了这些基础知识后,下面马上开始写代码(下面的代码是用来重定位的作用,也就是从NAND FLASH中读取数据,然后拷贝到目的地址)

void delay_some_time(void)

{

volatile int i;

for(i=0; i<10; i++);

}


void nand_select(void)

{

NFCONT &= ~(1<<1);

}


void nand_deselect(void)

{

NFCONT |= (1<<1);

}


void nand_cmd(unsigned char cmd)

{

NFCMMD = cmd;

delay_some_time(); //经验判断,发出命令后需要等待一些时间

}


void nand_addr(unsigned int addr)

{

unsigned int col = addr % 2048;

unsigned int page = addr / 2048;

//puts("in nand_addr\n\r");



/*芯片手册规定要在5个周期之内分别按下面的规则发出地址*/

NFADDR = col & 0xff;

delay_some_time();

NFADDR = (col >> 8) & 0xff;

delay_some_time();



NFADDR = page & 0xff;

delay_some_time();

NFADDR = (page >> 8) & 0xff;

delay_some_time();

NFADDR = (page >> 16) & 0xff;

delay_some_time();

//puts("leave nand_addr\n\r");

}



void nand_wait_ready(void)

{

/*NFSTAT的最低位为0的时候代表NAND flash正忙*/

while (!(NFSTAT & 1));

}



unsigned char nand_data(void)

{

return NFDATA;

}


void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)

{

int col = addr % 2048; //有可能是从每页的中间开始读

int i = 0;

//puts("in nand_read function\n\r");



/*1. 选中:因为NAND FLASH的数据线是复用的,所以必须先选中*/

nand_select();

//puts("after nand_select\n\r");



while (i<len)

{

/*2. 发出读命令00h*/

nand_cmd(0x00);



/*3. 发出地址(分5步发出)*/

nand_addr(addr);



/*4. 发出读命令30h*/

nand_cmd(0x30);


/*5. 判断状态,确定是否已经读完*/

nand_wait_ready();


/*6. 读数据*/

for(; (col < 2048) && (i < len); col++)

{

buf[i] = nand_data();

i++;

addr++;

}

col = 0;

}

/*7. 取消片选*/

nand_deselect();
}

(1)每次读操作开始前都要先选中芯片

(2)读操作前都要先发出00命令

(3)按照NAND FLASH芯片手册的要求,发出的地址,要分为五个周期,分别发出:列地址的低8位、列地址的高8位、行(页)地址的0~7位、行(页)地址的8~15位和行(页)地址的15~23位。其中,列地址求余后的余数,页地址则是除法得到的商。

(4)之后是发出的30命令(就是这么规定,没有解释)

(5)NAND FLASH读数据也很简单,直接读寄存器NFDATA

(6)读完后,取消片选,整个读操作的流程就算结束

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值