Nand Flash

自古美人都是妖i 提交于 2020-01-07 16:25:48

Nand Flash 硬件以及初始化

请看Nand Flash 硬件图:

 

nand flash 拥有DATA0~DATA7 1个字节的传输宽度,在此 DATA和地址线是共用的 当ALE为高电平的时候Data线会变成地址总线

下面介绍各个引脚的用处:

1. Rnb :   READY/BUSY OUTPUT 当为低电平的时候表示正在nandflash 忙状态

2. CLE 命令/数据标志引脚 当为高电平 的时候是写命令 低电平的时候是写数据

3. nFCE:   选择芯片引脚 Chip select

4. ALE: 当ALE为高电平的时候DATA线会变成地址线

5. nFWE 当这个引脚是低电平的时候 写使能

6.nFRE:当为低电平的时候读使能。

 

此外 在写使能和读使能都是在上升沿的时候读取和写入有效的数值

 

我们的S2C2440拥有Nandflash控制器所以只要合理的配置控制器的参数就可以读写其中的数据

首先我们先要实现nandflash 的初始化工作:

 

 上图描述的是nand flash 写命令和写地址的时序 名词解释如下:

1. TACLS: CLE & ALE duration setting value 命令或者地址线建立的时间

2. TWRPH0: 写地址或者命令的时间

2. TWRPH1:写使能无效到CLE或者ALE无效的时间

这三个是我们需要初始化的时钟

注意 我们看到HLCK的周期是10ns 也就是说明这三个建立或者无效的时间都可以在一个时钟周期完成,此时是10ns

 下图是芯片手册给的时序和时间参考信息:

 

 

 1. 从此图看出TACLS = TCLS - TWP  而TCLS和TWP都是12ns 所以TACLS为0

2. TWRPH0 : 在手册里面是TWP 所以是12ns

3. TWRPH1:TALH和tCH的最大值 表中可知是5ns 所以是5ns

 

我们得出结论:

1. TACLS 是0

2. TWRPH0:12ns

3 TWRPH1 :5ns

 

在结合CPU芯片手册做计算:

 

 TACLS =   0 

12ns = 10 * x+1; x = 1      TWRPH 0 = 1

5ns = (x+1)*10     x = 0;        TWRPH1 = 0;

 

 

下面是nandflash的初始化代码:

void nand_flash_Init(void)
{
  NFCONF =  (0<<12) | (1<<8)|(0<<4);

  NFCONT = (1<<1)|(1<<4)|(1<<0);

}

设置TACLS和TWRPH0 TWRPH1 的延时 然后使能EEC和nandfalsh

 

读nandflash

1. 选择nandflash

2. 写入col的LSB和MSB

3. 写入page的LSB Middle SB 和MSB

4. 写入0x30

5. 读取nandflash里面的数据 不过每一次只能读从0~2047的数据 所以读下一页的时候需要重新重复写0x00

6,取消选择nandflash

void nand_read(unsigned int addr, unsigned int *buff, unsigned int NumToRead)
{

    unsigned int  i = 0;
    unsigned int page = addr  >> 11;     //get page location
    unsigned int col = addr & 2047;       //get collumn location

    nand_select();
  
   while(i < NumToRead)
       {
          nand_cmd(0);

         /*send col addr */
       nand_addr_byte(col&0xFF);

       nand_addr_byte((col>>8)&0xFF);
     
          /*send row addr 1,2,3*/

        nand_addr_byte(page&0xFF);
     nand_addr_byte((page>>8)&0xFF);
        nand_addr_byte((page>>16)&0xFF);

    nand_cmd(0x30);

    Wait_ready();

    for(; (col < 2048)&(i<NumToRead); col++)
        {
           buff[i++] = nand_data();

           }
      if(i == NumToRead)
      break;

    col = 0;
    page++;
      }
   nand_deselect();
}

 

写nandflash

1. 选择nandflash

2.写入0x80

3. 写col

4. 写page

5. 写入数据

6.写入0x10

注意每一次只能写到2047 这个地址如果大于这个数字 则需要重新发送0x80

void nand_write(unsigned int addr, unsigned char *buff, unsigned int len)
{
   unsigned int page = addr / 2048;
   unsigned int col = addr & (2048-1);
  unsigned int i = 0;
   nand_select();
  while(1)
      {
           nand_cmd(0x80);

       nand_addr_byte(col & 0xff);

       nand_addr_byte((col >> 8)&0xff);

       nand_addr_byte(page & 0xff);

       nand_addr_byte((page>>8) & 0xff);
        
          nand_addr_byte((page>>16) & 0xff);

         for(; (col < 2048)&& (i < len); col++)
             {
                    nand_w_data(buff[i++]);
                  
        }
           nand_cmd(0x10);
       Wait_ready();

       if(i == len)
           break;

      col = 0;
      page++;

      }
}

擦除nandflash

1. 选择nandflash

2.写入0x60

3. 写入要擦除的块(注意块的大小是128k 所以说每一次擦除128k的内容)

4.写入0xD0

5.等待擦除完毕

6. 取消选择nandflash

int nand_flash_earse(unsigned int addr, unsigned int len)
{
     int page = addr / 2048;

     if(addr & (0x1FFFF))
     return -1;
    if((len & 0x1FFFF))
     return -1;

   nand_select();

   while(1)
       {
         page = addr / 2048;

     nand_cmd(0x60);

     nand_cmd(page & 0xff);

     nand_cmd((page >> 8)&0xff);

     nand_cmd((page>>16)&0xff);

     nand_cmd(0xD0);

     Wait_ready();

     len -= 128 * 1024;

     if(len == 0)
         break;
     addr += 128 * 1024;

       }
     nand_deselect();
    return 0;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!