天天看点

jz2440 nand flash1: flash 的介绍

1: flash 的介绍

常用的flash有nor  flash和nand  flash两种。主要区别:由于norflash的接口与ram完全相同,所以程序可以直接在norflash上运行,无需把程序拷贝到内存中运行,nand flash 要把程序拷贝到内存中运行。norflash的读操作效率非常高,但是擦擦和写的效率非常的低。另外norflash的存储空间一般很小。nandflash的擦除和写的效率非常高。一般而言,norflash 用于程序存储,nandflash用于数据存储。 对于flash 存储器件要考虑3点。1:位反转,2:坏块, 3: 可擦除次数。

2:nandflash的物理结构

jz2440 nand flash1: flash 的介绍

flash 引脚

I/O0~I/O7 数据输入和数据输出。从地址和数据都用IO口来传递。

CLE :命令锁使能,高电平有效,当CLE为高电平时,IO口传输的是命令 ALE : 地址使能, 高电平有效,当ALE为高电平时, IO口传输的是地址 当CLE和ALE都为低电平时候传输的是DATA CE : 当CE为低电平时,片选使能 RE:读使能,低电平有效 wE: 写使能,低电平有效 WP: 写保护,低电平有效 R/B# :就绪/输出忙信号 VCC: 电源 VSS: 接地

NC: 不接

nand flash 存储单元结构图:

jz2440 nand flash1: flash 的介绍

1:如图所示一页中main区的容量512B,16表示spare区容量(用于读写数据操作的时候存放校验码)

2:每个块里包含很多页,老的flash页的大小是256M, 512M,这类称作small block, 地址周期只有4个。常见的nand flash页的大小正常是2K,这成为big  block, 地址周期有5个。这个芯片每页512M属于小页

3:芯片写操作是以页为单位的,擦除是以块为单位的。nand flash 擦除就是把数据全变为1

4:由于nandflash 无法像norflash直接运行程序,所以一般用nandflash作为存储芯片的时候一般会在内部集成4K的ram.在启动的时候硬件会自动从nandflash 拷贝4K的空间到ram上,然后在ram上从0地址开始运行,再把NANDFLASH的程序拷贝到内存中去运行。

nand flash和2410或者2440的连接图如下:

jz2440 nand flash1: flash 的介绍

具体引脚的含义上面已经描述过在此就不在赘述。

nand flash控制器介绍:

CPU访问nand flash时候,需要先发出命令,然后再发出地址,最后才是数据的读写。这一系列的过程需要各个使能信号来分辨是命令还是地址还是数据.nand flash提供了NFCONF, NFCMD,NFADDR,NFDATA,NFSTAT,NFECC等6个寄存器。

代码分析:

jz2440 nand flash1: flash 的介绍
jz2440 nand flash1: flash 的介绍

 由图中可以知道TACLS = TCLS - TWP  = 15 - 15 = 0

 根据寄存器中描述的计算公式:Duration =  HCLK x TACLS =>  0ns = 10ns x TACLS  => TACLS = 0

TWRPH0 的时间是 twp ,查 时间表 得到 15ns      根据寄存器中描述的计算公式: Duration =  HCLK x ( TWRPH0 + 1 )  =>  15ns = 10ns x (TWRPH0 + 1)  => TWRPH0 = 0.5 ,由于他的取值范围是 (0~7) ,并且,时间表中的时间是最小能识别的时间,那我们取TWRPH0 = 1

TWRPH1 的时间是 tclh = 5ns     根据寄存器中描述的计算公式: Duration =  HCLK x ( TWRPH1 + 1 ) => 5ns = 10ns x (TWRPH1 + 1) => TWRPH1 = 0 即能满足 nand flash的初始化:

void nand_init(void)

{

   #define TACLS 0

   #define TWRPH0  3

   #define TWRPH1  0

    NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);  //设置时序

    NFCONT = (1<<4)|(1<<1)|(1<<0);   //使能nand flash控制器,初始化ECC,禁止片选

  }

void nand_select_chip(void)

{

     int i;

     NFCONT &= ~(1<<1);    //片选使能

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

}

void write_cmd(int cmd)

{

   unsigned long *p = (unsigned long *)NFCMD; 

   *p = cmd;  //写命令

}

 void wait_idle(void)

{

    int i;

    volatile unsigned char *p = (volatile unsigned char *)NFSTAT;

    while(!(*p & BUSY))

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

}

nand_deselect_chip(void)

{

    NFCONT |= (1<<1);

}

//读取数据

unsigned char read_data(void)

{

    volatile unsigned char *p = (volatile unsigned char *)NFDATA;

    return *p;

}

 void write_addr(unsigned int addr)

{

    int i;

    volatile unsigned char *p = (volatile unsigned char *)NFADDR;

    *p = addr & 0xff;

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

    *p = (addr >> 9) & 0xff;

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

    *p = (addr >> 17) & 0xff;

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

    *p = (addr >> 25) & 0xff;

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

}

继续阅读