📄 flash.c
字号:
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 + -