📄 drv_29lv160.c
字号:
int cLength, iRawWiteLen;
volatile _U16 *flashPtr;
volatile _U16 *gBuffer;
#ifdef DRV_DEBUG_FLASH
int i;
#endif
flashPtr = (volatile _U16 *)ulFlashAddr;
cLength = (int)((ulLength + 1)/2); /* 计算半字长度. */
iRawWiteLen = cLength;
gBuffer = (_U16 *)ulRamAddr;
#ifdef DRV_DEBUG_FLASH
(void)Drv_Print("\r\n Write 0x%x, from 0x%x, size is 0x%x", ulFlashAddr, ulRamAddr, ulLength);
#endif
while( cLength > 0 )
{
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_14CYC_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_25CYC_WORD_ADDR) = DRV_29LV160_25CYC_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_PROGRAM_CMD;
*flashPtr = *gBuffer;
/* 检测写入是否成功. */
if(Drv_29LV160_Detect( (_U16 *)flashPtr, *gBuffer) )
{
#ifdef DRV_DEBUG_FLASH
(void)Drv_Print("\r\n warning: write flash may failed at:0x%x.", (int)flashPtr);
return FAILURE;
#endif
}
cLength--;
flashPtr++;
gBuffer++;
/* 每block清狗4次 */
if( cLength%(iRawWiteLen/4) == 0 )
{
if( funcgDrvFeedDogHook != NULL )
{
funcgDrvFeedDogHook();
}
Drv_FeedHardWatchDog();
}
}
#ifdef DRV_DEBUG_FLASH
flashPtr = (volatile _U16 *)ulFlashAddr;
gBuffer = (_U16 *)ulRamAddr;
cLength = ulLength/2;
for( i = 0; i < cLength; i++) /*写入的数据全部校验一次.*/
{
if( *flashPtr++ != *gBuffer++ )
{
(void)Drv_Print("\r\n Error(%d): write failed in SST39vf160 at 0x%x on verification.",
__LINE__, (int)flashPtr);
return FAILURE;
}
}
if( ulLength%2 )
{
if( (*flashPtr++ & 0x00ff) != (*gBuffer++ & 0x00ff) ) /*奇数长度的最后一个字节.*/
{
(void)Drv_Print("\r\n Error(%d): write failed in SST39vf160 at 0x%x on verification.",
__LINE__, (int)flashPtr);
return FAILURE;
}
}
#endif
Drv_29LV160Reset();
return SUCCESS;
}
/* 可能会报告擦除检测失败,原因在于检测时间太短,正常擦除全部2M需要30秒,我们的检测时间只有5秒 */
void Drv_29LV160EraseChip(void)
{
#ifdef DRV_DEBUG_FLASH
volatile _U16 *flashPtr = NULL;
int i;
#endif
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_14CYC_CMD; /*连续解锁.*/
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_25CYC_WORD_ADDR) = DRV_29LV160_25CYC_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_ERASE_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_14CYC_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_25CYC_WORD_ADDR) = DRV_29LV160_25CYC_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_ERASE_CHIP_CMD; /*写入擦除命令.*/
if( Drv_29LV160_Detect((_U16 *)FLASH_START_ADDR, 0xffff) != SUCCESS )
{
#ifdef DRV_DEBUG_FLASH
(void)Drv_Print("\r\n warning: Chip Erase time out!");
#endif
}
#ifdef DRV_DEBUG_FLASH
/* 校验是否全为0xffff. */
flashPtr = (volatile _U16 *)FLASH_START_ADDR;
for( i = 0; i < FLASH_SIZE; i += 2, flashPtr++ )
{
if( *flashPtr != 0xffff )
{
(void)Drv_Print("\r\n Debug: Erase failed at 0x%x. Read value is 0x%x.", (int)flashPtr, *flashPtr);
Drv_29LV160Reset();
return;
}
}
#endif
Drv_29LV160Reset();
return;
}
void Drv_29LV160EraseBlock(_U32 ulBlockBaseAddr)
{
#ifdef DRV_DEBUG_FLASH
volatile _U16 *flashPtr = NULL;
int i;
#endif
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_14CYC_CMD; /*连续解锁.*/
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_25CYC_WORD_ADDR) = DRV_29LV160_25CYC_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_ERASE_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_1346CYC_WORD_ADDR) = DRV_29LV160_14CYC_CMD;
*((volatile _U16 *)FLASH_START_ADDR + DRV_29LV160_25CYC_WORD_ADDR) = DRV_29LV160_25CYC_CMD;
*(volatile _U16 *)ulBlockBaseAddr = DRV_29LV160_ERASE_SECTOR_CMD;
if( Drv_29LV160_Detect((_U16 *)ulBlockBaseAddr, 0xffff) != SUCCESS )
{
#ifdef DRV_DEBUG_FLASH
(void)Drv_Print("\r\n warning: Chip Erase time out!\n");
#endif
return;
}
#ifdef DRV_DEBUG_FLASH
/* 校验是否全为0xffff. */
flashPtr = (volatile _U16 *)ulBlockBaseAddr;
for( i = 0; i < DRV_29LV160_BLOCK_SIZE/2; i += 2, flashPtr++ )
{
if( *flashPtr != 0xffff )
{
(void)Drv_Print("\r\n Debug: Erase failed at 0x%x. Read value is 0x%x.", (int)flashPtr, *flashPtr);
Drv_29LV160Reset();
return;
}
}
#endif
Drv_29LV160Reset();
return;
}
void Drv_29LV160Read(_U32 ulFlashAddr, _U32 ulLength, _U32 ulRamAddr)
{
if (ulLength > FLASH_SIZE)
{
return;
}
memcpy((void *)ulRamAddr, (void *)ulFlashAddr, ulLength);
}
void Drv_29LV160Reset(void)
{
*(volatile _U16 *)(FLASH_START_ADDR) = DRV_29LV160_RESET_CMD;
return;
}
_U32 Drv_ReadFlash(_U32 ulFlashAddr, _U32 ulLength, _U32 ulRamAddr)
{
if (ucgDrvFlashDebugFlag != 0)
{
(void)Drv_Print("\r\n Read flash 0x%x, length is 0x%x, to 0x%x.",
ulFlashAddr, ulLength, ulRamAddr);
}
Drv_29LV160Reset();
Drv_29LV160Read(ulFlashAddr, ulLength, ulRamAddr);
return SUCCESS;
}
_U32 Drv_WriteFlash(_U32 ulFlashAddr, _U32 ulLength, _U32 ulRamAddr)
{
long WriteCount = 0;
_U8 *pSrc, *pDst, *pTmp;
_U32 ulAddrBlockEdge, ulWriteLen = 0, ulCurBlockSize;
if( ucgDrvFlashDebugFlag != 0 )
{
(void)Drv_Print( "\r\n Write flash 0x%x, length is 0x%x, from 0x%x.",
ulFlashAddr, ulLength, ulRamAddr );
}
if( (ulFlashAddr < FLASH_START_ADDR)
||(ulFlashAddr > FLASH_END_ADDR) )
{
(void)Drv_Print("\r\n Input flash address error, FlashAddr = 0x%lx", ulFlashAddr);
return FAILURE;
}
/* Get input parameter */
pTmp = (_U8 *)ulFlashAddr;
pSrc = (_U8 *)ulRamAddr;
WriteCount = (long)ulLength;
while( WriteCount > 0 )
{
/* Block size will change by address */
ulCurBlockSize = Drv_29LV160GetBlockSize( (_U32)pTmp );
/* Get current writing flash block address */
ulAddrBlockEdge = ( (_U32)pTmp & ~(ulCurBlockSize - 1) );
/* Read current block to BlockMapMem */
if (Drv_ReadFlash( ulAddrBlockEdge, ulCurBlockSize, (_U32)aucgBlockMapMem) != SUCCESS )
{
(void)Drv_Print("\r\n ReadFlash error!");
return FAILURE;
}
/* Get writing ram address(in ram), offset from 0 to ByteCount */
pSrc = (_U8 *)(pSrc + ulWriteLen);
/* Get writing block address(in aucgBlockMapMem), because ulAddrBlockEdge in block,
so offset is (ulFlashAddr - ulAddrBlockEdge), base is aucgBlockMapMem.
aucgBlockMapMem is map of flash in block */
pDst = (_U8 *)(ulFlashAddr - ulAddrBlockEdge + aucgBlockMapMem);
/* Get write count */
if( (_U32)WriteCount + ulFlashAddr - ulAddrBlockEdge >= ulCurBlockSize )
{
ulWriteLen = ulAddrBlockEdge + ulCurBlockSize - ulFlashAddr;
}
else
{
/* If last block, only write remain content */
ulWriteLen = (_U32)WriteCount;
}
/* If content is same in a block, no erase no write */
if( memcmp(pDst, pSrc, ulWriteLen) != 0 )
{
memcpy((char *)pDst, (char *)pSrc, ulWriteLen);
if( funcgDrvFeedDogHook != NULL )
{
funcgDrvFeedDogHook();
}
Drv_FeedHardWatchDog();
Drv_29LV160EraseBlock( ulAddrBlockEdge );
if( funcgDrvFeedDogHook != NULL )
{
funcgDrvFeedDogHook();
}
Drv_FeedHardWatchDog();
if( Drv_29LV160Write(ulAddrBlockEdge, ulCurBlockSize, (_U32)aucgBlockMapMem) != SUCCESS )
{
return FAILURE;
}
}
pTmp = (_U8 *)(ulAddrBlockEdge + ulCurBlockSize);
WriteCount -= (long)ulWriteLen;
ulFlashAddr += ulWriteLen;
}
return SUCCESS;
}
_U32 Drv_FlashTestWrite( _U8 *FlashAddr, _U32 ByteCount, _U8 *RamAddr )
{
return Drv_29LV160Write((_U32)FlashAddr, (_U32)ByteCount, (_U32)RamAddr);
}
_U32 Drv_FlashDebug(_U32 ulDebugFlag)
{
if (ulDebugFlag == 0)
{
ucgDrvFlashDebugFlag = 0;
}
else
{
ucgDrvFlashDebugFlag = 1;
}
return 0;
}
_U32 Drv_WriteFlashDelay( _U32 FlashAddr, _U32 ByteCount, _U32 RamAddr )
{
return Drv_WriteFlash(FlashAddr, ByteCount, RamAddr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -