Nandflash 驱动移植 (四)

来源:互联网 发布:java web开发流程图 编辑:程序博客网 时间:2024/05/22 16:38

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%08x\n"), Nouse,Infoma,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() *######\r\n")));          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%08x\n"), 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%08x\n"), 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 = %d\n"), NUM_OF_BLOCKS));     RETAILMSG(1, (TEXT("[FMD] FMD_Init() : PAGES_PER_BLOCK = %d\n"), PAGES_PER_BLOCK));     RETAILMSG(1, (TEXT("[FMD] FMD_Init() : SECTORS_PER_PAGE = %d\n"), 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, pSectorBuff, pSectorInfoBuff, 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, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, 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, pSectorBuff, pSectorInfoBuff, 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 end\n"))); RETAILMSG(1, (TEXT("[FMD] ++FMD_ReadSector sector bytes:\n"))); for (nSectorLoop = 0; nSectorLoop < 2048; nSectorLoop++) { if(j--==0) { j=40; RETAILMSG(1, (TEXT("\n"))); } RETAILMSG(1, (TEXT("%x "), pSectorBuffRead[nSectorLoop])); } RETAILMSG(1, (TEXT("\n end\n"))); 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, pSectorBuff, pSectorInfoBuff, dwNumSectors);     }  #ifdef    SYNC_OP     LeaveCriticalSection(&g_csNandFlash); #endif  #if (NAND_DEBUG)     RETAILMSG(1, (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_INTERFACE\n")));              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 Supported\n")));         return FALSE;      case IOCTL_FMD_UNLOCK_BLOCKS:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_UNLOCK_BLOCKS Not Supported\n")));         return FALSE;      case IOCTL_FMD_READ_RESERVED:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_READ_RESERVED\n")));         return FALSE;      case IOCTL_FMD_WRITE_RESERVED:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_WRITE_RESERVED\n")));         return FALSE;      case IOCTL_FMD_GET_RESERVED_TABLE:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RESERVED_TABLE\n")));         return FALSE;      case IOCTL_FMD_SET_REGION_TABLE:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_REGION_TABLE\n")));         return FALSE;      case IOCTL_FMD_SET_SECTORSIZE:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_SECTORSIZE\n")));         return FALSE;      case IOCTL_FMD_RAW_WRITE_BLOCKS:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_RAW_WRITE_BLOCKS\n")));         return FALSE;      case IOCTL_FMD_GET_RAW_BLOCK_SIZE:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RAW_BLOCK_SIZE\n")));         return FALSE;      case IOCTL_FMD_GET_INFO:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_INFO\n")));         return FALSE;      case  IOCTL_FMD_SET_XIPMODE    :         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_XIPMODE\n")));         return FALSE;      case  IOCTL_FMD_GET_XIPMODE:         RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_XIPMODE\n")));         return FALSE;      case  IOCTL_DISK_FLUSH_CACHE:         //RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_DISK_FLUSH_CACHE\n")));         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 Parameter\n")));         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->dwNumBlocks, pFlashInfo->wSectorsPerBlock, 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; } 


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


原创粉丝点击