嵌入式bootloader开发Tiny6410(7)

NAND Flash读写擦除操作实现

概要:

本节主要记录开发Tiny6410自带的NAND FLASH的过程,实现了NAND FLASH的擦除,读写数据功能,但都只是简单的实现而已,并没有做精细而完整的实现,毕竟只是想学原理。

前言:

工欲善其事,必先利其器。在做开发之前,必须保证良好的环境和设备,笔者所使用的tiny6410光盘中自带的uboot版本比较老,而且其并不支持MLC2的读写操作,但是之前并不知道,写了很多次,但是总是写不到NAND FLASH中去,还以为是NAND FLASH设备的坏块太多,各种原因各种奇葩猜想,还好,最后时刻想起了友善之臂的官网,无意间看到了uboot的某一版的发行注释中写着实现了MLC2的读写,啊。。。。。有点怒了。。。。竟然是使用的uboot的问题,立即马上下载,然后烧录进去,重写NAND FLASH,写入成功!!!

为了方便,现将新版的uboot和System.map文件共享出来,版权属于友善之臂公司。

uboot-ram256M nand-flash版 与 System.map文件

免费下载地址在

用户名与密码都是

具体下载目录在 /2014年资料/2月/18日/嵌入式bootloader开发Tiny6410

下载方法见

----- ----- ----------  ----- ----- 分割线 ----- ----- ----------  -----

详细的有关NAND FLASH设备的介绍以及一些常识请自行百度或者直接查阅S3C6410数据手册和相应的NAND FLASH数据手册,本文中以Tiny6410中使用的三星公司产的MLC的NAND FLASH芯片K9GAG08U0E(2GB MLC)为例。

具体NAND FLASH的接口电路如下:

嵌入式bootloader开发Tiny6410

LDATA0~LDATA7是I/O口,传输数据、命令或者地址

FWEn:NAND FLASH写数据信号,低有效

FREn:NAND FLASH读数据信号,低有效

FCLE:命令锁存信号

FALE:地址锁存信号

RnB:忙或准备好状态标志位

S3C6410本身集成有NAND FLASH控制器,若要使用只需进行相应的配置即可。

相关的寄存器如下:

//nand flash K9GAG08U0E
#define Base 0x70200000
#define NFCONF (*(volatile unsigned long *)(Base + 0x00))
#define NFCONT (*(volatile unsigned long *)(Base + 0x04 ))
#define NFCMMD (*(volatile unsigned char *)(Base + 0x08 ))
#define  NFADDR (*(volatile unsigned char *)(Base + 0x0c))
#define  NFDATA (*(volatile unsigned char *)(Base + 0x10))<PRE class=cpp>#define  NFSTAT (*(volatile unsigned long *)(Base + 0x28))</PRE>

NAND FLASH controller的初始化主要有:

1.初始化NFCONF,配置TACLS 、TWRPH0、TWRPH1 等。

2.初始化NFCONT,使能NAND FLASH控制器

嵌入式bootloader开发Tiny6410

嵌入式bootloader开发Tiny6410

具体代码如下:

void nand_init(){
        reset();//无关紧要,要不要都可以

NFCONF &=~((0x7<<4)|(0x7<<8)|(0x7<<12)|(1<<30));
        NFCONF |=((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4));

NFCONT |= 1 ;// enable controller

}

读操作的流程如下:

1.片选有效

2.发送命令0x00H

3.发送地址信号

4.发送命令0x30h

5.检测ready/busy状态标志位,若不忙,读取指定字节的数据

6.拉高片选信号,使无效

具体代码实现如下:

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

NFCONT &= ~(1<<1);//片选有效
        NFCMMD = 0x00;  //read 1 circle
        get_addr(addr);
        NFCMMD = 0x30;//read 2 circle
        volatile int i; 
        while(!(NFSTAT & 1))    //wait until ready
                ;
        for(i=0;i<PAGE_SIZE;++i)//read a page
                buf[i]=NFDATA;
        NFCONF |= (1<<1);//拉高
}

写操作的流程如下:

1.片选有效

2.发送命令0x80

3.发送地址信号

4.发送命令0x10

5.检测ready/busy状态标志位,若不忙,读取指定字节的数据

6.拉高片选信号,使无效

具体代码实现如下:

void nand_write(unsigned long addr,char *buf,int len)
{
        volatile int i; 
        NFCONT &= ~(1<<1);//片选有效
        NFCMMD = 0x80;  //write 1 circle
        get_addr(addr);
        for(i=0;i<len;++i)//write a page
                NFDATA=buf[i];
        for(i=len;i<PAGE_SIZE;++i)
                NFDATA = 0xff;

NFCMMD = 0x10;//write 2 circle
        while(!(NFSTAT & 1))    //wait until ready
                ;
        show("nand write ok!\n");

NFCONF |= (1<<1);//拉高
}

擦除操作的流程如下:

1.片选有效

2.发送命令0x60

3.发送地址信号(注意这里的地址是页号

4.发送命令0xd0

5.检测ready/busy状态标志位,若不忙,读取指定字节的数据

6.拉高片选信号,使无效

void nand_erase(unsigned long addr)
{

volatile int i,row;
        NFCONT &= ~(1<<1);//片选有效
        NFCMMD = 0x60;  //write 1 circle

row = addr / PAGE_SIZE;
        NFADDR = row &0xff;
        NFADDR =(row>>8) &0xff;
        NFADDR = (row>>16) & 0xff;

NFCMMD = 0xd0;//write 2 circle
        while(!(NFSTAT & 1))    //wait until ready
                ;
        show("nand erase ok!\n");

NFCONF |= (1<<1);//拉高
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/552a31ae52b091d572ef6ed781433166.html