📄 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_FLASH;
static DWORD dwStartEraseAddr = 0;
static DWORD dwStartEraseLength = 0;
//
//
//
extern DWORD gdwFlashSize ;
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;
//
//
//
BOOL 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;
}
return TRUE;
}
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)
{
//
// 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;
UINT 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();
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;
}
}
// 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)
{
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;
}
BOOL WriteSpansion29LV320D_1x16(DWORD dwDest, DWORD dwSource, DWORD dwLength)
{
ULONG ulStart;
PUSHORT pDataBuffer = (PUSHORT) dwSource;
DWORD iIdx;
int iResult = FLASH_ERR_OK;
DWORD timeout;
DWORD dwOffset = dwDest-FLASH_VIRTUAL_MEMORY;
//
// Save off the start address and the length.
//
gpulCurAddr = (PUSHORT) dwDest;
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) = 0x0020;
*(gpulBaseAddr + 0) = 0x00a0;
*(gpulBaseAddr + (dwOffset >> 1) + iIdx) = *(pDataBuffer + iIdx);
timeout = 10000000;
ulStart = GetSystemTimeInMsec();
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;
}
}
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));
}
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));
}
*(gpulBaseAddr + AMD_SETUP_ADDR1) = 0x0090;
*(gpulBaseAddr + AMD_SETUP_ADDR2) = 0x0000;
if( iIdx %20000 ==0 )
RETAILMSG(1,(L"."));
}
*(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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -