📄 fmd.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
#include <fmd.h>
#include "nand.h"
#define MAX_PAGE_SIZE 2112
extern FLASH_CHIP_STRU g_stFlashChipInfo;
/*******************************************************************************
Function: BMM_TranslateInfo
Description: 本接口用于块信息(BMM信息和SECTOR信息)与SpareArea之间的转换
Input: 1、SpareArea缓冲区指针
2、BMM信息缓冲区指针
3、SECTOR信息缓冲区指针
4、转换类型
Output: 转换生成的数据
Return: FMD_SUCCESS:操作成功;
其他:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
DWORD BMM_TranslateInfo(PSectorInfo pSectorInfoBuff, LPBYTE pSectorBuff, DWORD dwTranslateType)
{
unsigned char ucTempBuf[8] = {0};
/*参数判断*/
if(SPAREAREA_TO_BLOCKINFO == dwTranslateType)
{
/*根据SpareArea的实际结构从中获取相应的SECTORINFO信息;*/
if(NULL != pSectorInfoBuff)
{
ucTempBuf[0] = *(pSectorBuff);
ucTempBuf[1] = *(pSectorBuff + 1);
ucTempBuf[2] = *(pSectorBuff + 5);
ucTempBuf[3] = *(pSectorBuff + 6);
ucTempBuf[4] = *(pSectorBuff + 7);
ucTempBuf[5] = *(pSectorBuff + 13);
ucTempBuf[6] = *(pSectorBuff + 16);
ucTempBuf[7] = *(pSectorBuff + 17);
memcpy((UINT8*)pSectorInfoBuff, ucTempBuf, 8);
}
}
else
{
/*根据SpareArea的实际结构将相应的SECTORINFO信息写入到SpareArea对应位置中;*/
if(NULL != pSectorInfoBuff)
{
memcpy(ucTempBuf, (UINT8*)pSectorInfoBuff, 8);
*(pSectorBuff) = ucTempBuf[0];
*(pSectorBuff + 1) = ucTempBuf[1];
*(pSectorBuff + 5) = ucTempBuf[2];
*(pSectorBuff + 6) = ucTempBuf[3];
*(pSectorBuff + 7) = ucTempBuf[4];
*(pSectorBuff + 13) = ucTempBuf[5];
*(pSectorBuff + 16) = ucTempBuf[6];
*(pSectorBuff + 17) = ucTempBuf[7];
}
}
return FMD_SUCCESS;
}
/*******************************************************************************
Function: FMD_Init
Description: 本接口用于FMD设备初始化
Input: 1、注册表项
2、FLASH结构体(pRegIn)
Output: 1、FLASH结构体(pRegOut)
2、物理扇区空闲区地址
Return: 设备句柄
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
PVOID FMD_Init(void)
{
DWORD dwFlashID = 0;
g_stFlashChipInfo.pBaseAddress = 0;
g_stFlashChipInfo.dwPhyIntr = NANDC_PHY_INTRRUPT;
g_stFlashChipInfo.dwNandcBaseAddr = NANDC_DATA_BASE_ADDR;
g_stFlashChipInfo.SectorSize = NF_SECTOR_SIZE;
g_stFlashChipInfo.SectorsPerBlock = NF_SECTORS_PER_BLOCK;
g_stFlashChipInfo.SpareSize = NF_SPARE_SIZE;
g_stFlashChipInfo.bRunWithIntr = FALSE;
g_stFlashChipInfo.BlockSize = g_stFlashChipInfo.SectorSize*g_stFlashChipInfo.SectorsPerBlock;
g_stFlashChipInfo.pNvBlock = (PBYTE)MemAlloc(g_stFlashChipInfo.BlockSize);
g_stFlashChipInfo.pfnCheckOrgBadBlock = NULL;
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO: FMD_Init]:pBaseAddress=0x%x.\r\n"), (ULONG)g_stFlashChipInfo.pBaseAddress));
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO: FMD_Init]:dwNandcBaseAddr=0x%x.\r\n"), (ULONG)g_stFlashChipInfo.dwNandcBaseAddr));
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO: FMD_Init]:dwPhyIntr=0x%x.\r\n"), (ULONG)g_stFlashChipInfo.dwPhyIntr));
if(FMD_SUCCESS != NF_Init(&dwFlashID))
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_Init]: NF_Init.\r\n")));
return NULL;
}
if(MT29F2G16ABD == dwFlashID)
{
g_stFlashChipInfo.pfnCheckOrgBadBlock = CheckMT29FBadBlock;
}
if(!ReplaceBadBlockSign())
{
return NULL;
}
if(!InitNv())
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR InitNv]FMD_Init : InitNv Nv region is not ready.\r\n")));
}
return((PVOID)g_stFlashChipInfo.TotalBlockNumbers);
}
/*******************************************************************************
Function: FMD_Deinit
Description: 本接口用于去初始化FMD设备
Input: 由FMD_Init返回的句柄
Output: none
Return: TRUE:操作成功;
FALSE:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
BOOL FMD_Deinit(PVOID pBaseAddress)
{
return(TRUE);
}
/*******************************************************************************
Function: FMD_GetInfo
Description: 本接口用于读取FLASH中BLOCK SIZE大小等参数信息
Input: FLASH信息缓冲区指针
Output: FLASH信息
Return: TRUE:操作成功;
FALSE:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO FMD_GetInfo]: TotalFlashBlocks = 0x%x\r\n"),g_stFlashChipInfo.TotalBlockNumbers));
pFlashInfo->flashType = NAND;
pFlashInfo->dwNumBlocks = g_stFlashChipInfo.TotalBlockNumbers;
pFlashInfo->dwBytesPerBlock = g_stFlashChipInfo.BlockSize;
pFlashInfo->wDataBytesPerSector = (WORD)g_stFlashChipInfo.SectorSize;
pFlashInfo->wSectorsPerBlock = (WORD)g_stFlashChipInfo.SectorsPerBlock;
return(TRUE);
}
#if 0
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetInfoEx
Description: Determines the size characteristics for the Flash memory device.
Includes support for multiple regions.
Notes: If pFlashInfo is NULL, then this just returns the number of reserved regions.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL FMD_GetInfoEx(PFlashInfoEx pFlashInfo, PDWORD pdwNumRegions)
{
pFlashInfo->cbSize = sizeof(FlashInfoEx);
pFlashInfo->flashType = NAND;
pFlashInfo->dwNumBlocks = g_stFlashChipInfo.TotalBlockNumbers;
pFlashInfo->dwDataBytesPerSector = (WORD)g_stFlashChipInfo.SectorSize;
pFlashInfo->dwNumRegions = 1;
return(TRUE);
}
#endif
/*******************************************************************************
Function: FMD_GetPhysSectorAddr
Description: 本接口用于读取FLASH指定逻辑扇区的实际扇区地址
Input: 逻辑扇区地址
Output: 实际扇区地址
Return: none
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
VOID FMD_GetPhysSectorAddr (DWORD dwSector, PSECTOR_ADDR pStartSectorAddr)
{
}
/*******************************************************************************
Function: FMD_ReadSector
Description: 本接口用于把从一个扇区开始的一段地址的数据读取出来
Input: 1、起始扇区地址
2、数据缓冲区指针
3、扇区信息缓冲区指针
4、待读取的扇区数
Output: 扇区数据
Return: TRUE:操作成功;
FALSE:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
DWORD i = 0;
DWORD ret = 0;
BOOL bLastMode = FALSE;
BYTE pcSectorBuf[MAX_PAGE_SIZE] = {0};
volatile SECTOR_ADDR physicalSectorAddr = 0;
volatile SECTOR_ADDR physicalSectorInfoAddr = 0;
volatile DWORD Size = 0;
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO FMD_ReadSector]:startSectorAddr = 0x%x\r\n"), startSectorAddr));
//----- 1. Check the input parameters -----
// NOTE: The FAL insures that the starting sector address is in the allowable range.
if((dwNumSectors == 0) || ((pSectorBuff == NULL) && (pSectorInfoBuff == NULL)))
{
return(FALSE);
}
for(i = startSectorAddr ; i < (startSectorAddr + dwNumSectors) ; i++)
{
//----- Compute the physical address for the requested -----
physicalSectorAddr = g_stFlashChipInfo.pBaseAddress*2 + i*NF_SECTOR_ADDR_SHIFT;
physicalSectorInfoAddr = physicalSectorAddr + g_stFlashChipInfo.SectorSize;
if(NULL != pSectorBuff)
{
/*调用NF_PageRead读取SECTOR的MainArea的数据;*/
ret = NF_PageRead(physicalSectorAddr, pcSectorBuf, (g_stFlashChipInfo.SectorSize+g_stFlashChipInfo.SpareSize));
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_ReadSector]:NF_PageRead Error!physicalSectorAddr = 0x%x,ret = 0x%x\r\n"), physicalSectorAddr, ret));
return FALSE;
}
memcpy(pSectorBuff, pcSectorBuf, g_stFlashChipInfo.SectorSize);
pSectorBuff+=g_stFlashChipInfo.SectorSize;
if(NULL != pSectorInfoBuff)
{
/*调用BMM_TranslateInfo转换SpareArea成SECTOR信息;*/
ret = BMM_TranslateInfo(pSectorInfoBuff, pcSectorBuf+g_stFlashChipInfo.SectorSize, SPAREAREA_TO_BLOCKINFO);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[NANDFMD:FMD_ReadSector]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
pSectorInfoBuff++;
}
}
else if(NULL != pSectorInfoBuff)
{
/*调用NF_PageRead读取SECTOR的SpareArea的数据(此时不会出现ECC纠正错误NF_ECC_CORRECT_ERROR);*/
ret = NF_PageRead(physicalSectorInfoAddr, g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_ReadSector]:NF_PageRead SpareArea Error!ret = 0x%x\r\n"),ret));
return FALSE;
}
/*调用BMM_TranslateInfo转换SpareArea成SECTOR信息;*/
ret = BMM_TranslateInfo(pSectorInfoBuff, g_stFlashChipInfo.pucSpareArea, SPAREAREA_TO_BLOCKINFO);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_ReadSector]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
pSectorInfoBuff++;
}
}
return(TRUE);
}
/*******************************************************************************
Function: FMD_WriteSector
Description: 本接口用于写一块缓冲区的内容到从一个扇区开始的一段地址中
Input: 1、起始扇区地址
2、数据缓冲区指针
3、扇区信息缓冲区指针
4、待写入的扇区数
Output: none
Return: TRUE:操作成功;
FALSE:操作不成功;
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
DWORD i = 0;
DWORD ret = 0;
BOOL bLastMode = FALSE;
BYTE pcSectorBuf[MAX_PAGE_SIZE] = {0};
volatile SECTOR_ADDR physicalSectorAddr = 0;
volatile SECTOR_ADDR physicalSectorInfoAddr = 0;
OALMSG(ZONE_FMD_OPS, (TEXT("[INFO FMD_WriteSector]:startSectorAddr = 0x%x\r\n"), startSectorAddr));
//----- 1. Check the input parameters -----
// NOTE: The FAL insures that the starting sector address is in the allowable range.
if((dwNumSectors == 0) || ((pSectorBuff == NULL) && (pSectorInfoBuff == NULL)))
{
return FALSE;
}
for(i = startSectorAddr; i < (startSectorAddr + dwNumSectors); i++)
{
physicalSectorAddr = g_stFlashChipInfo.pBaseAddress*2 + i*NF_SECTOR_ADDR_SHIFT;
physicalSectorInfoAddr = physicalSectorAddr + g_stFlashChipInfo.SectorSize;
if(NULL != pSectorBuff)
{
memset(pcSectorBuf+g_stFlashChipInfo.SectorSize, 0xFF, g_stFlashChipInfo.SpareSize);
if(NULL != pSectorInfoBuff)
{
ret = BMM_TranslateInfo(pSectorInfoBuff, pcSectorBuf+g_stFlashChipInfo.SectorSize, BLOCKINFO_TO_SPAREAREA);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_WriteSector]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return FALSE;
};
pSectorInfoBuff++;
};
memcpy(pcSectorBuf, pSectorBuff, g_stFlashChipInfo.SectorSize);
/*调用NF_PageProgram写入扇区的MainArea;*/
ret = NF_PageProgram(physicalSectorAddr, pcSectorBuf, g_stFlashChipInfo.SectorSize+g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR,(TEXT("[ERROR FMD_WriteSector]:NF_PageProgram Error!ret = 0x%x\r\n"), ret));
return FALSE;
};
pSectorBuff += g_stFlashChipInfo.SectorSize;
}
else if(NULL != pSectorInfoBuff)
{
/*调用BMM_TranslateInfo转换SECTOR信息成SpareArea信息;*/
memset(g_stFlashChipInfo.pucSpareArea, 0xFF, g_stFlashChipInfo.SpareSize);
ret = BMM_TranslateInfo(pSectorInfoBuff, g_stFlashChipInfo.pucSpareArea, BLOCKINFO_TO_SPAREAREA);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR, (TEXT("[ERROR FMD_WriteSector]:BMM_TranslateInfo Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
/*调用NF_PageProgram写入扇区的SpareArea;*/
ret = NF_PageProgram(physicalSectorInfoAddr, g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
{
OALMSG(ZONE_FMD_ERR,(TEXT("[ERROR FMD_WriteSector]:NF_PageProgram Error!ret = 0x%x\r\n"), ret));
return FALSE;
}
pSectorInfoBuff++;
};
}
return TRUE;
}
/*******************************************************************************
Function: FMD_GetBlockStatus
Description: 本接口用于读取块状态
Input: 待操作块地址
Output: none
Return: 块状态
History:
1. Created by chenbiyao on 2006/04/09
2. .....
*******************************************************************************/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
ULONG ulBlock = 0;
DWORD ret = 0;
DWORD dwStatus = 0;
ulBlock = g_stFlashChipInfo.pBaseAddress/g_stFlashChipInfo.BlockSize + blockID;
/*调用NF_PageRead读取SpareArea信息;*/
ret = NF_PageRead(ulBlock*g_stFlashChipInfo.SectorsPerBlock*NF_SECTOR_ADDR_SHIFT + g_stFlashChipInfo.SectorSize,
g_stFlashChipInfo.pucSpareArea, g_stFlashChipInfo.SpareSize);
if(FMD_SUCCESS != ret)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -