📄 spansion29lv320d_1x16.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_1x16.h"
//
// Definitions for Flash erasing.
//
#define FLASH_BLOCK_SIZE 0x20000 //128KB
#define FLASH_BLOCK_SIZE_WORD 0x10000 //64KW
//
//
//
static volatile PUSHORT gpulCurAddr = 0;
static volatile PUSHORT gpulBaseAddr = (PUSHORT)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_1x16(void)
{
DWORD iIdx;
// Query 16 bitwidth id.
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_READ_ID;
gdwManufactureId = *(gpulBaseAddr + AMD_VENDORID_ADDR);
// Query 32 bitwidth flash.
*(gpulBaseAddr + AMD_QUERY_ADDR) = AMD_READ_QUERY;
gdwFlashSize = 1 << (*(gpulBaseAddr + 0x27) & 0xFF);
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;
}
// Put the FLASH into read array mode.
*gpulBaseAddr = AMD_RESET;
EdbgOutputDebugString
(
"Flash Query: Nor Flash ID %x,size %x \r\n",
gdwManufactureId,gdwFlashSize
);
if(gdwManufactureId == 0x0001)
{
return TRUE;
}
else
{
EdbgOutputDebugString
(
"Flash Query: Nor Flash ID %x is not AMD \r\n",gdwManufactureId
);
return FALSE;
}
}
BOOL GotEraseFlashSectorIndex_1X16(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_1X16(void)
{
DWORD dwBlockSize;
dwBlockSize = sBlockInfo[gdwCurEraseRegion].block_size;
return dwBlockSize;
}
BOOL StartEraseSpansion29LV320D_1x16(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_1X16(dwStartAddr))
{
EdbgOutputDebugString
(
"ERROR: Address %x is not on a flash block boundary.\r\n",
dwStartAddr
);
return FALSE;
}
dwStartEraseAddr = dwStartAddr;
dwStartEraseLength = dwLength;
return TRUE;
}
void ContinueEraseSpansion29LV320D_1x16(void)
{
}
BOOL AmdFlashEraseSector_1X16(DWORD dwEraseBase,DWORD dwEraseLen)
{
ULONG ulStart;
int iResult = FLASH_ERR_OK;
int timeout=0;
int i=0;
// Send erase block command - six step sequence
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_SETUP_ERASE;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(gpulBaseAddr + (dwEraseBase >> 1)) = 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 >> 1))) & AMD_SECTOR_ERASE_TIMER)
== AMD_SECTOR_ERASE_TIMER)
break;
if( GetSystemTimeInMsec() > ulStart + 10000 )
{
EdbgOutputDebugString("Erase Sector TimeOut\n");
gpulBaseAddr[0] = 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)
{
for(i=0;i<dwEraseLen/2;i++)
{
if (0xffff != *(gpulBaseAddr + (dwEraseBase >> 1)+i))
{
EdbgOutputDebugString("Erase Sector error %x\n",i);
iResult= FLASH_ERR_DRV_TIMEOUT;
break;
}
}
}
if (FLASH_ERR_OK != iResult)
{
gpulBaseAddr[0] = AMD_RESET;
}
return TRUE;
}
BOOL FinishEraseSpansion29LV320D_1x16 (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 = gdwFlashSize;//dwStartEraseLength;
DWORD dwEraseBase = dwStartEraseAddr-FLASH_VIRTUAL_MEMORY;
for(i = gdwCurEraseRegion; i < gdwNumEraseRegion; i++)
{
for(j = gdwCurEraseBlock; j< sBlockInfo[i].blocks; j++)
{
if(dwEraseLen > (sBlockInfo[i].block_size))
{
dwEraseLen = dwEraseLen - (sBlockInfo[i].block_size );
if(AmdFlashEraseSector_1X16(dwEraseBase,sBlockInfo[i].block_size)==FALSE)
{
EdbgOutputDebugString("error 1");
return FALSE;
}
else
dwEraseBase = dwEraseBase + (sBlockInfo[i].block_size );
EdbgOutputDebugString(".");
}
else
{
if(AmdFlashEraseSector_1X16(dwEraseBase,sBlockInfo[i].block_size)==FALSE)
{
EdbgOutputDebugString("error 2");
return FALSE;
}
else
{
EdbgOutputDebugString("\n");
return TRUE;
}
}
}
}
return FALSE;
#endif
}
BOOL WriteSpansion29LV320D_1x16(DWORD dwDest, DWORD dwSource, DWORD dwLength)
{
ULONG ulStart;
PUSHORT pDataBuffer = (PUSHORT) dwSource;
#if 0
DWORD noffset;
//
// Save off the start address and the length.
//
gpulCurAddr = (PUSHORT) 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,iIdx0;
int iResult = FLASH_ERR_OK;
DWORD timeout;
DWORD dwOffset = dwDest-FLASH_VIRTUAL_MEMORY;
//
// Save off the start address and the length.
//
gpulCurAddr = (PUSHORT) dwDest;
/*
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = 0x0020;
*/
for(iIdx = 0; iIdx < (dwLength+1)/2; iIdx++)
{
// Send program block command - four step sequence
/*
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_PROGRAM;
*/
*(gpulBaseAddr + AMD_SETUP_ADDR1) = AMD_SETUP_CODE1;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = AMD_SETUP_CODE2;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = 0x0020;
*(gpulBaseAddr + 0) = 0x00a0;
*(gpulBaseAddr + (dwOffset >> 1) + iIdx) = *(pDataBuffer + iIdx);
timeout = 10000000;
ulStart = GetSystemTimeInMsec();
// for(iIdx0 = 0; iIdx0 < 100; iIdx0++){}
while (1)
{
if ( *(pDataBuffer + iIdx) == *(gpulBaseAddr + (dwOffset >> 1) + iIdx))
break;
// Can't check for FLASH_Err since it'll fail in parallel
// configurations.
if (--timeout == 0) {
iResult = FLASH_ERR_DRV_TIMEOUT;
break;
}
}
//for(iIdx0 = 0; iIdx0 < 50; iIdx0++){}
if (FLASH_ERR_OK != iResult)
{
*gpulBaseAddr = AMD_RESET;
EdbgOutputDebugString("word/2 Write TimeOut:addre=%x value=%x %x\n",
(gpulBaseAddr + (dwOffset >> 1) + iIdx),*(gpulBaseAddr + (dwOffset >> 1) + iIdx),*(pDataBuffer + iIdx));
//return FALSE;
}
if (*(gpulBaseAddr + (dwOffset >>1) + iIdx) != *(pDataBuffer + iIdx) )
{
// Only update return value if erase operation was OK
if (FLASH_ERR_OK == iResult)
iResult = FLASH_ERR_DRV_VERIFY;
EdbgOutputDebugString("word/2 Write error:address=%x value=%x trueValue=%x\n",
(gpulBaseAddr + (dwOffset >> 1) + iIdx),*(gpulBaseAddr + (dwOffset >> 1) + iIdx),*(pDataBuffer + iIdx));
//break;
}
//EdbgOutputDebugString(".");
*(gpulBaseAddr + AMD_SETUP_ADDR1) = 0x0090;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = 0x0000;
}
//for(iIdx0 = 0; iIdx0 < 100; iIdx0++){}
//gpulBaseAddr[0] = AMD_RESET;
*(gpulBaseAddr + AMD_SETUP_ADDR1) = 0x0090;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = 0x0000;
for(iIdx = 0; iIdx < (dwLength+1)/2; iIdx++)
{
if ( *(pDataBuffer + iIdx) != *(gpulBaseAddr + (dwOffset >> 1) + iIdx))
{
EdbgOutputDebugString("word/2 Write error:addre=%x value=%x should value=%x\n",
(gpulBaseAddr + (dwOffset >> 1) + iIdx),
*(gpulBaseAddr + (dwOffset >> 1) + iIdx),
*(pDataBuffer + iIdx));
}
}
gpulBaseAddr[0] = AMD_RESET;
EdbgOutputDebugString("write finished\n");
return TRUE;
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -