2440之NOR FLASH

来源:互联网 发布:软件加盟 编辑:程序博客网 时间:2024/06/10 04:18
 

NOR FLASH

   2440支持从非NAND启动,也就是NOR启动,nor flash映射在处理器的bank0地址空间(从系统地址0x00000000开始)。系统上电复位,处理器就自动从0x00000000地址处开始取得指令运行。因此nor flash中要存放系统启动代码,这些代码必须在系统上电时开始取得一系列初始化的工作。

  2440的开发板采用了SST39VF1601SST39VF160是由SST公司推出的容量为1MB×16bitCMOS多用途flash

引脚定义参考用户手册,原理图如下:

      

注意下地址线连接方式。

NOR FALSH也采用命令方式进行编程。常用命令如下,具体应用参考用户手册

FALSH进行的最基本操作由读操作,写操作,和擦除操作。以下将详细介绍。

SST39V的读操作是用/CE/OE信号线控制的。当两者都为低时,处理器就可以从SST39VF160的输出口读取数据。/CESST39VF160的片选线,当/CE为高,芯片未被选中,/OE是输出使能信号线,当/CE/OE中的某一个为高时,SST39VF160的数据线为高阻态。

读操作的时序如下图:

SST39VF160的写操作主要是以一个字接着一个字的方式进行写入的。在写入之前,扇区中如果由数据(0),则必须首先进行充分地擦除。写操作分三步进行。第1步,送出“软件数据保护”的3字节;第2步,送出地址和数据;第3步,内部写入处理阶段,这个阶段在第4/WE/CE的上升沿时被初始化。被初始化后,内部写入处理就将在20us时间内完成。在内部写入阶段,任何指令狗将被忽略。字写时序如图所示。

                                   WE信号有效

扇区或块操作允许SST39VF160以一个扇区接一个扇区,或一个块接一个块地进行擦除。扇区时统一的2Kword16位)大小。块是统一的32Kword大小。扇区操作通过执行6字节的指令序列来进行,这个指令序列中包括扇区擦除指令(30h)和扇区地址(SA)。块操作也通过6字节的指令序列来进行,这个指令序列中包括块擦除指令(50h)和块地址(BA)。扇区或块的地址在/WE的第6个下降沿处锁存,指令字节(30h50h)在/WE的第6个上升沿处锁存。之后,开始内部擦除操作。可以采用/data polling bittoggle bit的方法来判定内部擦除是否结束。除此之外,在内部擦除阶段,其他的指令都将被忽略。

SST39VF160还提供一个整片擦除的功能,允许使用者一个行快速擦除整个存储器(存储阵列每个单位都为1)。整片擦除同样通过执行6字节的指令序列来进行,6字节指令序列中包括片擦除指令(10h)和字节序列最后的地址5555h。下图为擦除操作的流程图。

 

以上信息全部来自SST39VF1601用户手册

SST39VF提供了两种软件方法来检测内部操作是否完成。软件检测方式涉及两个状态位:/Data Polling bit(DQ7)Toggle bitDQ6)。在/WE的上升沿,写入结束检测功能被使能,同时内部写入或擦除也被初始化。这里只介绍Toggle bit方式。

在北部写入或擦除都会产生一个不断翻转的10。当内部写入或擦除完成时,翻转位在第4/WE /CE的上升沿处有效。在擦除操作中,翻转位在第6/WE /CE的上升沿处有效,流程图如下

 

在程序中你会发现:

define writeflashaddrdat  *((volatile unsigned int *)(addr<<1))=(unsigned int)dat;

从原理图中可以看出芯片的A0 ,连接到地址线的A1addr为写入数据的目标地址,由于dat16位字而不是字节。因而addr也是字地址。但对处理器而言地址是以字节位单位的,因此,addr必须加以调整,左移1位。

       在有些程序中如下定义:

#define  ROM_BASE 0x04000000    //地址重定向到x04000000

#define  CMD_ADDR0 *((volatile U16 *)(0x5555*2+ROM_BASE))

#define  CMD_ADDR1 *((volatile U16 *)(0x2aaa*2+ROM_BASE))

判断读写完成的代码为:

         while(1)

         {

              i = *(volatile U16 *)ProgStart&0x40;

              if(i!=*(volatile U16 *)ProgStart&0x40)         //D6 == D6

                   continue;

              if((*(volatile U16 *)ProgStart&0x80)==(j&0x80))   

                   break;                      //D7 == D7

         }

D6D7分别进行判断。

看程序是要明白U32 ProgStart (volatile U16 *)ProgStart*(volatile U16 *)ProgStart得含义,不然在以后的程序中大量出现的时候就很感到很迷惑。

    附一道测试题:

    在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。