加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Nandflash 驱动移植 (四)

发布时间:2020-12-15 18:24:34 所属栏目:百科 来源:网络整理
导读:Nandflash驱动移植系列文章导航: Nandflash 驱动移植 (一) Nandflash 驱动移植 (二) Nandflash 驱动移植 (三) Nandflash 驱动移植 (四) Nandflash 驱动移植 (五) Nandflash 驱动移植 (六) 一共六篇 ? ? ? 接着上一篇,这一篇介绍cpp部分 fmd.cp

Nandflash驱动移植系列文章导航:

Nandflash 驱动移植 (一)

Nandflash 驱动移植 (二)

Nandflash 驱动移植 (三)

Nandflash 驱动移植 (四)

Nandflash 驱动移植 (五)

Nandflash 驱动移植 (六)

一共六篇

?

?

?

接着上一篇,这一篇介绍cpp部分


fmd.cpp,这里将逐个函数进行分析讲解:


//
 // 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.
 //
 #include <fmd.h>
 #include <nkintr.h>
 #include <oal.h>
 
 // BSP Configuration Files
 #include "bsp_cfg.h"
 #include "bsp_base_reg_cfg.h"
 
 // Base Definitions
 #include "s3c6410_base_regs.h"
 #include "s3c6410_nand.h"
 #include "s3c6410_syscon.h"
 
 //#include <ethdbg.h>
 #include "Cfnand.h"
 //#include <kitl.h>
 
 //#define SYNC_OP
 #define CHECK_SPAREECC    (0)  // 1 gjl 
 #define NAND_DEBUG        (0)
 
 #define NAND_BASE        (0xB0200000)    // PA:0x70200000
 #define SYSCON_BASE        (0xB2A0F000)    // PA:0x7E00F000
 
 #ifdef    SYNC_OP
 CRITICAL_SECTION    g_csNandFlash;
 #endif
 
 #ifdef __cplusplus    // gjl
 extern "C" {
  int iSighForSlcMlc;   // gjl 
 }
 #endif
 
 static volatile S3C6410_NAND_REG *g_pNFConReg = NULL;
 static volatile S3C6410_SYSCON_REG *g_pSysConReg = NULL;
 
 #define DEBUG_WRITE_READ_EQUAL 0
 
 #if DEBUG_WRITE_READ_EQUAL
 DWORD g_MECCBuf[8];
 DWORD g_MECCBuf_R[8];
 DWORD g_SECCBuf[2];
 DWORD g_SECCBuf_R[2];
 #endif
 
 extern "C"
 {
     void RdPage512(unsigned char *bufPt);
     void RdPage512Unalign(unsigned char *bufPt);
     void WrPage512(unsigned char *bufPt);
     void WrPage512Unalign(unsigned char *bufPt);
     void WrPageInfo(PBYTE pBuff);
     void RdPageInfo(PBYTE pBuff);
 }
 
 NANDDeviceInfo GetNandInfo(void) { return stDeviceInfo; }

引用头文件这部分不需要更改


1、读取Flash的ID:

 /*
     @func   DWORD | ReadFlashID | Reads the flash manufacturer and device codes.
     @rdesc  Manufacturer and device codes.
     @comm
     @xref
 */
 static DWORD ReadFlashID(void)
 {
     BYTE Mfg,Dev,Nouse,Infoma,Planesize;
     int i;
 
     NF_nFCE_L();                // Deselect the flash chip.
     NF_CMD(CMD_READID);        // Send flash ID read command.
 
     NF_ADDR(0);
 
     for (i=0; i<10; i++)
     {
         Mfg    = NF_RDDATA_BYTE();
         if (Mfg == 0xEC || Mfg == 0x98) break;
     }
 
     Dev    = NF_RDDATA_BYTE();
     Nouse    = NF_RDDATA_BYTE();
     Infoma   = NF_RDDATA_BYTE();
     Planesize = NF_RDDATA_BYTE();
     //RETAILMSG(1,(TEXT("[FMD:ERR] FMD_Init() : page info = 0x%08x,0x%08x,0x%08xn"),Planesize));
     //According to the read ID from flash,Nouse=0x14,Infoma=0xa5,planesize=0x64,the page size is 2K,block size is 256KB
     //there are 4096 blocks,plane num=2,plane size=4Gbit
     //So we should change the cfnand.h nandflash information.
     NF_nFCE_H();
 
     return ((DWORD)(Mfg<<8)+Dev);
 }
这个也不需要修改,具体请参照手册


2、flash初始化:

 /*
     @func   PVOID | FMD_Init | Initializes the Smart Media NAND flash controller.
     @rdesc  Pointer to S3C2410 NAND controller registers.
     @comm
     @xref
 */
 
 PVOID FMD_Init(LPCTSTR lpActiveReg,PPCI_REG_INFO pRegIn,PPCI_REG_INFO pRegOut)
 {
     volatile DWORD nNandID;
     UINT8 nMID,nDID;
     UINT32 nCnt;
     BOOL bNandExt = FALSE;
 
 	RETAILMSG(1,(TEXT("[FMD] ++FMD_Init() *######rn")));
 
 
 
 	
 
     if (pRegIn && pRegIn->MemBase.Num && pRegIn->MemBase.Reg[0])
     {
         g_pNFConReg = (S3C6410_NAND_REG *)(pRegIn->MemBase.Reg[0]);
     }
     else
     {
         g_pNFConReg = (S3C6410_NAND_REG *)NAND_BASE;
     }
 
     g_pSysConReg = (S3C6410_SYSCON_REG *)SYSCON_BASE;
 
 #ifdef    SYNC_OP
     InitializeCriticalSection(&g_csNandFlash);
 
     EnterCriticalSection(&g_csNandFlash);
 #endif
 
     // Configure BUS Width and Chip Select for NAND Flash
     g_pSysConReg->MEM_SYS_CFG &= ~(1<<12);    // NAND Flash BUS Width -> 8 bit
     g_pSysConReg->MEM_SYS_CFG &= ~(0x1<<1);    // Xm0CS2 -> NFCON CS0
 
     // Set up initial flash controller configuration.
     g_pNFConReg->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
     NF_ECCTYPE_4BIT();
     g_pNFConReg->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
     g_pNFConReg->NFSTAT = (1<<4);
 
     nNandID = ReadFlashID();
 
 #ifdef    SYNC_OP
     LeaveCriticalSection(&g_csNandFlash);
 #endif
 
     nMID = (UINT8)(nNandID >> 8);
     nDID = (UINT8)(nNandID & 0xff);
 
     RETAILMSG(1,(TEXT("[FMD:INF] FMD_Init() : Read ID = 0x%08xn"),nNandID));
 
     for (nCnt = 0; astNandSpec[nCnt].nMID != 0; nCnt++)
     {
         if (nDID == astNandSpec[nCnt].nDID)
         {
             bNandExt = TRUE;
             break;
         }
     }
 
     if (!bNandExt)
     {
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_Init() : Unknown ID = 0x%08xn"),nNandID));
         return NULL;
     }
 
     NUM_OF_BLOCKS = astNandSpec[nCnt].nNumOfBlks;
     PAGES_PER_BLOCK = astNandSpec[nCnt].nPgsPerBlk;
     SECTORS_PER_PAGE = astNandSpec[nCnt].nSctsPerPg;
 
 
 	
     RETAILMSG(1,(TEXT("[FMD] FMD_Init() : NUM_OF_BLOCKS = %dn"),NUM_OF_BLOCKS));
     RETAILMSG(1,(TEXT("[FMD] FMD_Init() : PAGES_PER_BLOCK = %dn"),PAGES_PER_BLOCK));
     RETAILMSG(1,(TEXT("[FMD] FMD_Init() : SECTORS_PER_PAGE = %dn"),SECTORS_PER_PAGE));
 
 	// gjl
 	if(iSighForSlcMlc == 1)
 	{
     		NUM_OF_BLOCKS = 8192;
     		PAGES_PER_BLOCK = 8;
     		SECTORS_PER_PAGE = 4;
 	}
 	else
 	{
 			NUM_OF_BLOCKS = astNandSpec[nCnt].nNumOfBlks;
 			PAGES_PER_BLOCK = astNandSpec[nCnt].nPgsPerBlk;
 			SECTORS_PER_PAGE = astNandSpec[nCnt].nSctsPerPg;
 
 	}
 
     RETAILMSG(1,(TEXT("[FMD] --FMD_Init()n")));
 
     return((PVOID)g_pNFConReg);
 }

上面这个代码是原BSP中的,这个初始化函数里面,有些东西需要修改一下

// Set up initial flash controller configuration.
g_pNFConReg->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);

这个我们对照手册看一下


NFCONF[0]必须写0,NFCONF[2]必须写1,所以最后修改为:

g_pNFConReg->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4) | (1<<2) | (0<<0);

这一句接下来,原代码中使用的是NF_ECCTYPE_4BIT(); ?4bit的ECC,这里我们将使用8bit的ECC,修改为

NF_ECCTYPE_8BIT();		// use 8bit ECC


接下来初始化配置NFCONT

原:

g_pNFConReg->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);

参照手册修改为:

g_pNFConReg->NFCONT = (0<<13)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);


接下来直接看到

	// gjl
 	if(iSighForSlcMlc == 1)
 	{
     		NUM_OF_BLOCKS = 8192;
     		PAGES_PER_BLOCK = 8;
     		SECTORS_PER_PAGE = 4;
 	}
 	else
 	{
 			NUM_OF_BLOCKS = astNandSpec[nCnt].nNumOfBlks;
 			PAGES_PER_BLOCK = astNandSpec[nCnt].nPgsPerBlk;
 			SECTORS_PER_PAGE = astNandSpec[nCnt].nSctsPerPg;
 
 	}
这里if中的NUM_OF_BLOCKS = 8192;这个定死了,不大好,咱改成(修改之后,可以同时兼容K9GAG08U0D 2G和K9LBG08U0D 4G的Nandflash)
NUM_OF_BLOCKS = astNandSpec[nCnt].nNumOfBlks;

到此,FMD_Init()函数就基本上搞掂了。


3、FMD_ReadSector()

 /*
     @func   BOOL | FMD_ReadSector | Reads the specified sector(s) from NAND flash.
     @rdesc  TRUE = Success,FALSE = Failure.
     @comm
     @xref
 */
 BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr,LPBYTE pSectorBuff,PSectorInfo pSectorInfoBuff,DWORD dwNumSectors)
 {
     BOOL bRet;
 
     //RETAILMSG(1,(TEXT("[R:0x%08x] n"),startSectorAddr));
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] ++FMD_ReadSector(0x%08x) n"),startSectorAddr));
 #endif
 
 #ifdef    SYNC_OP
     EnterCriticalSection(&g_csNandFlash);
 #endif
 
     if ( IS_LB )
     {
         bRet = FMD_LB_ReadSector(startSectorAddr,pSectorBuff,pSectorInfoBuff,dwNumSectors);
     }
     else
     {
         bRet = FMD_SB_ReadSector(startSectorAddr,dwNumSectors);
     }
 
 #ifdef    SYNC_OP
     LeaveCriticalSection(&g_csNandFlash);
 #endif
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] --FMD_ReadSector()n")));
 #endif
 
     return bRet;
 }
这里我们不需要做修改,不过其中调用的FMD_LB_ReadSector()函数待会需要修改一下(FMD_LB_ReadSector()是针对Nandflash,4bit或8bit的ECC;而FMD_SB_ReadSector()是针对Norflash,1bit的ecc校验)



4、FMD_EraseBlock() ?擦除块

 /*
     @func   BOOL | FMD_EraseBlock | Erases the specified flash block.
     @rdesc  TRUE = Success,FALSE = Failure.
     @comm
     @xref
 */
 BOOL FMD_EraseBlock(BLOCK_ID blockID)
 {
     BOOL    bRet = TRUE;
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] ++FMD_EraseBlock(0x%08x) n"),blockID));
 #endif
 
 #ifdef    SYNC_OP
     EnterCriticalSection(&g_csNandFlash);
 #endif
 
     if ( IS_LB )
     {
         bRet = FMD_LB_EraseBlock(blockID);
     }
     else
     {
         bRet = FMD_SB_EraseBlock(blockID);
     }
 
 #ifdef    SYNC_OP
     LeaveCriticalSection(&g_csNandFlash);
 #endif
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] --FMD_EraseBlock()n")));
 #endif
 
     return bRet;
 }

这个函数也没有什么需要修改的,其中调用到的FMD_LB_EraseBlock()待会会讲到。



5、FMD_WriteSector()

 /*
     @func   BOOL | FMD_WriteSector | Writes the specified data to the specified NAND flash sector/page.
     @rdesc  TRUE = Success,FALSE = Failure.
     @comm
     @xref
 */
 BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr,DWORD dwNumSectors)
 {
     BOOL    bRet = TRUE;
 #if DEBUG_WRITE_READ_EQUAL
 	BYTE    pSectorBuffRead[4096]; // gjl 2048
 	SectorInfo    SectorInfoBuffRead;
 	PSectorInfo    pSectorInfoBuffRead = &SectorInfoBuffRead;
 	BYTE     *temp = (BYTE*)pSectorInfoBuff;
 	BYTE     *temp1 = (BYTE*)pSectorInfoBuffRead;
 	UINT16 nSectorLoop,j=40;
 #endif
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] ++FMD_WriteSector(0x%08x) n"),startSectorAddr));
 #endif
 
 #ifdef    SYNC_OP
     EnterCriticalSection(&g_csNandFlash);
 #endif
 
     if ( IS_LB )
     {
         bRet = FMD_LB_WriteSector(startSectorAddr,dwNumSectors);
 #if DEBUG_WRITE_READ_EQUAL
 		FMD_LB_ReadSector(startSectorAddr,pSectorBuffRead,pSectorInfoBuffRead,dwNumSectors);
 		for (nSectorLoop = 0; nSectorLoop < 2048; nSectorLoop++)
 		{
 			if(pSectorBuff[nSectorLoop] != pSectorBuffRead[nSectorLoop])
 				break;
 		}
 		RETAILMSG(1,(TEXT("[FMD] ++FMD_WriteSector equal number = %x n"),nSectorLoop));
 		for (nSectorLoop = 0; nSectorLoop < 8; nSectorLoop++)
 		{
 			if(temp1[nSectorLoop] != temp[nSectorLoop])
 				break;
 		}
 		RETAILMSG(1,(TEXT("[FMD] ++FMD_WriteSector informationequal equal number = %x n"),nSectorLoop));
 		RETAILMSG(1,(TEXT("[FMD] ++FMD_WriteSector sector bytes:n")));
 		for (nSectorLoop = 0; nSectorLoop < 2048; nSectorLoop++)
 		{
 			if(j--==0)
 			{
 				j=40;
 				RETAILMSG(1,(TEXT("n")));
 			}
 			RETAILMSG(1,(TEXT("%x "),pSectorBuff[nSectorLoop]));
 		}
 		RETAILMSG(1,(TEXT("n endn")));
 		RETAILMSG(1,(TEXT("[FMD] ++FMD_ReadSector sector bytes:n")));
 		for (nSectorLoop = 0; nSectorLoop < 2048; nSectorLoop++)
 		{
 			if(j--==0)
 			{
 				j=40;
 				RETAILMSG(1,pSectorBuffRead[nSectorLoop]));
 		}
 		RETAILMSG(1,(TEXT("n endn")));
 		for (nSectorLoop = 0; nSectorLoop < 8; nSectorLoop++)
 		{
 			if(g_MECCBuf_R[nSectorLoop] != g_MECCBuf[nSectorLoop])
 				break;
 		}
 		RETAILMSG(1,(TEXT("[FMD] ++FMD_WriteSector MECC data equal number = %x n"),nSectorLoop));
 		for (nSectorLoop = 0; nSectorLoop < 8; nSectorLoop++)
 		{
 			if(g_SECCBuf_R[nSectorLoop] != g_SECCBuf[nSectorLoop])
 				break;
 		}
 		RETAILMSG(1,(TEXT("[FMD] ++FMD_WriteSector SECC data equal number = %x n"),nSectorLoop));
 		
 #endif
     }
     else
     {
         bRet = FMD_SB_WriteSector(startSectorAddr,(TEXT("[FMD] --FMD_WriteSector()n")));
 #endif
 
     return bRet;
 }

该函数也没有什么地方需要修改的。



6、FMD_PowerUp()

VOID FMD_PowerUp(VOID)
 {
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] FMD_PowerUp() n")));
 #endif
 
     // Set up initial flash controller configuration.
     g_pNFConReg->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
     g_pNFConReg->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
     g_pNFConReg->NFSTAT = (1<<4);
 }

这里我们参照之前在FMD_Init()的配置,修改其中的NFCONF和NFCONT的配置为:

g_pNFConReg->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4) | (1<<2) | (0<<0);
g_pNFConReg->NFCONT = (0<<13)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);



7、FMD_PowerDown()

VOID FMD_PowerDown(VOID)
 {
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] FMD_PowerDown() n")));
 #endif
 
 }

该函数不需要修改什么。



接下来的这几个函数都不需要修改:

BOOL FMD_OEMIoControl(DWORD dwIoControlCode,PBYTE pInBuf,DWORD nInBufSize,PBYTE pOutBuf,DWORD nOutBufSize,PDWORD pBytesReturned)
 {
     switch(dwIoControlCode)
     {
         case IOCTL_FMD_GET_INTERFACE:
         {
             RETAILMSG(1,(TEXT("[FMD] FMD_OEMIoControl() : IOCTL_FMD_GET_INTERFACEn")));
 
             if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
             {
                 DEBUGMSG(1,(TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_INTERFACE bad parameter(s).n")));
                 return(FALSE);
             }
 
             PFMDInterface pInterface = (PFMDInterface)pOutBuf;
 
             pInterface->cbSize = sizeof(FMDInterface);
             pInterface->pInit = FMD_Init;
             pInterface->pDeInit = FMD_Deinit;
             pInterface->pGetInfo = FMD_GetInfo;
             pInterface->pGetInfoEx = NULL;        //FMD_GetInfoEx;
             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 = NULL;
 
             break;
         }
 
     case IOCTL_FMD_LOCK_BLOCKS:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_LOCK_BLOCKS Not Supportedn")));
         return FALSE;
 
     case IOCTL_FMD_UNLOCK_BLOCKS:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_UNLOCK_BLOCKS Not Supportedn")));
         return FALSE;
 
     case IOCTL_FMD_READ_RESERVED:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_READ_RESERVEDn")));
         return FALSE;
 
     case IOCTL_FMD_WRITE_RESERVED:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_WRITE_RESERVEDn")));
         return FALSE;
 
     case IOCTL_FMD_GET_RESERVED_TABLE:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RESERVED_TABLEn")));
         return FALSE;
 
     case IOCTL_FMD_SET_REGION_TABLE:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_REGION_TABLEn")));
         return FALSE;
 
     case IOCTL_FMD_SET_SECTORSIZE:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_SECTORSIZEn")));
         return FALSE;
 
     case IOCTL_FMD_RAW_WRITE_BLOCKS:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_RAW_WRITE_BLOCKSn")));
         return FALSE;
 
     case IOCTL_FMD_GET_RAW_BLOCK_SIZE:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RAW_BLOCK_SIZEn")));
         return FALSE;
 
     case IOCTL_FMD_GET_INFO:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_INFOn")));
         return FALSE;
 
     case  IOCTL_FMD_SET_XIPMODE    :
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_XIPMODEn")));
         return FALSE;
 
     case  IOCTL_FMD_GET_XIPMODE:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_XIPMODEn")));
         return FALSE;
 
     case  IOCTL_DISK_FLUSH_CACHE:
         //RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_DISK_FLUSH_CACHEn")));
         return TRUE;
 
     default:
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_OEMIoControl() : Unknown IOCTL (0x%08x)n"),dwIoControlCode));
         return FALSE;
     }
 
     return TRUE;
 }
 
 BOOL FMD_Deinit(PVOID hFMD)
 {
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] FMD_Deinit() n")));
 #endif
 
     return(TRUE);
 }
 
 
 /*
     @func   BOOL | FMD_GetInfo | Provides information on the NAND flash.
     @rdesc  TRUE = Success,FALSE = Failure.
     @comm
     @xref
 */
 BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
 {
 	// Add by AlexLee RunNo[5]
     UINT32  nCnt;
     UINT32 nNandID;
     UINT8 nMID,nDID;
 
     if (pFlashInfo == NULL)
     {
         RETAILMSG(1,(TEXT("[FMD:ERR] FMD_GetInfo() : Invalid Parametern")));
         return(FALSE);
     }
 
     pFlashInfo->flashType = NAND;
 
 #ifdef    SYNC_OP
     EnterCriticalSection(&g_csNandFlash);
 #endif
 
     nNandID = ReadFlashID();
 
 #ifdef    SYNC_OP
     LeaveCriticalSection(&g_csNandFlash);
 #endif
 
     nMID = nNandID >> 8;
     nDID = nNandID & 0xff;
 
     for (nCnt = 0; astNandSpec[nCnt].nMID != 0; nCnt++)
     {
         if (nDID == astNandSpec[nCnt].nDID)
         {
             break;
         }
     }
 
     //  OK,instead of reading it from the chip,we use the hardcoded
     //  numbers here.
 
     pFlashInfo->dwNumBlocks         = NUM_OF_BLOCKS;
     pFlashInfo->wSectorsPerBlock    = PAGES_PER_BLOCK;
     pFlashInfo->wDataBytesPerSector = NAND_SECTOR_SIZE;
     pFlashInfo->dwBytesPerBlock     = (PAGES_PER_BLOCK * NAND_SECTOR_SIZE);
 
     //RETAILMSG(1,(TEXT("[FMD] FMD_GetInfo() : NUMBLOCKS = %d(0x%x),SECTORSPERBLOCK = %d(0x%x),BYTESPERSECTOR = %d(0x%x) n"),pFlashInfo->dwNumBlocks,pFlashInfo->wSectorsPerBlock,pFlashInfo->wDataBytesPerSector,pFlashInfo->wDataBytesPerSector)); // del by alexlee
 
     return TRUE;
 }
 
 
 /*
     @func   DWORD | FMD_GetBlockStatus | Returns the status of the specified block.
     @rdesc  Block status (see fmd.h).
     @comm
     @xref
 */
 DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
 {
     DWORD dwResult = 0;
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] ++FMD_GetBlockStatus(0x%08x) n"),blockID));
 #endif
 
 #ifdef    SYNC_OP
     EnterCriticalSection(&g_csNandFlash);
 #endif
 
     if ( IS_LB )
     {
         dwResult = FMD_LB_GetBlockStatus(blockID);
     }
     else
     {
         dwResult = FMD_SB_GetBlockStatus(blockID);
     }
 
 #ifdef    SYNC_OP
     LeaveCriticalSection(&g_csNandFlash);
 #endif
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] --FMD_GetBlockStatus()n")));
 #endif
 
     return dwResult;
 }
 
 
 /*
     @func   BOOL | FMD_SetBlockStatus | Marks the block with the specified block status.
     @rdesc  TRUE = Success,FALSE = Failure.
     @comm
     @xref
 */
 BOOL FMD_SetBlockStatus(BLOCK_ID blockID,DWORD dwStatus)
 {
     BOOL    bRet = TRUE;
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] ++FMD_SetBlockStatus(0x%08x,0x%08x) n"),blockID,dwStatus));
 #endif
 
 #ifdef    SYNC_OP
     EnterCriticalSection(&g_csNandFlash);
 #endif
 
     if ( IS_LB )
     {
         bRet = FMD_LB_SetBlockStatus(blockID,dwStatus);
     }
     else
     {
         bRet = FMD_SB_SetBlockStatus(blockID,dwStatus);
     }
 
 #ifdef    SYNC_OP
     LeaveCriticalSection(&g_csNandFlash);
 #endif
 
 #if (NAND_DEBUG)
     RETAILMSG(1,(TEXT("[FMD] --FMD_SetBlockStatus()n")));
 #endif
 
     return bRet;
 }
 


文章有点长,先到这里了,关键点将在下一篇介绍

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读