📄 amd.c
字号:
// To see if DQ6 is toggling
if ((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ6_X16)) !=
(ulDataRead & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ6_X16))) {
// DQ6 is toggling
ERRORMSG(ZONE_HAL_ERROR,
(TEXT("Program failure [0x%x] 0x%x : expect 0x%x\r\n"),
ulProgramAddress, ulDataWritten, ulDataToWrite));
// Probably due to an attempt to program a 0 to 1.
ERRORMSG(ZONE_HAL_ERROR,
(TEXT("DQ6 is toggling. Probably due to an attempt to program a 0 to 1!\r\n"))) ;
bSuccess = FALSE;
}
}
}
} // end poll for datum prog done
// Check for prog timeout.
if (!bDone && (j == g_FlashProgInfo.ulMaxDatumProgTOFactor))
bSuccess = FALSE;
if (!bSuccess)
break;
// Since the polling needs to occur on the last datum programmed
// to the buffer the math to advance the pointers
// for next datum is left until now
pulData = (ULONG *)((ULONG)pulData + dwBusWidth);
ulProgramAddress += dwBusWidth;
} // End prog datum loop
if (g_FlashProgInfo.bUnlockBypassSupport) {
// Exit bypass mode
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_1_ADDR_RESET_BYPASS, CYCLE_1_DATA_RESET_BYPASS);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_2_ADDR_RESET_BYPASS, CYCLE_2_DATA_RESET_BYPASS);
}
}
// Use write buffer programming if at least 1 page of data to write
// and supported (write buffer size non zero).
// Refer to AMD's "Write buffer programming and page buffer read"
// application note for more details.
if (bSuccess && dwNumPages > 0) {
// Find start sector address and size
ulFlashSectorAddr = pFlashDesc->FlashBase;
bDone = FALSE;
for (ulCurRegion = 0;
!bDone && (ulCurRegion < pFlashDesc->Geometry.NumEraseBlockRegions);
ulCurRegion++) {
// Get erase block size
ulSectorSize = bIsPaired ?
2 * pFlashDesc->Geometry.EraseBlockInfo[ulCurRegion].EraseBlockSize * CFI_ERASE_BLOCK_SIZE_MULTP :
pFlashDesc->Geometry.EraseBlockInfo[ulCurRegion].EraseBlockSize * CFI_ERASE_BLOCK_SIZE_MULTP;
ulNumRegionBlocks = (ULONG)(pFlashDesc->Geometry.EraseBlockInfo[ulCurRegion].NumIdentEraseBlocks + 1);
for (ulCurBlock = 0; !bDone && (ulCurBlock < ulNumRegionBlocks); ulCurBlock++) {
DEBUGMSG(ZONE_HAL_FUNCTION,
(TEXT("ulFlashSectorAddr 0x%x\r\n"), ulFlashSectorAddr));
if ((ulProgramAddress >= ulFlashSectorAddr) &&
(ulProgramAddress < (ulFlashSectorAddr + ulSectorSize))) {
// Found sector, break
bDone = TRUE;
} else {
// Increment flash walk address
ulFlashSectorAddr += ulSectorSize;
}
}
}
// Program address may be middle of sector
ulSectorSize -= ulProgramAddress - ulFlashSectorAddr;
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("Sector 0x%x Size 0x%x\r\n"),
ulFlashSectorAddr, ulSectorSize));
ulBufDatumSize = bIsPaired ? (ulWriteBufferSize / sizeof(ULONG)) :
(ulWriteBufferSize / sizeof(USHORT));
for (i = 0; bSuccess && i < dwNumPages; i++) {
bDone = FALSE;
#ifdef DEBUG
ulPageStart = ulProgramAddress;
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("Page %d\r\n"), i));
for (j = 0; j < ulBufDatumSize; j++)
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("[0x%x] 0x%x\r\n"),
(ulPageStart + j), bIsPaired? *((volatile ULONG *)(ulPageStart + j)) :
*((volatile USHORT *)(ulPageStart + j))));
#endif
ulDataToWrite = bIsPaired? *(ULONG *)pulData : *(USHORT *)pulData;
if (bIgnore0to1) {
for(j = 0; j < (ulBufDatumSize); j++)
ulIgnoreBuffer[j] = bIsPaired ? *((volatile ULONG *)ulProgramAddress + j)
: *((volatile USHORT *)ulProgramAddress + j);
ulDataToWrite &= ulIgnoreBuffer[0];
}
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase, CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK) ;
WR_FLASH_REG_16(bIsPaired, ulProgramAddress, CYCLE_3_DATA_WR_BUFR);
WR_FLASH_REG_16(bIsPaired, ulProgramAddress, (ulBufDatumSize - 1));
WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
for (j = 0; j < (ulBufDatumSize - 1); j++) {
pulData = (ULONG *)((ULONG)pulData + dwBusWidth);
ulProgramAddress += dwBusWidth;
ulDataToWrite = bIsPaired? *(ULONG *)pulData : *(USHORT *)pulData;
if (bIgnore0to1)
ulDataToWrite &= ulIgnoreBuffer[j + 1];
WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
}
WR_FLASH_REG_16(bIsPaired, ulFlashSectorAddr, CYCLE_1_DATA_WR_BUFR_PROGRAM);
#ifdef USE_OS_SERVICES
for (j = 0; bSuccess && !bDone && j < g_FlashProgInfo.ulMaxBufferProgTOFactor; j++) {
StallExecution(g_FlashProgInfo.ulBufferProgTO_us);
#else
j = 0;
while (!bDone && bSuccess && j++ < CHECK_STATUS_TIMEOUT) {
#endif
ulDataWritten = bIsPaired? *((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("[0x%x] 0x%x : expect 0x%x\r\n"),
ulProgramAddress, ulDataWritten, ulDataToWrite));
if ((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16)) ==
(ulDataToWrite & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16))) {
if (ulDataWritten != ulDataToWrite) {
ulDataWritten = bIsPaired ? *((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("[0x%x] 0x%x : expect 0x%x\r\n"),
ulProgramAddress, ulDataWritten, ulDataToWrite));
if (ulDataWritten == ulDataToWrite) {
// page is programmed properly
bDone = TRUE;
} else {
// programming failure
ERRORMSG(ZONE_HAL_ERROR, (TEXT("program buffer failure [0x%x] 0x%x : expect 0x%x\r\n"),
ulProgramAddress, ulDataWritten, ulDataToWrite));
bSuccess = FALSE;
}
} else {
// page is programmed properly
bDone = TRUE;
}
} else {
if ((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ5_X16)) ==
CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ5_X16)) {
ulDataWritten = bIsPaired ? *((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
if ((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16)) !=
(ulDataToWrite & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16))) {
ERRORMSG(ZONE_HAL_ERROR, (TEXT("Program Buffer failure: Poll cnt %d [0x%x] 0x%x : expect 0x%x\r\n"),
j, ulProgramAddress, ulDataWritten, ulDataToWrite)) ;
bSuccess = FALSE;
}
} else if((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ1_X16))
== CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ1_X16)) {
ulDataWritten = bIsPaired ? *((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
if ((ulDataWritten & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16))
!= (ulDataToWrite & CREATE_MASK_16(bIsPaired, AMD_FLASH_DQ7_X16))) {
ERRORMSG(ZONE_HAL_ERROR, (TEXT("Program Buffer aborted: Poll cnt %d [0x%x] 0x%x : expect 0x%x\r\n"),
j, ulProgramAddress, ulDataWritten, ulDataToWrite)) ;
bSuccess = FALSE;
}
}
}
} // end page done poll
// Check for prog timeout.
#ifdef USE_OS_SERVICES
if (!bDone && j == g_FlashProgInfo.ulMaxBufferProgTOFactor)
#else
if (!bDone && j > CHECK_STATUS_TIMEOUT)
#endif
bSuccess = FALSE;
if (!bSuccess)
break;
if (bDone) {
#ifdef DEBUG
for (j = 0; j < ulBufDatumSize; j++)
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("[0x%x] 0x%x\r\n"),
(ulPageStart + j), bIsPaired? *((volatile ULONG *)(ulPageStart + j)) :
*((volatile USHORT *)(ulPageStart + j)) ));
#endif
// since the polling needs to occur on the last datum programmed
// to the buffer the math to advance the pointers
// for next page is left until now
ulLen -= ulWriteBufferSize;
pulData = (ULONG *)((ULONG)pulData + dwBusWidth);
ulProgramAddress += dwBusWidth;
ulSectorSize -= ulWriteBufferSize;
ulProgBytes += ulWriteBufferSize;
if (ulSectorSize == 0) {
// Next sector
ulFlashSectorAddr = ulProgramAddress;
ulCurBlock++;
if (ulCurBlock >= ulNumRegionBlocks) {
ulCurRegion++;
ulCurBlock = 0;
ulSectorSize = bIsPaired
? 2 * pFlashDesc->Geometry.EraseBlockInfo[ulCurRegion].EraseBlockSize * CFI_ERASE_BLOCK_SIZE_MULTP
: pFlashDesc->Geometry.EraseBlockInfo[ulCurRegion].EraseBlockSize * CFI_ERASE_BLOCK_SIZE_MULTP;
ulNumRegionBlocks = (ULONG)(pFlashDesc->Geometry.EraseBlockInfo[ulCurRegion].NumIdentEraseBlocks + 1);
}
DEBUGMSG(ZONE_HAL_FUNCTION, (TEXT("Sector 0x%x Size 0x%x\r\n"),
ulFlashSectorAddr, ulSectorSize));
}
}
} // end loop pages
}
//
// Tail unaligned bytes programming (Single word programming)
//
if (ulBufAlignTailBytes != 0) {
ulProgBytes = ulBufAlignTailBytes;
for (i = 0; i < ulProgBytes; i += dwBusWidth) {
bDone = FALSE;
ulDataToWrite = bIsPaired ? *(ULONG *)pulData : *(USHORT *)pulData;
if (bIgnore0to1) {
ulDataWritten = bIsPaired ?
*(volatile ULONG *)ulProgramAddress :
*(volatile USHORT *)ulProgramAddress;
ulDataToWrite &= ulDataWritten;
}
if (g_FlashProgInfo.bUnlockBypassSupport) {
// Send unlock bypass enter command for first datum
if (i == 0) {
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_3_ADDR_CMD_x16, CYCLE_3_DATA_UNLOCK_BYPASS);
}
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_1_ADDR_PROGRAM_BYPASS, CYCLE_1_DATA_PROGRAM_BYPASS);
WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
} else {
// 4 cycle per datum program
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_1_ADDR_UNLOCK_x16, CYCLE_1_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
CYCLE_2_ADDR_UNLOCK_x16, CYCLE_2_DATA_UNLOCK);
WR_FLASH_REG_INDEXED16(bIsPaired, ulFlashBase,
UNLOCK_ADDR1_x16, CYCLE_3_DATA_PROGRAM);
WR_FLASH_16(bIsPaired, ulProgramAddress, ulDataToWrite);
}
j = 0;
while (!bDone && bSuccess && (j++ < CHECK_STATUS_TIMEOUT)) {
// Read 1
ulDataWritten = bIsPaired ?
*((volatile ULONG *)(ulProgramAddress)) :
*((volatile USHORT *)(ulProgramAddress));
// D7 will be driven to complement of D7 written to the FLASH.
// When it is driven to the value just written,
// the program operation is complete.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -