📄 fmd.c
字号:
{
return BLOCK_STATUS_BAD;
}
/*调用BMM_TranslateInfo转换读取的SpareArea成SECTOR信息;*/
ret = BMM_TranslateInfo(&(g_stFlashChipInfo.stSectorInfo), g_stFlashChipInfo.pucSpareArea, SPAREAREA_TO_BLOCKINFO);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_GetBlockStatus]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return BLOCK_STATUS_BAD;
}
/*SECTOR信息中块状态是STATUS_READONLY*/
if(g_stFlashChipInfo.stSectorInfo.bBadBlock != 0xFF)
{
return BLOCK_STATUS_BAD;
}
/*SECTOR信息中块状态是STATUS_READONLY*/
if(!(g_stFlashChipInfo.stSectorInfo.bOEMReserved & OEM_BLOCK_READONLY))
{
dwStatus |= BLOCK_STATUS_READONLY;
}
/*SECTOR信息中块状态是STATUS_RESERVED*/
if(!(g_stFlashChipInfo.stSectorInfo.bOEMReserved & OEM_BLOCK_RESERVED))
{
dwStatus |= BLOCK_STATUS_RESERVED;
}
OALMSG(ZONE_FMD_OPS,(TEXT("[INFO FMD_GetBlockStatus]:blockID = 0x%x,dwStatus = 0x%x\r\n"), ulBlock, dwStatus));
return dwStatus;
}
/*******************************************************************************
Function: FMD_SetBlockStatus
Description: 本接口用于写块状态
Input: 1、待操作块地址
2、待操作块状态
Output: none
Return: TRUE:操作成功;
FALSE:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
DWORD ret = 0;
DWORD ulBlock = g_stFlashChipInfo.pBaseAddress/g_stFlashChipInfo.BlockSize + blockID;
/* 只支持设置为坏块 */
if(BLOCK_STATUS_BAD != dwStatus)
{
return FALSE;
}
/*调用NF_PageRead读取块信息;*/
ret = NF_PageRead(ulBlock*g_stFlashChipInfo.SectorsPerBlock*NF_SECTOR_ADDR_SHIFT + g_stFlashChipInfo.SectorSize,
g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_SetBlockStatus]:NF_PageRead Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
/*调用BMM_TranslateInfo转换SpareArea到SECTOR信息各标志位;*/
ret = BMM_TranslateInfo(&(g_stFlashChipInfo.stSectorInfo),g_stFlashChipInfo.pucSpareArea, SPAREAREA_TO_BLOCKINFO);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_SetBlockStatus]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
/*块状态是坏块标志*/
g_stFlashChipInfo.stSectorInfo.bBadBlock = 0x0;
/*调用BMM_TranslateInfo转换SECTOR信息各标志位到SpareArea;*/
memset(g_stFlashChipInfo.pucSpareArea, 0xFF, g_stFlashChipInfo.SpareSize);
ret = BMM_TranslateInfo(&(g_stFlashChipInfo.stSectorInfo), g_stFlashChipInfo.pucSpareArea, BLOCKINFO_TO_SPAREAREA);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_SetBlockStatus]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
/*调用NF_PageProgram写块的SpareArea;*/
ret = NF_PageProgram(blockID*g_stFlashChipInfo.SectorsPerBlock*NF_SECTOR_ADDR_SHIFT + g_stFlashChipInfo.SectorSize,
g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)/*出现坏块*/
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_SetBlockStatus]:NF_PageProgram Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
/*调用NF_PageRead读取块信息;*/
ret = NF_PageRead(ulBlock*g_stFlashChipInfo.SectorsPerBlock*NF_SECTOR_ADDR_SHIFT + g_stFlashChipInfo.SectorSize,
g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_SetBlockStatus]:NF_PageRead Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
/*调用BMM_TranslateInfo转换SpareArea到SECTOR信息各标志位;*/
ret = BMM_TranslateInfo(&(g_stFlashChipInfo.stSectorInfo),g_stFlashChipInfo.pucSpareArea, SPAREAREA_TO_BLOCKINFO);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_SetBlockStatus]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
if(0x0 != g_stFlashChipInfo.stSectorInfo.bBadBlock)
{
return FALSE;
}
return TRUE;
}
/*******************************************************************************
Function: FMD_EraseBlock
Description: 本接口用于擦除一个指定块的内容
Input: 待擦除块地址
Output: none
Return: TRUE:操作成功;
FALSE:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
volatile ULONG ulBlock = 0;
BOOL bRetVal = TRUE;
DWORD ret = 0;
ulBlock = g_stFlashChipInfo.pBaseAddress/g_stFlashChipInfo.BlockSize + blockID;
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO FMD_EraseBlock]: NF_BlockErase ulBlock = 0x%x.\r\n"), ulBlock));
ret = NF_BlockErase(ulBlock);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_EraseBlock]: NF_BlockErase ulBlock = 0x%x error = 0x%x\r\n"), ulBlock, ret));
bRetVal = FALSE;
}
return bRetVal;
}
/*******************************************************************************
Function: FMD_PowerUp
Description: 本接口用于完成FMD设备上电动作
Input: none
Output: none
Return: none
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
VOID FMD_PowerUp(VOID)
{
return;
}
/*******************************************************************************
Function: FMD_PowerDown
Description: 本接口用于完成FMD设备下电动作
Input: none
Output: none
Return: none
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
VOID FMD_PowerDown(VOID)
{
return;
}
/*******************************************************************************
Function: FMD_OEMIoControl
Description: 本接口用于写块状态
Input: 1、IOCTL命令
2、输入缓冲区指针
3、输入缓冲区数据长度
4、输出缓冲区指针
5、输出缓冲区数据长度
Output: 1、输出数据
2、输出数据长度
Return: TRUE:操作成功;
FALSE:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize,
PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO FMD_OEMIoControl]: base = 0x%x,dwIoControlCode = 0x%x.\r\n"),IOCTL_FMD_GET_INTERFACE,dwIoControlCode));
switch(dwIoControlCode)
{
case IOCTL_FMD_GET_INTERFACE:
{
if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_OEMIoControl]: IOCTL_FMD_GET_INTERFACE bad parameter(s).\r\n")));
return(FALSE);
}
PFMDInterface pInterface = (PFMDInterface)pOutBuf;
pInterface->cbSize = sizeof(FMDInterface);
pInterface->pInit = FMD_Init;
pInterface->pDeInit = FMD_Deinit;
pInterface->pGetInfo = FMD_GetInfo;
#if 0
pInterface->pGetInfoEx = FMD_GetInfoEx;
#endif
pInterface->pGetBlockStatus = FMD_GetBlockStatus;
pInterface->pSetBlockStatus = FMD_SetBlockStatus;
pInterface->pReadSector = FMD_ReadSector;
pInterface->pWriteSector = FMD_WriteSector;
pInterface->pEraseBlock = FMD_EraseBlock;
pInterface->pPowerUp = FMD_PowerUp;
pInterface->pPowerDown = FMD_PowerDown;
pInterface->pGetPhysSectorAddr = FMD_GetPhysSectorAddr;
//pInterface->pOEMIoControl = FMD_OEMIoControl;
break;
}
default:
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_OEMIoControl]: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
return(FALSE);
}
return(TRUE);
}
BOOL CheckMT29FBadBlock(BLOCK_ID blockID)
{
DWORD ret;
/*调用NF_PageRead读取Block第一个page的SpareArea信息;*/
ret = NF_PageRead(blockID*g_stFlashChipInfo.SectorsPerBlock*NF_SECTOR_ADDR_SHIFT + g_stFlashChipInfo.SectorSize,
g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR ReplaceBadBlockSign]: Unknown Block 0x%x status\r\n"), blockID));
return TRUE;
}
if(0xFF != g_stFlashChipInfo.pucSpareArea[0])
{
return TRUE;
}
/*调用NF_PageRead读取Block第后一个page的SpareArea信息;*/
ret = NF_PageRead(((blockID+1)*g_stFlashChipInfo.SectorsPerBlock-1)*NF_SECTOR_ADDR_SHIFT + g_stFlashChipInfo.SectorSize,
g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR ReplaceBadBlockSign]: Unknown Block 0x%x status last page\r\n"), blockID));
return TRUE;
}
if(0xFF != g_stFlashChipInfo.pucSpareArea[0])
{
return TRUE;
}
return FALSE;
}
BOOL CheckFlashFirstUse(void)
{
BYTE pcSector[MAX_PAGE_SIZE];
DWORD dwFirstDword;
// 如果第0个Block已经被使用
if(FMD_ReadSector(0, pcSector, NULL, 1))
{
memcpy(&dwFirstDword, pcSector, sizeof(dwFirstDword));
if(0xFFFFFFFF != dwFirstDword)
{
return FALSE;
}
}
// 如果第1个Block已经被使用
if(FMD_ReadSector(g_stFlashChipInfo.SectorsPerBlock, pcSector, NULL, 1))
{
memcpy(&dwFirstDword, pcSector, sizeof(dwFirstDword));
if(0xFFFFFFFF != dwFirstDword)
{
return FALSE;
}
}
return (FLASH_IS_NO_NV == CheckNV())?TRUE:FALSE;
}
/* replace MT29F2G16ABD nand flash bad block */
BOOL ReplaceBadBlockSign(void)
{
DWORD ui;
OALMSG(ZONE_FMD_OPS, ("[INFO ReplaceBadBlockSign] +\r\n"));
if(FALSE == CheckFlashFirstUse())
{
return TRUE;
}
OALMSG(ZONE_FMD_OPS, ("[INFO ReplaceBadBlockSign] Flash is first use\r\n"));
if(NULL == g_stFlashChipInfo.pfnCheckOrgBadBlock)
{
return TRUE;
}
for(ui=0; ui<g_stFlashChipInfo.TotalBlockNumbers; ui++)
{
//OALMSG(1, (TEXT("CHECK: Block 0x%x\r\n"), ui));
if(g_stFlashChipInfo.pfnCheckOrgBadBlock(ui))
{
OALMSG(ZONE_FMD_ERR, ("[INFO ReplaceBadBlockSign]: Original find a bad block = 0x%x\r\n", ui));
FMD_EraseBlock(ui);
if(FALSE == FMD_SetBlockStatus(ui, BLOCK_STATUS_BAD))
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR ReplaceBadBlockSign]: Original set bad 0x%x block error\r\n"), ui));
return FALSE;
}
}
}
//dwTickCount = GetPassedMicSec(dwTickCount);
//OALMSG(1, ("Check Flash Passed %d Time\r\n", dwTickCount));
OALMSG(ZONE_FMD_OPS, ("[INFO ReplaceBadBlockSign] -\r\n"));
return TRUE;
}
/*******************************************************************************
Function: CreateNv
Description: 本接口用于创建NV项区域
Input: none
Output: NV区域信息
Return: TRUE/FALSE
History:
1. Created by c56450 on 2006/04/09
2. .....
*******************************************************************************/
BOOL CreateNv(void)
{
DWORD i = 0;
DWORD j = 0;
SectorInfo stSectorInfo;
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO FMD]CreateNv : create a nv region.\r\n")));
g_stFlashChipInfo.bNvInitialFlag = FALSE;
memset(g_stFlashChipInfo.dwNvAddr, 0, sizeof(g_stFlashChipInfo.dwNvAddr));
memset(&stSectorInfo, 0xFF, sizeof(SectorInfo));
for(i=NV_START_BLOCK; i<(NV_START_BLOCK+NV_MAX_BLOCK); i++)
{
if (FMD_GetBlockStatus(i) & BLOCK_STATUS_BAD)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD]CreateNv : get block status find a bad block = %d.\r\n"), i));
continue;
}
if(FMD_SUCCESS != NF_BlockErase(i))
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD]CreateNv : NF_BlockErase find a bad block = %d.\r\n"), i));
FMD_SetBlockStatus(i, BLOCK_STATUS_BAD);
continue;
}
stSectorInfo.dwReserved1 = j;
if(!FMD_WriteSector(i*g_stFlashChipInfo.SectorsPerBlock, NULL, &stSectorInfo, 1))
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD]CreateNv : Error while FMD_WritePhySector, Sector = %d.\r\n"), i*g_stFlashChipInfo.SectorsPerBlock));
FMD_SetBlockStatus(i, BLOCK_STATUS_BAD);
continue;
}
g_stFlashChipInfo.dwNvAddr[j] = i;
if(++j == NV_BLOCK_NUM)
{
g_stFlashChipInfo.bNvInitialFlag = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -