• NorFlash


    一、NorFlash概述

    1、NorFlash

      Intel于1988年首先开发出NOR Flash 技术,彻底改变了原先由EPROM(Erasable Programmable Read-Only-Memory电可编程序只读存储器)和EEPROM(电可擦只读存储器Electrically Erasable Programmable Read - Only Memory)一统天下的局面。 

      NOR的优越之处是芯片内执行(XIP, eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中。NOR的传输效率很高,在1~4MB的小容量时具有很高的成本效益,但是很低的写入和擦除速度大大影响了它的性能。

    2、NandFlash和NorFlash对比 

    Nor/Nand Flash 的差别
      Nor  Nand
    容量 1MB~32MB 16M~512MB
    XIP Yes No
    擦除 非常慢(5S) 快(3ms)
    慢        快
    可靠性 比较高,位反转的比例小于NandFlash的10% 比较低,位反转比较常见,必须有校验措施,比如TNR必须有坏块管理措施
    可擦除次数 10000~100000               100000~1000000
    生命周期     低于NandFlash的10%              是NorFlash的10倍以上    
    接口       与RAM接口相同                    I/O接口
    访问方法 随机访问 顺序访问
    易用性 容易 复杂
    主要用途 常用于保存代码和关键数据 用于保存数据
    价格 便宜

    3、CFI(Common Flash Interface)
       不同公司产的NOR Flash在 erase,program,lock,unlock等操作上有差别,即command set不一样。
       NorFlash要是支持CFI就好办多了,就不用改代码。通过CFI可以读出片子的manufacturer id,vendorid等等,在程序中就可以通过以上信息来选择正确的erase,program等操作方式。
       NorFlash的数据线和地址线都可能为32/16/8条.为了统一起见,通过CFI接口查询时, CFI接口描述的地址均为Flash芯片的地址,CFI接口查询到的数据,以低字节D7-D0上为准,高字节数据线无视就好了。

     CFI的作用是把NorFlash 的信息通过统一的方法读出来。

    二、NorFlash物理结构

      以下内容皆以EN29LV160AB(word模式)为例进行说明。

    1、引脚

    2、NorFlash块图

    3、扇区结构

      Size: 2 MB in 35 Sectors
      Sector Start Addresses:
        00000000      00004000      00006000      00008000      00010000 
        00020000      00030000      00040000      00050000      00060000     
        00070000      00080000      00090000      000A0000      000B0000     
        000C0000      000D0000      000E0000      000F0000      00100000     
        00110000      00120000      00130000      00140000      00150000     
        00160000      00170000      00180000      00190000      001A0000     
        001B0000      001C0000      001D0000      001E0000      001F0000 

      EN29LV160AB大小为2M,总共35个扇区,上图列出了每个扇区的起始地址。

    三、NorFlash与ARM接线图

      左图为EN29LV160AB与ARM的接线图,右图是SRAM与ARM的接线图,可以看到两者没多大的差别。

    、NorFlash相对于RAM使用的特殊性 

    NorFlash相对于RAM使用的特殊性

     

    RAM

    NorFlash

    读取/写入的叫法

    读取/写入

    读取/编程(Program)

    读取/写入的最小单位

    字节(Byte)

    字(Word)

    擦除(Erase)操作的最小单位

    字节

    Sector/扇区

    擦除操作的含义

    将数据删除/全部写入0

    将整个块都擦除成全是1,也就是里面的数据都是0xFF

    对于写操作

    直接写即可

    在写数据之前,要先擦除,然后再写

     五、NorFlash操作

    1、CFI操作

      EN29LV160AB遵循CFI接口协议,所以可以进行CFI操作方式。下表仅仅是CFI查询信息的命令表,还有其他表格,这里不再列出。下边将要阐述的操作方式不是通用性的CFI操作,而是EN29LV160AB特有命令集操作。

    2、NorFlash命令表

      不利用CFI方式也可以操作,EN29LV160AB有自己的命令集,利用这个命令集可以完成需要的操作。

    3、状态标志位

    DQ7

    Data# Polling bit,在编程过程从正在编程的地址中读出的数据的 DQ7 为要写入数据位的补码。比如写入的数据为 0x0000 ,即输入的 DQ7 为  0 ,则在编程中读出的数据为  1  ;当编程完成时读出的数据又变回输入的数据  0  。在擦除过程中 DQ7 输出为   0 ;擦除完成后输出为 1 ;注意读取的地址必须是擦除范围内的地址。RY/BY#:高电平表示‘就绪’,低电平表示‘忙’。


    DQ6

    轮转位 1(Toggle Bit 1 ),在编程和擦除期间,读任意地址都会导致 DQ6 的轮转(0 ,1间相互变换)。当操作完成后,DQ6停止转换。

     
    DQ2

    轮转位 2 (Toggle Bit 2 ),当某个扇区被选中擦除时,读有效地址(地址都在擦除的扇区范围内)会导致 DQ2 的轮转。 注意: DQ2 只能判断一个特定的扇区是否被选中擦除,但不能区分这个扇区是否正在擦除中或者
    正处于擦除暂停状态。相比之下,DQ6 可以区分 Nor Flash 是否处于擦除中或者擦除暂停状态,但不能区分哪个扇区被选中擦除,因此需要这 2 个位来确定扇区和模式状态信息。


    DQ5

    超时位(Exceeded Timing Limits) ,当编程或擦除操作超过了一个特定内部脉冲计数时 DQ5=1,表明操作失败。当编程时把 0 改为  1  就会导致 DQ5=1,因为只有擦除擦做才能把 0  改为 1 。当错误发生后需要执行复位命令才能返回到读数据状态。

    DQ3

    (扇区擦除计时位)Sector Erase Timer  ,只在扇区擦除指令时起作用。当擦除指令真正开始工作时 DQ3=1  ,此时输入的命令(除擦除暂停命令外)都被忽略,DQ3=0  时,可以添加附加的扇区用于多扇区擦除。

    六、实现代码

    1、读ID

    /*******************************************************************
    函数功能:显示NorFlash的“Manufacturer ID”和“Device ID”
    输入参数:addr
    输出参数:无
     ********************************************************************/
    void NOR_Read_ID(void)
    {
        unsigned short ManuID,DevID;
        
        NOR_Rest();
        NOR_WR(0x555,0xaa);
        NOR_WR(0x2aa,0x55);
        NOR_WR(0x555,0x90);
        ManuID = NOR_RD(0x0);
        DevID = NOR_RD(0x1);
        printf("Manufacturer ID: %x
    ",ManuID);    
        printf("Device ID: %x
    ",DevID);
    }

    2、读内容并显示

    /*******************************************************************
    函数功能:从NorFlash给定的地址处显示256B的内容
    输入参数:addr
    输出参数:无
    *********************************************************************/
    void NOR_2K_Content(unsigned char *addr)
    {   unsigned int i;
     
        printf("Show 256 Bytes content of NorFlash:
    ");    
        for(i=0; i<256; i++) {
            if((i%16)==0) printf("
    %4x: ", i);
            printf("%02x ", *addr++);
        }
        printf("
    ");
    }

    3、擦除

    /*******************************************************************
    函数功能:擦除整个芯片
    输入参数:无
    输出参数:无
    ********************************************************************/
    void NOR_EraseChip(void)
    {
        printf("chip erasing is started!
    ");
        NOR_Rest();
        NOR_WR(0x555,0xaa);
        NOR_WR(0x2aa,0x55);
        NOR_WR(0x555,0x80);
        NOR_WR(0x555,0xaa);
        NOR_WR(0x2aa,0x55);
        NOR_WR(0x555,0x10); 
        printf("it may takes some seconds,plese wait......
    ");
        if(NOR_Wait())
        {
            printf("Erasing done!
    ");
        }
        else
        {
            printf("Erasing error!
    ");
        }
     }
     
    /*******************************************************************
    函数功能:擦除给定的扇区
    输入参数:sect    扇区号
    输出参数:无
    *********************************************************************/
    void NOR_EraseSector(unsigned char sect)
    {
        unsigned int sectaddr;
        
        if(sect > 34)
        {
            printf("sect number error!
    ");
            return ;
        }
        
        switch(sect)
        {
            case 0:
                    sectaddr = 0x0;
                    break;
            case 1:
                    sectaddr = 0x2000;
                    break;
            case 2:
                    sectaddr = 0x3000;
                    break;
            case 3:
                    sectaddr = 0x4000;
                    break;
            default:
                    sectaddr = 0x8000*(sect - 3);        
        }
        printf("Sector %d erasing is started!
    ",sect);
        NOR_Rest();
        NOR_WR(0x555,0xaa);
        NOR_WR(0x2aa,0x55);
        NOR_WR(0x555,0x80);
        NOR_WR(0x555,0xaa);
        NOR_WR(0x2aa,0x55);
        NOR_WR(sectaddr,0x30); 
        printf("it may takes some seconds,plese wait......
    ");
        if(NOR_Wait())
        {
            printf("Erasing done!
    ");
        }
        else
        {
            printf("Erasing error!
    ");
        }
     }

    4、编程

    /*******************************************************************
    函数功能:写一个字(2Byte)
    输入参数:addr    要写入一个字的物理地址,注意第0位肯定是‘0’
              data  要写入的数据
    输出参数:1 成功
              0    失败
    ********************************************************************/
    static unsigned int NOR_Program(unsigned int addr,unsigned short data)
    {
            NOR_Rest();
            NOR_WR(0x555,0xaa);
            NOR_WR(0x2aa,0x55);
            NOR_WR(0x555,0xa0);
            NOR_WR_DAT(addr,data);
            return NOR_Wait();  
    }
    
    /*******************************************************************
    函数功能:写入多个字节
    输入参数:srcaddr    源地址
              desaddr    目的地址
              size        大小(以Byte为单位)
    输出参数:1 成功
              0    失败
    ********************************************************************/
    unsigned int NOR_Write(unsigned short *srcaddr,unsigned int desaddr,unsigned int size)
    {
            unsigned int i;
            printf(" Write NorFlash start!
    ");
            for(i = 0;i < size;i += 2){
                if( NOR_Program(desaddr,*srcaddr) != 1){
                    printf(" Write NorFlash error!
    ");
                    return 0;
                }
                desaddr += 2;
                srcaddr++;
            }
            printf(" Write done.
    ");
            return 1;
    }

    5、等待擦除或者编程结束

      判断当前状态,从而决定是否等待以及判断是否出错是根据状态标志位来操作的。“等待擦除或者编程结束”有不同的方法实现,这里使用的是DQ6轮转判断。

    /*******************************************************************
    函数功能:等待擦除或者编程结束
    输入参数:无
    输出参数:    1    成功
                0    失败
    *********************************************************************/
    static unsigned int NOR_Wait(void)
    {
        unsigned short oldstatus,newstatus;
        while(1)
        {        oldstatus = NOR_RD(0x0);
                newstatus = NOR_RD(0x0);
                if( (oldstatus&0x40) == (newstatus&0x40) )
                    return 1;
                if( newstatus&0x20 )
                {
                    oldstatus = NOR_RD(0x0);
                    newstatus = NOR_RD(0x0);
                if( (oldstatus&0x40) == (newstatus&0x40) )
                    return 1;
                else
                    return 0;
                }
            }                                       
    }

    参考资料:CFI接口 

         Nor/Nand FLASH的读写

         Nor Flash 在实际应用中的读取方式

    测试代码及文档资料:

         NorFlash.zip

  • 相关阅读:
    过滤器和拦截器的区别
    sql注入
    JavaScript学习
    Linux简单学习
    HTML DOM学习
    Java集合
    java 多线程学习
    常用的OO设计原则
    JAVA设计模式一策略模式(Strategy Pattern)
    201521123071《Java程序设计》第1周学习总结
  • 原文地址:https://www.cnblogs.com/amanlikethis/p/3627595.html
Copyright © 2020-2023  润新知