概要:

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


前言:

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

uboot-ram256M nand-flash版:uboot

System.map文件:System.map


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

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

flash_erase 命令擦除整个eMMC_ci

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))
#define  NFSTAT (*(volatile unsigned long *)(Base + 0x28))


NAND FLASH controller的初始化主要有:

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

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

flash_erase 命令擦除整个eMMC_#define_02

flash_erase 命令擦除整个eMMC_#define_03

具体代码如下:

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);//拉高
}