s3c2440操作norflash EN29LV160AB

     norflash 兼具dram和nandflash优点: 掉电数据不丢失,可以随机 读,也就是说可以直接执行程序。但有个缺点就是造价比较高,一般只是小容量使用。

以前用mini2440板子用的是SST39VF1601,具体操作过程可见前面博文。这里是EN29LV160AB,跟之前的略有不同。


     对norflash的操作主要就是读、写、擦除和识别等。EN29LV160AB的数据宽度可以是8位字节型,也可以是16位的字型,它由EN29LV160AB的某一引脚配置实现的。

在这里我们选择字型。

   对norflash的读操作比较简单,系统上电后会自动进入读模式,而且也不需要额外的命令来实现读操作,就像访问dram一样cpu直接发出读指令 就可以了。下面的函数实现了读操作:

U16 read_en29lv160ab(U32 addr)
{
	return *((volatile U16 *)(addr));
}

       norflash不仅能够实现硬件复位,而且可以实现软件复位。软件复位的操作是向任一地址写入复位命令0xF0。下面的函数实现了软件复位:

void reset_en29lv160ab(void)
{
	*((volatile U16 *)0x0) = 0xf0;
}

       norflash的擦除操作和写操作要稍微复杂一些,它们需要4个或6个周期来完成,每一个周期都要把相应的命令写入norflash中的某一命令寄存器中。写操作的过程为第一

个周期是把命令0xAA写入地址为0x555的命令寄存器中,第二个周期是把命令0x55写入地址为0x2AA命令寄存器中,第三个周期是把命令0xA0再写入地址为0x555命令寄存

器中,第四个周期为真正地把要写入的数据写入到norflash的地址中。下面的函数实现了写操作,其中该函数的两个输入参数分别为要写入的数据和地址,为了方便,我们事

先定义好命令寄存器:

#define    flash_base              0x00000000
#define    CMD_ADDR0              *((volatile U16 *)((0x555<<1)+flash_base))
#define    CMD_ADDR1              *((volatile U16 *)((0x2aa<<1)+flash_base))

U8 en29lv160ab_program(U32 addr, U16 dat)
{
	CMD_ADDR0 = 0xaa;
	CMD_ADDR1 = 0x55;
	CMD_ADDR0 = 0xa0;
	*((volatile U16 *)(addr)) = dat;

	return check_toggle();
}

   由于我们是把 norflash 连接到了  s3c2440  的bank 0上,因此norflash中的地址相对于s3c2440来说基址为0x00000000。而之所以又把norflash中的地址向左移一位(即乘

以2),是因为我们是把 s3c2440 的  ADDR1  连接到了 norflash 的A0上的缘故。

s3c2440操作norflash EN29LV160AB_第1张图片


    在该函数中,我们还调用了check_toggle函数,它的作用是用于判断这次操作是否正确,它的原型为:

U8 check_toggle(void)
{
	volatile U16 newtoggle,oldtoggle;
	oldtoggle = *((volatile U16 *)0x0);

	while(1)
	{    
		newtoggle = *((volatile U16 *)0x0);
		if((oldtoggle & 0x40)==(newtoggle & 0x40))
			break;

		if(newtoggle & 0x20)           //DQ5
		{
			oldtoggle = *((volatile U16 *)0x0);
			newtoggle = *((volatile U16 *)0x0);

			if((oldtoggle & 0x40)==(newtoggle & 0x40))
				break;
			else
				return 0;         //错误
		}    
		oldtoggle = newtoggle;
	}

	return 1;         //正确
}

     它的原理是连续两次读取数据总线上的数据,判断数据总线上的第6位数值(DQ6)是否翻转,如果没有翻转则正确,否则还要判断第5位(DQ5),以确定是否是因为超时而引起的翻转。

     norflash也需要擦除操作,写操作只能使“1”变为“0”,而只有擦除才能使“0”变为“1”---这点与nandflash一致。因此在写之前一定要先擦除。擦除分为块擦除和整片擦除。块擦

除的过程为第一个周期是把命令0xAA写入地址为0x555的命令寄存器中,第二个周期是把命令0x55写入地址为0x2AA命令寄存器中,第三个周期是把命令0x80再写入地址为0x555命令寄存器中,第四个周期是把命令0xAA写入地址为0x555的命令寄存器中,第五个周期是把命令0x55再写入地址为0x2AA命令寄存器中,第六个周期是把命令0x30

写入要擦除块的首地址内。

s3c2440操作norflash EN29LV160AB_第2张图片

s3c2440操作norflash EN29LV160AB_第3张图片

    注意因为这里选择字型,所以上图的命令序列应该选择word一栏。


下面的函数为块擦除,其中输入参数为要擦除块的首地址:

U8 en29lv160ab_sector_erase(U32 section_addr)
{
	CMD_ADDR0 = 0xaa;
	CMD_ADDR1 = 0x55;
	CMD_ADDR0 = 0x80;
	CMD_ADDR0 = 0xaa;
	CMD_ADDR1 = 0x55;
	*((volatile U16 *)(section_addr)) = 0x30;

	return check_toggle();
}


  下面链接给出一个我调试通过的例子,实现 norflash的 擦除,写,读操作。注意当操作norflash的时候 一定要选择开发板从norflash启动。由于这个比较特殊所以开始的汇编

代码设置 栈的时候一定 要选择合适的,刚开始还是设置成适用于nandflash 的4K位置

ldr     sp, =1024*4         @ stack pointer point to 4K
显然从norflash启动的时候 4K还映射着norflash ,是无法作为栈使用的,当然程序错误了,憋了很久才找到远因。

由于这个比较特殊,所以就没有把这些代码集成到norflash里面,直接是一个独立的裸机程序。



https://www.dropbox.com/sh/4ljok09eyqb5ke6/AAC4pzHtEUCYQjSlyLr8Jt6ka?dl=0





你可能感兴趣的:(s3c2440,NorFlash,EN29LV160AB)