⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 norflash.c

📁 基于S3C2410和SM501的彩屏控制器程序
💻 C
字号:
#define __NORFLASH
#include "Norflash.h"
#undef __NORFLASH


//********************** Global Variable **********************

BYTE cFlashType;	// flash类型
WORD wTotalSector;	// 总共扇区数
DWORD wTotalSize;	// Flash的总容量

//*************************************************************



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 读当前NorFLASH类型.
//	
// 返回: FLASH类型.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BYTE ReadNorFlashType (void)
{
	// 用头信息中的FLASH类型
	cFlashType = NOR_FLASH_S29GL256N;

	switch( cFlashType )
	{
		case NOR_FLASH_AM29LV320D:
			wTotalSector = 64;
			break;
	
		case NOR_FLASH_AM29LV160D:	
			wTotalSector = 32;
			break;

		case NOR_FLASH_AM29LV800B:			
			wTotalSector = 16;
			break;

		case NOR_FLASH_S29GL256N:
			wTotalSector = 256;
			break;

		default:	// 错误	
			wTotalSector = 0;			
			return FALSE;				
	}

	return cFlashType;
}//ReadNorFlashType()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 禁止Flash读写.
// 描述: 保护NorFlash, 读写都禁止. 禁止后读数据只能读到全0.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void DisableFlash (void)
{
	Clr_MRST();
	Clr_FLASHWP();
}//DisableFlash()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 允许Flash读写.
// 描述: 取消NorFlash保护, 允许对其读写.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void EnableFlash(void)
{
	Set_MRST();
	Set_FLASHWP();
}//EnableFlash()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 擦除单个扇区.
// 描述: 擦除NorFlash某个扇区. 耗时700-1500ms.
//
// [参数表]
//	Dst: 扇区地址.
//	
// 返回: 擦除操作是否成功. 0-失败; 1-成功.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BYTE EraseOneSector(DWORD Dst)
{       
    int	i,j;
    ulong start, now, last;
    vu_short *addr = (vu_short*)(0x00);
    
	disable_interrupts();	// 关总中断
	EnableFlash();			// 允许Flash读写

	addr[0x555] = (vu_short)0xAAAA;
	addr[0x2AA] = (vu_short)0x5555;
	addr[0x555] = (vu_short)0x8080;
	addr[0x555] = (vu_short)0xAAAA;
	addr[0x2AA] = (vu_short)0x5555;
	addr = (vu_short*)(FLASH_ADDRESS+Dst);
	addr[0] =(vu_short)0x3030;
	
	for(i=0; i<300; i++)		// 延时
		for(j=0; j<1000; j++);

	start = get_timer(0);
	last  = start;
	addr = (vu_short*)(FLASH_ADDRESS+Dst);
	while ((addr[0] & 0x8080) != 0x8080) 
	{
		if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT)
			return FALSE;

		// ----- 计算(显示)等待时间, 单位:秒 -----
		if ((now - last) > 100000) 
		{	/* every second */
			last = now;
		}
	}
	
  	DisableFlash();		// 禁止Flash读写
  	addr = (vu_short *)(0x0);
	addr[0] = (vu_short)0xF0F0;

	return TRUE;        
}//EraseOneSector()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 擦除扇区.
// 描述: 擦除给定扇区号的扇区内容.
//
// [参数表]
//	wSector: 扇区号.
//	
// 返回: 擦除操作是否成功. 0-失败; 1-成功.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BYTE EraseSector(WORD wSector)
{
/*	// Commnet: 旧彩显板的写法, 需要对Flash的前64K做特殊处理
// 注意: 每种类型的FLASH的前64K扇区是不同的!
	DWORD	wFirst64K[][9]={
				{8,0x0000,0x2000,0x4000,0x6000,0x8000,0xA000,0xC000,0xE000},	//NOR_FLASH_AM29LV320D,8*8K
				{4,0x0000,0x4000,0x6000,0x8000},	//NOR_FLASH_AM29LV160D,1*16K,2*8K,1*32K
				{4,0x0000,0x4000,0x6000,0x8000}};	//NOR_FLASH_AM29LV800B,1*16K,2*8K,1*32K
	WORD i;
	int  j;
	
	if( wTotalSector == 0 || wSector>=wTotalSector )	//无效FLASH或参数错误
		return FALSE;
	
	if( wSector==0 )	// 对扇区0的特殊处理
	{
		for(i=0; i<wFirst64K[cFlashType-1][0]; i++)
		{
			if( EraseOneSector(wFirst64K[cFlashType-1][i+1]) == FALSE )
				return FALSE;
			for(j=0; j<300000; j++);	// 延时等待
		}
		return TRUE;
	}
	else
		return EraseOneSector((DWORD)wSector*65536);
*/
	
	if( wTotalSector == 0 || wSector>=wTotalSector )	//无效FLASH或参数错误
		return FALSE;
	
	return EraseOneSector((DWORD)wSector*NOR_FLASH_SECTOR_SIZE);	// 擦除指定的扇区
	// 注: 新彩显板的NorFlash每个扇区都是128KB.
}//EraseSector()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 写一个字进Flash.
// 描述: 写入一个字(4字节)到Flash的指定位置.
//
// [参数表]
//	dest: 写入地址.
//	data: 写入内容.
//
//返回: 0-完成; 1-写入超时; 2-Flash未擦除.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static int write_word (ulong dest, ulong data)
{
	vu_short *addr = (vu_short *)(FLASH_ADDRESS);
	vu_short sdata;

	ulong start;

	/* Check if Flash is (sufficiently) erased */
	if ((*((vu_long *)dest) & data) != data) {
		return (2);
	}

	/* First write upper 16 bits */
	sdata = (short)(data>>16);
	sdata = (sdata >> 8) | (sdata << 8);

	/* Disable interrupts which might cause a timeout here */

/* 在Writeflash中统一关、开中断, 避免每次重复操作 */
//	disable_interrupts();

	addr[0x555] = 0xAAAA;
	addr[0x2AA] = 0x5555;
	addr[0x555] = 0xA0A0;

	*((vu_short *)dest) = sdata;

	/* re-enable interrupts if necessary */

	//enable_interrupts();

	/* data polling for D7 */
	start = get_timer (0);
	while ((*((vu_short *)dest) & 0x8080) != (sdata & 0x8080)) {
		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
			return (1);
		}
	}

	/* Now write lower 16 bits */
	sdata = (short)(data&0xffff);
	sdata = (sdata >> 8) | (sdata << 8);

	/* Disable interrupts which might cause a timeout here */
//	disable_interrupts();

	addr[0x555] = 0xAAAA;
	addr[0x2AA] = 0x5555;
	addr[0x555] = 0xA0A0;

	*((vu_short *)dest + 1) = sdata;

	/* re-enable interrupts if necessary */
	
//	enable_interrupts();

	/* data polling for D7 */
	start = get_timer (0);
	while ((*((vu_short *)dest + 1) & 0x8080) != (sdata & 0x8080)) {
		if (get_timer(start) > CFG_FLASH_WRITE_TOUT) {
			return (1);
		}
	}
	return (0);
}//write_word()



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 写Flash.
// 描述: 将数据块写入Flash.
//
// [参数表]
//	src: 数据块始地址.
//	addr: Flash的写入始地址.
//	cnt: 写入字符计数.
//
// 返回: 0-完成; 1-写入超时; 2-Flash未擦除.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int Writeflash (uchar *src, ulong addr, ulong cnt)
{
	ulong wp;	// 写入指针
	ulong cp;	// 拷贝指针. 用于处理始、末端非对齐数据
	ulong data;	// 临时数据缓冲, 用于调整写入的内容, 为写入flash准备数据
//注: 因为write_word函数是以整型(4字节)进行写入, 所以需要调整所需的格式.
	int i, l, rc;

	wp = (addr & ~3);	/* get lower word aligned address */

	disable_interrupts();	// 关闭总中断, 防止因中断引起的写入超时

	/* handle unaligned start bytes */
	// 起始段数据(<4字节)处理, 目的是为批量写入数据前对齐地址.
	if ((l = addr - wp) != 0)
	{
		data = 0;
		for (i=0, cp=wp; i<l; ++i, ++cp)	// 将flash中即将被写入的位置的起始内容填充数据缓冲
		{
			data = (data << 8) | (*(uchar *)cp);
		}
		for (; i<4 && cnt>0; ++i)	// 将起始段未对齐数据在数据缓冲中进行转换
		{
			data = (data << 8) | *src++;
			--cnt;
			++cp;
		}
		for (; cnt==0 && i<4; ++i, ++cp)	// 将数据缓冲的末端空余位置用flash中即将被写入的位置的内容填充
		{
			data = (data << 8) | (*(uchar *)cp);
		}

		if ((rc = write_word( wp, data)) != 0)	// 写入
		{
			enable_interrupts();	// 打开总中断
			return (rc);	// 写入出错返回
		}
		wp += 4;	// 写入指针指向下一位置
	}

	/* handle word aligned part	 */
	// 批量写入数据, 每次以一个字(32bit)的长度进行写入
	while (cnt >= 4)
	{
		data = 0;
		for (i=0; i<4; ++i)
		{
			data = (data << 8) | *src++;
		}
		if ((rc = write_word( wp, data)) != 0)	// 写入
		{
			enable_interrupts();	// 打开总中断
			return (rc);	// 写入出错返回
		}
		wp  += 4;	// 写入指针指向下一位置
		cnt -= 4;
	}

	if (cnt == 0)	// 若上述操作正好写完, 则返回完成.
	{
		enable_interrupts();	// 打开总中断
		return (0);
	}

	/* handle unaligned tail bytes */
	// 处理数据块的尾部数据(<4字节)
	data = 0;
	for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp)	// 将尾部数据在数据缓冲中进行转换
	{
		data = (data << 8) | *src++;
		--cnt;
	}
	for (; i<4; ++i, ++cp)	// 将数据缓冲的空余位置用flash中即将被写入的位置的内容填充
	{
		data = (data << 8) | (*(uchar *)cp);
	}
	rc = write_word( wp, data);
	enable_interrupts();	// 打开总中断
	return (rc);	// 返回最终操作结果
}//Writeflash()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -