📄 spansion29lv320d_2x16.c
字号:
//**********************************************************************
//
// Filename: Spansion_1x16.c
//
// Description: Flashing program for Spansion Flash.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Use of this source code is subject to the terms of the Cirrus end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to
// use this source code. For a copy of the EULA, please see the
// EULA.RTF on your install media.
//
// Copyright(c) Cirrus Logic Corporation 2005, All Rights Reserved
//
//**********************************************************************
#include <windows.h>
#include <hwdefs.h>
#include <halether.h>
#include <debugtimer.h>
#include "spansion29lv320d_2x16.h"
//#define amdflash_debug 0
//
// Definitions for Flash erasing.
//
#define FLASH_BLOCK_SIZE 0x20000 //128KB
#define FLASH_BLOCK_SIZE_WORD 0x10000 //64KW
//
//
//
static volatile PULONG gpulCurAddr = 0;
static volatile PULONG gpulBaseAddr = (PULONG)PHYSICAL_ADDR_ASYNC_CS6;
static DWORD dwStartEraseAddr = 0;
static DWORD dwStartEraseLength = 0;
//
//
//
static DWORD gdwFlashSize =0;
static DWORD gdwManufactureId =0;
struct EraseBlockInfo sBlockInfo[4];
static DWORD gdwNumEraseRegion =0;
static DWORD gdwCurEraseRegion =0;
static DWORD gdwCurEraseBlock =0;
static DWORD gdwCurEraseBlockMask =0;
static DWORD gdwFlashBufferSize =64;
//
//
//
void AmdFlashSpansion29LV320D_2x16(void)
{
DWORD iIdx;
// Query 16 bitwidth id.
*(gpulBaseAddr + AMD_SETUP_ADDR1) = (AMD_SETUP_CODE1 << 16) | AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = (AMD_SETUP_CODE2 << 16) | AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = (AMD_READ_ID << 16) | AMD_READ_ID;
gdwManufactureId = ((*(gpulBaseAddr + AMD_VENDORID_ADDR) << 16)
| ((*(gpulBaseAddr + AMD_VENDORID_ADDR)) & 0xFFFF));
// Query 32 bitwidth flash.
*(gpulBaseAddr + AMD_QUERY_ADDR) = (AMD_READ_QUERY << 16) | AMD_READ_QUERY;
gdwFlashSize = 1 << (*(gpulBaseAddr + 0x27) & 0xFF);
gdwFlashSize = gdwFlashSize*2;
gdwNumEraseRegion = *(gpulBaseAddr + 0x2c) & 0xFFFF;
for(iIdx = 0; iIdx <gdwNumEraseRegion; iIdx++)
{
sBlockInfo[iIdx].blocks = (*(gpulBaseAddr + 0x2d + (iIdx<<2)) & 0xFFFF) + 1;
sBlockInfo[iIdx].block_size = (((*(gpulBaseAddr + 0x30 + (iIdx<<2)) & 0xFFFF) << 8) +
(*(gpulBaseAddr + 0x2f + (iIdx<<2)) & 0xFFFF)) << 8;
//sBlockInfo[iIdx].block_size = sBlockInfo[iIdx].block_size *2;
}
// Put the FLASH into read array mode.
*gpulBaseAddr = (AMD_RESET << 16) | AMD_RESET;
EdbgOutputDebugString
(
"Flash Query: Nor Flash ID %x,size %x,base add %x\r\n",
gdwManufactureId,gdwFlashSize,gpulBaseAddr
);
if(gdwManufactureId == 0x00010001)
{
return TRUE;
}
else
{
EdbgOutputDebugString
(
"Flash Query: Nor Flash ID %x is not AMD \r\n",gdwManufactureId
);
return FALSE;
}
}
BOOL GotEraseFlashSectorIndex_AMD(DWORD dwStartAddr)
{
DWORD i,j,dwEraseLen;
dwEraseLen = dwStartAddr-FLASH_VIRTUAL_MEMORY;
for(i = 0; i <gdwNumEraseRegion; i++)
{
for(j = 0; j< sBlockInfo[i].blocks; j++)
{
if(dwEraseLen > sBlockInfo[i].block_size)
{
dwEraseLen = dwEraseLen - sBlockInfo[i].block_size;
}
else if(dwEraseLen ==sBlockInfo[i].block_size)
{
gdwCurEraseRegion = i;
gdwCurEraseBlock = j;
return TRUE;
}
else
{
gdwCurEraseRegion = i;
gdwCurEraseBlock = j;
return FALSE;
}
}
}
return FALSE;
}
DWORD GetEraseFlashBlockSize_AMD(void)
{
DWORD dwBlockSize;
dwBlockSize = sBlockInfo[gdwCurEraseRegion].block_size;
return dwBlockSize;
}
BOOL StartEraseSpansion29LV320D_2x16(DWORD dwStartAddr, DWORD dwLength)
{
//
// Make sure that the flash addresses are valid.
//
if(dwStartAddr + dwLength >FLASH_VIRTUAL_MEMORY + gdwFlashSize ||
dwStartAddr < FLASH_VIRTUAL_MEMORY )
{
EdbgOutputDebugString
(
"ERROR: No Flash located in the locations from %x to %xr\r\n",
dwStartAddr,
dwLength
);
return FALSE;
}
//
// Check to make sure that the flash is on a Block boundary.
//
if(GotEraseFlashSectorIndex_AMD(dwStartAddr))
{
EdbgOutputDebugString
(
"ERROR: Address %x is not on a flash block boundary.\r\n",
dwStartAddr
);
return FALSE;
}
#ifdef amdflash_debug
EdbgOutputDebugString
(
"StartEraseFlashAMD_2x16 %x %x %x %x\r\n",
gdwCurEraseRegion,gdwCurEraseRegion,gdwCurEraseBlock,sBlockInfo[gdwCurEraseRegion].block_size
);
#endif
dwStartEraseAddr = dwStartAddr;
dwStartEraseLength = gdwFlashSize;//dwLength;
return TRUE;
}
void ContinueEraseSpansion29LV320D_2x16(void)
{
}
BOOL AmdFlashEraseSector(DWORD dwEraseBase)
{
ULONG ulStart;
int iResult = FLASH_ERR_OK;
// Send erase block command - six step sequence
*(gpulBaseAddr + AMD_SETUP_ADDR1) = (AMD_SETUP_CODE1 << 16) | AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = (AMD_SETUP_CODE2 << 16) | AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = (AMD_SETUP_ERASE << 16) | AMD_SETUP_ERASE;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = (AMD_SETUP_CODE1 << 16) | AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = (AMD_SETUP_CODE2 << 16) | AMD_SETUP_CODE2;
*(gpulBaseAddr + (dwEraseBase >> 2)) = (AMD_BLOCK_ERASE << 16) | AMD_BLOCK_ERASE;
// Now poll for the completion of the sector erase timer (50us)
ulStart = GetSystemTimeInMsec();
//timeout = 10000000; how many retries?
while (1)
{
if (((*(gpulBaseAddr + (dwEraseBase >> 2))) & AMD_SECTOR_ERASE_TIMER)
== AMD_SECTOR_ERASE_TIMER)
break;
if( GetSystemTimeInMsec() > ulStart + 10000 )
{
EdbgOutputDebugString("Erase Sector TimeOut\n");
gpulBaseAddr[0] = (AMD_RESET<<16)|AMD_RESET;
iResult = FLASH_ERR_DRV_TIMEOUT;
return FALSE;
}
// if (--timeout == 0)
// {
// iResult = FLASH_ERR_DRV_TIMEOUT;
// break;
// }
}
/*
// Then wait for erase completion.
if (FLASH_ERR_OK == iResult) {
timeout = 10000000;
while (1) {
if (0xffffffff == (*(ptr32 + (iSector >> 2)))) {
break;
}
// Don't check for FLASH_Err here since it will fail
// with devices in parallel because these may finish
// at different times.
if (--timeout == 0) {
iResult = FLASH_ERR_DRV_TIMEOUT;
break;
}
}
}
if (FLASH_ERR_OK != iResult)
*ptr32 = (AMD_RESET << 16) | AMD_RESET;
} else{
// No such parameter.
return 1;
*/
return TRUE;
}
BOOL FinishEraseSpansion29LV320D_2x16 (void)
{
#if 0
ULONG ulStart;
int BlockCount;
//
// Count the # of blocks need to erase.
//
BlockCount = ( dwStartEraseLength + (FLASH_BLOCK_SIZE - 1) ) / FLASH_BLOCK_SIZE;
//
// Save off the start address and the length.
//
gpusCurAddr = (PUSHORT) dwStartEraseAddr;
while(BlockCount--)
{
//
// Issue Sector Erase Command Sequence
//
gpusBaseAddr[LLD_UNLOCK_ADDR1] = NOR_UNLOCK_DATA1;
gpusBaseAddr[LLD_UNLOCK_ADDR2] = NOR_UNLOCK_DATA2;
gpusBaseAddr[LLD_UNLOCK_ADDR1] = NOR_ERASE_SETUP_CMD;
gpusBaseAddr[LLD_UNLOCK_ADDR1] = NOR_UNLOCK_DATA1;
gpusBaseAddr[LLD_UNLOCK_ADDR2] = NOR_UNLOCK_DATA2;
//
// Write Sector Erase Command to Offset
//
gpusCurAddr[0] = NOR_SECTOR_ERASE_CMD;
//
// Wait the toggle bit.
//
ulStart = GetSystemTimeInMsec();
while ((gpusBaseAddr[0] & 0x0080) != 0x0080)
{
if( GetSystemTimeInMsec() > ulStart + 10000 )
{
EdbgOutputDebugString("Erase Sector TimeOut\n");
gpusBaseAddr[0] = NOR_RESET_CMD;
return FALSE;
}
}
EdbgOutputDebugString(".");
gpusCurAddr += FLASH_BLOCK_SIZE_WORD;
}
EdbgOutputDebugString("\n");
return TRUE;
#else
DWORD i, j;
DWORD dwEraseLen = dwStartEraseLength;
DWORD dwEraseBase = dwStartEraseAddr-FLASH_VIRTUAL_MEMORY;
for(i = gdwCurEraseRegion; i < gdwNumEraseRegion; i++)
{
for(j = gdwCurEraseBlock; j< sBlockInfo[i].blocks; j++)
{
#ifdef amdflash_debug
EdbgOutputDebugString
(
"FinishEraseFlashC3_2x16 1:%x %x %x %x,Current %x %x \r\n",
i,j,sBlockInfo[i].block_size,sBlockInfo[i].blocks,
dwEraseLen,dwEraseBase
);
#endif
if(dwEraseLen > (sBlockInfo[i].block_size << 1))
{
dwEraseLen = dwEraseLen - (sBlockInfo[i].block_size << 1);
if(AmdFlashEraseSector(dwEraseBase)==FALSE)
return FALSE;
else
dwEraseBase = dwEraseBase + (sBlockInfo[i].block_size << 1);
EdbgOutputDebugString(".");
}
else
{
if(AmdFlashEraseSector(dwEraseBase)==FALSE)
return FALSE;
else
{
EdbgOutputDebugString("\n");
return TRUE;
}
}
}
}
return FALSE;
#endif
}
BOOL WriteSpansion29LV320D_2x16(DWORD dwDest, DWORD dwSource, DWORD dwLength)
{
ULONG ulStart;
PULONG pDataBuffer = (PULONG) dwSource;
#if 0
DWORD noffset;
//
// Save off the start address and the length.
//
gpulCurAddr = (PULONG) dwDest;
//
// Load Data into Buffer
//
for(noffset=0;noffset<(dwLength+1)/2;noffset++)
{
//
// Write one word data.
//
gpusBaseAddr[LLD_UNLOCK_ADDR1] = NOR_UNLOCK_DATA1;
gpusBaseAddr[LLD_UNLOCK_ADDR2] = NOR_UNLOCK_DATA2;
gpusBaseAddr[LLD_UNLOCK_ADDR1] = NOR_PROGRAM_CMD;
gpusCurAddr[noffset] = pDataBuffer[noffset];
//
// Print something to indicate still running.
//
if(( noffset & ( FLASH_BLOCK_SIZE_WORD -1 )) == 0 )
EdbgOutputDebugString(".");
//
// Wait for write finish.
//
ulStart = GetSystemTimeInMsec();
while ((gpusCurAddr[noffset] & 0x0080) != (pDataBuffer[noffset] & 0x0080))
{
if( GetSystemTimeInMsec() > ulStart + 10000 )
{
EdbgOutputDebugString("Word Write TimeOut\n");
gpusBaseAddr[0] = NOR_RESET_CMD;
return FALSE;
}
}
}
EdbgOutputDebugString("\n");
return TRUE;
#else
DWORD iIdx;
int iResult = FLASH_ERR_OK;
DWORD timeout;
DWORD dwOffset = dwDest-FLASH_VIRTUAL_MEMORY;
//
// Save off the start address and the length.
//
gpulCurAddr = (PULONG) dwDest;
#ifdef amdflash_debug
EdbgOutputDebugString
(
"WriteSpansion29LV320D_2x16 0:%x %x %x %x\r\n",
dwOffset,gpulBaseAddr,gpulCurAddr,dwLength
);
#endif
for(iIdx = 0; iIdx < (dwLength>>2); iIdx++)
{
// Send program block command - four step sequence
*(gpulBaseAddr + AMD_SETUP_ADDR1) = (AMD_SETUP_CODE1 << 16) | AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = (AMD_SETUP_CODE2 << 16) | AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = (AMD_PROGRAM << 16) | AMD_PROGRAM;
*(gpulBaseAddr + (dwOffset >> 2) + iIdx) = *(pDataBuffer + iIdx);
timeout = 10000000;
ulStart = GetSystemTimeInMsec();
while (1)
{
if (*(pDataBuffer + iIdx) == *(gpulBaseAddr + (dwOffset >> 2) + iIdx))
break;
// Can't check for FLASH_Err since it'll fail in parallel
// configurations.
if (--timeout == 0) {
iResult = FLASH_ERR_DRV_TIMEOUT;
break;
}
}
if (FLASH_ERR_OK != iResult)
{
*gpulBaseAddr = (AMD_RESET << 16) | AMD_RESET;
EdbgOutputDebugString("Word Write TimeOut\n");
return FALSE;
}
if (*(gpulBaseAddr + (dwOffset >> 2) + iIdx) != *(pDataBuffer + iIdx))
{
// Only update return value if erase operation was OK
if (FLASH_ERR_OK == iResult)
iResult = FLASH_ERR_DRV_VERIFY;
break;
}
#ifdef amdflash_debug
EdbgOutputDebugString(".");
EdbgOutputDebugString
(
"WriteSpansion29LV320D_2x16 1:%x %x \r\n",
iIdx,gpulBaseAddr
);
#endif
}
EdbgOutputDebugString("\n");
return TRUE;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -