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

📄 flash.c

📁 《嵌入式网络系统设计-基于Atmel ARM7 系列》这个本书的光盘资料
💻 C
📖 第 1 页 / 共 2 页
字号:
	OS_ENTER_CRITICAL()
	{
		__macDFL_SetFMCNForNVM();
	
		AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_SET_GP_NVM | (cNVMBit << 8);
	
		__macDFL_WaitFlashReady(__unStatus);
	}
	OS_EXIT_CRITICAL()		
	
	return __macDFL_GetNVMStatus(cNVMBit);
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : DFL_ClearNVM
//* 功能描述 : 清除NVM位
//* 入口参数 : <cNVMBit>[in] 要设置的NVM位(0-2)
//* 出口参数 : 指令执行成功返回TRUE,否则返回FLASE
//*------------------------------------------------------------------------------------------------
int DFL_ClearNVM(char cNVMBit)
{
#if OS_CRITICAL_METHOD == 3                     
    OS_CPU_SR  	cpu_sr = 0;
#endif

	unsigned int __unStatus;
	
	if(cNVMBit > 2)
		return FALSE;
		
	if(!__macDFL_GetNVMStatus(cNVMBit))
		return TRUE;

	OS_ENTER_CRITICAL()
	{
		__macDFL_SetFMCNForNVM();
	
		AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_CLR_GP_NVM | (cNVMBit << 8);
	
		__macDFL_WaitFlashReady(__unStatus);
	}		
	OS_EXIT_CRITICAL()	
	
	return !__macDFL_GetNVMStatus(cNVMBit);
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __ilIsDataCorrect
//* 功能描述 : 在软件层面对数据作做一次判断,看其是否正确
//* 入口参数 : <punFrom>[in] 指向原始数据的指针
//*			 :   <punTo>[in] 指向目标数据的指针
//*			 :  <unSize>[in] 进行比较的数据长度
//* 出口参数 : 无
//*------------------------------------------------------------------------------------------------
__inline unsigned int __ilIsDataCorrect(unsigned int *punFrom, unsigned int* punTo, unsigned int unSize)
{
	while(unSize > 0)
	{
		if(*punFrom != *punTo)
			return ((unsigned int)punTo);
		
		unSize-=4;
		punFrom++;
		punTo++;
	}
	
	return 0x00000000;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __DFL_WritePage
//* 功能描述 : 把数据写入指定的页面。该函数具备容错能力,它会检查检查写入的数据是否正确,如果不正确它会尝试
//*			 : 重新写入直至正确或者到达指定的尝试次数--3次。
//* 入口参数 :  <sPageIdx>[in] 要写入的页面序号
//*			 : <cIsLocked>[in] 是否锁定相关页面
//*          :   <punFrom>[in] 指向原始数据的指针
//*          :     <unLen>[in] 原始数据长度
//* 出口参数 : - ERR_WFLASH_OK		: 编程成功
//*			 : - ERR_WFLASH_LOCK	: 正在编程的页面已被锁定
//*			 : - ERR_WFLASH_PROG	: 编程失败
//*          : - ERR_WFLASH_UNLOCK	: 解锁失败。参数cIsLocked为TRUE时,该返回值有效
//*------------------------------------------------------------------------------------------------
static char __DFL_WritePage(short sPageIdx, char cIsLocked, unsigned int *punFrom, unsigned int unLen)
{
#if OS_CRITICAL_METHOD == 3                     
    OS_CPU_SR  	cpu_sr = 0;
#endif

	unsigned int 	__unStatus, *__punTo, *__punNextTo, *__punNextFrom, __unCurLenToWrite;
	char 			i = 0;
	
	__punTo = (unsigned int*)((unsigned int)AT91C_IFLASH + sPageIdx * FLASH_PAGE_SIZE);	
	for(i=0; i<3; i++)
	{
		OS_ENTER_CRITICAL()
		{
			__macDFL_SetFMCNForFlash();
			
			if(unLen > 0)
			{
				__punNextTo = __punTo;
				__punNextFrom = punFrom;
				__unCurLenToWrite = unLen;
				do{
					*__punNextTo = *__punNextFrom;
					__punNextTo++;
					__punNextFrom++;
				}while(__unCurLenToWrite -= 4);
			}			
	
			AT91C_BASE_MC->MC_FCR = AT91C_MC_CORRECT_KEY | AT91C_MC_FCMD_START_PROG | (sPageIdx << 8);
			
			//* 等待编程成功
			__macDFL_WaitFlashReady(__unStatus);
		}	
		OS_EXIT_CRITICAL()
	
		if(__unStatus & AT91C_MC_LOCKE)
			return ERR_WFLASH_LOCK;
			
		if(__ilIsDataCorrect(punFrom, __punTo, unLen) == 0x00000000)			
			return ERR_WFLASH_OK;
	}
	
	return ERR_WFLASH_PROG;
}
//*------------------------------------------------------------------------------------------------
//* 函数名称 : __DFL_WriteFlash
//* 功能描述 : 把数据写入FLASH,并根据参数cIsLocked判断是否锁定
//* 入口参数 :   <punFrom>[in] 指向写入数据的指针
//*          :      <unTo>[in] 要写入的地址
//*          :     <nSize>[in] 要写入的数据长度
//*			 : <cIsLocked>[in] 是否锁定相关页面
//* 出口参数 : 返回数据写入的开始地址,如果写入失败则返回一个小于AT91C_IFLASH的值,分别为:
//*			 : - ERR_WFLASH_INVALID_ADDR : 指定写入的地址无效
//*			 : - ERR_WFLASH_LOCK		 : 正在编程的页面已被锁定
//*			 : - ERR_WFLASH_PROG		 : 编程出错
//*          : - ERR_WFLASH_UNLOCK		 : 解锁出错
//*------------------------------------------------------------------------------------------------
static unsigned int __DFL_WriteFlash(unsigned int *punFrom, unsigned int unTo, int nSize, char cIsLocked)
{
	unsigned int 	*__punTo, *__punNextTo, *__punNextFrom;
	int 			__nSize, __nCurSizeToWrite, __nTotalSizeToWrite = 0, __nTotalSizeNotToWrite;
	short 			__sCurPage;
	char			__cResult, __cBitNum;
	unsigned short	__usLockRegions = 0x0000;
	
	
	//* 先将数据写入FLASH锁存缓冲器。因为数据手册表明不允许写入8位或16位数据,所以这里必须按照32位进行数据
	//* 写入。在写入锁存缓冲器之前先对据大小进行32位对齐运算。
	__nSize = (int)ALIGN32(nSize);
	
	__punTo = (unsigned int*)unTo;
	
	//* 如果指定的写入地址超出了FLASH的结束地址或者写入的数据超出了FLASH存储容量,函数立即返回,不再继续写入。
	//* 如果指定的FLASH地址并不是页面起始地址,同样视为无效地址
	if((__punTo > (unsigned int*)AT91C_IFLASH_ENDADDR) 
		|| (__punTo < (unsigned int*)AT91C_IFLASH)
		|| (((unsigned int*)AT91C_IFLASH_ENDADDR - __punTo) < __nSize)
		|| (unTo & FLASG_PAGE_SIZE_MASK))
		return ERR_WFLASH_INVALID_ADDR;
	
	//* 开始页编程
	__punNextFrom = punFrom;
	__punNextTo = __punTo;
	__sCurPage = ((unsigned int)__punNextTo - (unsigned int)AT91C_IFLASH) / FLASH_PAGE_SIZE;
	do{
		__nTotalSizeNotToWrite = __nSize - __nTotalSizeToWrite;
		__nCurSizeToWrite = (FLASH_PAGE_SIZE < __nTotalSizeNotToWrite) ? FLASH_PAGE_SIZE:__nTotalSizeNotToWrite;
		
		//* 解锁当前页面
		if(!DFL_PageUnlock(__sCurPage))
			return ERR_WFLASH_UNLOCK;								
		
		if((__cResult = __DFL_WritePage(__sCurPage, cIsLocked, __punNextFrom, __nCurSizeToWrite)) != ERR_WFLASH_OK)
			return __cResult;
			
		__punNextFrom = (unsigned int*)((unsigned int)__punNextFrom + __nCurSizeToWrite);
		
		//* 设置锁定区域位
		if(cIsLocked)
		{
			__cBitNum = __sCurPage / PAGES_PER_LOCK_REGION;
			__usLockRegions |= 1 << __cBitNum;
		}
		
		__nTotalSizeToWrite += __nCurSizeToWrite;
		__sCurPage++;
	}while(__nTotalSizeToWrite < __nSize);
	
	//* 锁定页面
	if(cIsLocked)
	{
		for(__cBitNum=0; __cBitNum<FLASH_LOCK_REGIONS_NB; __cBitNum++)
		{
			if(__usLockRegions & (1 << __cBitNum))
				DFL_PageLock(__cBitNum * PAGES_PER_LOCK_REGION);
		}
	}
	
	return (unsigned int)__punTo;
}

⌨️ 快捷键说明

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