2440支持从非NAND启动,也就是NOR启动,nor flash映射在处理器的bank0地址空间(从系统地址0x00000000开始)。系统上电复位,处理器就自动从0x00000000地址处开始取得指令运行。因此nor flash中要存放系统启动代码,这些代码必须在系统上电时开始取得一系列初始化的工作。
2440的开发板采用了SST39VF1601,SST39VF160是由SST公司推出的容量为1MB×16bit的CMOS多用途flash。
引脚定义参考用户手册,原理图如下:
注意下地址线连接方式。
对NOR FALSH也采用命令方式进行编程。常用命令如下,具体应用参考用户手册
对FALSH进行的最基本操作由读操作,写操作,和擦除操作。以下将详细介绍。
SST39V的读操作是用/CE和/OE信号线控制的。当两者都为低时,处理器就可以从SST39VF160的输出口读取数据。/CE是SST39VF160的片选线,当/CE为高,芯片未被选中,/OE是输出使能信号线,当/CE和/OE中的某一个为高时,SST39VF160的数据线为高阻态。
读操作的时序如下图:
SST39VF160的写操作主要是以一个字接着一个字的方式进行写入的。在写入之前,扇区中如果由数据(0),则必须首先进行充分地擦除。写操作分三步进行。第1步,送出“软件数据保护”的3字节;第2步,送出地址和数据;第3步,内部写入处理阶段,这个阶段在第4个/WE或/CE的上升沿时被初始化。被初始化后,内部写入处理就将在20us时间内完成。在内部写入阶段,任何指令狗将被忽略。字写时序如图所示。
WE信号有效
扇区或块操作允许SST39VF160以一个扇区接一个扇区,或一个块接一个块地进行擦除。扇区时统一的2Kword(16位)大小。块是统一的32Kword大小。扇区操作通过执行6字节的指令序列来进行,这个指令序列中包括扇区擦除指令(30h)和扇区地址(SA)。块操作也通过6字节的指令序列来进行,这个指令序列中包括块擦除指令(50h)和块地址(BA)。扇区或块的地址在/WE的第6个下降沿处锁存,指令字节(30h或50h)在/WE的第6个上升沿处锁存。之后,开始内部擦除操作。可以采用/data polling bit或toggle bit的方法来判定内部擦除是否结束。除此之外,在内部擦除阶段,其他的指令都将被忽略。
SST39VF160还提供一个整片擦除的功能,允许使用者一个行快速擦除整个存储器(存储阵列每个单位都为1)。整片擦除同样通过执行6字节的指令序列来进行,6字节指令序列中包括片擦除指令(10h)和字节序列最后的地址5555h。下图为擦除操作的流程图。
以上信息全部来自SST39VF1601用户手册
SST39VF提供了两种软件方法来检测内部操作是否完成。软件检测方式涉及两个状态位:/Data Polling bit(DQ7)和Toggle bit(DQ6)。在/WE的上升沿,写入结束检测功能被使能,同时内部写入或擦除也被初始化。这里只介绍Toggle bit方式。
在北部写入或擦除都会产生一个不断翻转的1和0。当内部写入或擦除完成时,翻转位在第4个/WE 或/CE的上升沿处有效。在擦除操作中,翻转位在第6个/WE 或/CE的上升沿处有效,流程图如下
在程序中你会发现:
#define writeflash(addr,dat) *((volatile unsigned int *)(addr<<1))=(unsigned int)dat;
从原理图中可以看出芯片的A0 ,连接到地址线的A1,addr为写入数据的目标地址,由于dat为16位字而不是字节。因而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
}
对D6,D7分别进行判断。
看程序是要明白U32 ProgStart ,(volatile U16 *)ProgStart,*(volatile U16 *)ProgStart得含义,不然在以后的程序中大量出现的时候就很感到很迷惑。
附一道测试题:
在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写代码去完成这一任务。