📄 fmd.cpp
字号:
// Read the bad block mark
pInfo->bBadBlock = (BYTE) ((rddata>>8) & 0xff);
// Second reserved field (WORD)
pInfo->wReserved2 = (WORD) ((rddata>>16) & 0xffff);
SetChipSelect(mode,HIGH);
SetKMode(bLastMode);
}
/*
* NAND_LB_WriteSectorInfo
*
* Write SectorInfo out to the spare area. The current implementation only handles
* one sector at a time.
*/
BOOL NAND_LB_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
volatile DWORD wrdata;
BOOL bRet = TRUE;
int NewSpareAddr = 2048 + 16*(sectorAddr%4);
int NewSectorAddr = sectorAddr/4;
BOOL bLastMode = SetKMode(TRUE);
// Chip enable
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Write the command
// First, let's point to the spare area
NF_CMD(CMD_WRITE);
// Write the address
NF_ADDR((NewSpareAddr)&0xff);
NF_ADDR((NewSpareAddr>>8)&0xff);
NF_ADDR(NewSectorAddr & 0xff);
NF_ADDR((NewSectorAddr >> 8) & 0xff);
if (LB_NEED_EXT_ADDR) {
NF_ADDR((NewSectorAddr >> 16) & 0xff);
}
// Now let's write the SectorInfo data
//
// Write the first reserved field (DWORD)
NF_DATA_W4( pInfo->dwReserved1 );
wrdata = (DWORD)(pInfo->bOEMReserved) | (((DWORD)(pInfo->bBadBlock) << 8)&0x0000ff00) | (((DWORD)(pInfo->wReserved2) << 16)&0xffff0000);
NF_DATA_W4( wrdata );
// Issue the write complete command
NF_CMD(CMD_WRITE2);
// Check ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
if ( READ_REGISTER_USHORT(pNFSTAT) & STATUS_ILLACC )
{
RETAILMSG(1, (TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page (Illigar Access) %d!\n"), sectorAddr));
WRITE_REGISTER_USHORT(pNFSTAT, STATUS_ILLACC); // Write 1 to clear.
bRet = FALSE;
}
else
{
// Check the status of program
NF_CMD(CMD_STATUS);
if(NF_DATA_R() & STATUS_ERROR) {
RETAILMSG(1, (TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page %d!\n"), sectorAddr));
bRet = FALSE;
}
}
SetChipSelect(mode,HIGH);
SetKMode(bLastMode);
return bRet;
}
// FMD_LB_ReadSector
//
// Read the content of the sector.
//
// startSectorAddr: Starting page address
// pSectorBuff : Buffer for the data portion
// pSectorInfoBuff: Buffer for Sector Info structure
// dwNumSectors : Number of sectors
//
BOOL FMD_LB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff,
PSectorInfo pSectorInfoBuff, DWORD dwNumSectors, int mode)
{
DWORD i;
BYTE eccBuf[8];
volatile DWORD rddata;
int NewSpareAddr = 2048 + 16*(startSectorAddr%4);
int NewDataAddr = 512*(startSectorAddr%4);
int NewSectorAddr = startSectorAddr/4;
// DWORD Mecc0, Mecc1;
// RETAILMSG(1, (TEXT("FMD::FMD_LB_ReadSector 0x%x \r\n"), startSectorAddr));
// RETAILMSG(1, (TEXT("startSectorAddr = 0x%x \r\n"), startSectorAddr));
// RETAILMSG(1, (TEXT("NewSpareAddr = 0x%x \r\n"), NewSpareAddr));
// RETAILMSG(1, (TEXT("NewDataAddr = 0x%x \r\n"), NewDataAddr));
// RETAILMSG(1, (TEXT("NewSectorAddr = 0x%x \r\n"), NewSectorAddr));
// Sanity check
if (!pSectorBuff && !pSectorInfoBuff || dwNumSectors > 1) {
RETAILMSG(1, (TEXT("Invalid parameters!\n")));
return FALSE;
}
if(!pSectorBuff) {
// We are reading spare only
// RETAILMSG(1, (TEXT("FMD::FMD_LB_ReadSector **** Read Spare Only **** \r\n")));
NAND_LB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff, mode);
// There is no ECC for the sector info, so the read always succeed.
return TRUE;
}
// RETAILMSG(1, (TEXT("FMD::FMD_LB_ReadSector 0x%x \r\n"), startSectorAddr));
BOOL bLastMode = SetKMode(TRUE);
// Initialize ECC register
NF_RSTECC();
NF_MECC_UnLock();
// Enable the chip
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Issue command
NF_CMD(CMD_READ);
// Set up address
NF_ADDR((NewDataAddr)&0xff);
NF_ADDR(((NewDataAddr)>>8)&0xff);
NF_ADDR((NewSectorAddr) & 0xff);
NF_ADDR((NewSectorAddr >> 8) & 0xff);
if (LB_NEED_EXT_ADDR) {
NF_ADDR((NewSectorAddr >> 16) & 0xff);
}
NF_CMD(CMD_READ3); // 2nd command
NF_DETECT_RB(); // Wait tR(max 12us)
// BUGBUG, because Media Player for Pocket PC sometimes pass us un-aligned buffer
// we have to waste cycle here to work around this problem
if( ((DWORD) pSectorBuff) & 0x3) {
for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++) {
rddata = (DWORD) NF_DATA_R4();
pSectorBuff[i*4+0] = (BYTE)(rddata & 0xff);
pSectorBuff[i*4+1] = (BYTE)(rddata>>8 & 0xff);
pSectorBuff[i*4+2] = (BYTE)(rddata>>16 & 0xff);
pSectorBuff[i*4+3] = (BYTE)(rddata>>24 & 0xff);
}
}
else {
ReadPage512(pSectorBuff, pNFDATA);
}
// Do the ECC thing here
// We read the ECC value from the ECC register pFNECC
NF_MECC_Lock();
// Mecc0 = READ_REGISTER_ULONG(pNFMECC0);
// Mecc1 = READ_REGISTER_ULONG(pNFMECC1);
NF_CMD(CMD_RDO);
// Set up address
NF_ADDR((NewSpareAddr)&0xff);
NF_ADDR(((NewSpareAddr)>>8)&0xff);
NF_CMD(CMD_RDO2);
// Read the SectorInfo data
if(pSectorInfoBuff) {
// Read the SectorInfo data (we only need to read first 8 bytes)
pSectorInfoBuff->dwReserved1 = NF_DATA_R4();
rddata = NF_DATA_R4();
// OEM byte
pSectorInfoBuff->bOEMReserved = (BYTE) (rddata & 0xff);
// Read the bad block mark
pSectorInfoBuff->bBadBlock = (BYTE) ((rddata>>8) & 0xff);
// Second reserved field (WORD)
pSectorInfoBuff->wReserved2 = (WORD) ((rddata>>16) & 0xffff);
}
else {
// Advance the read pointer
for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++) {
rddata = (DWORD) NF_DATA_R4(); // read and trash the data
}
}
// RETAILMSG(1, (TEXT("3 \r\n")));
// Verify the ECC values
//
// Read the ECC buffer 8bytes
for(i=0; i<2; i++) {
rddata = (DWORD) NF_DATA_R4();
// RETAILMSG(1, (TEXT("rddata 0x%x \r\n"), rddata));
eccBuf[i*4+0] = (BYTE)(rddata & 0xff);
eccBuf[i*4+1] = (BYTE)(rddata>>8 & 0xff);
eccBuf[i*4+2] = (BYTE)(rddata>>16 & 0xff);
eccBuf[i*4+3] = (BYTE)(rddata>>24 & 0xff);
}
// Mecc0 = READ_REGISTER_ULONG(pNFMECC0);
// Copmare with the ECC generated from the HW
WRITE_REGISTER_ULONG(pNFMECCD0, (DWORD)((DWORD)(eccBuf[1]<<16) | (DWORD)(eccBuf[0]&0xff)));
WRITE_REGISTER_ULONG(pNFMECCD1, (DWORD)((DWORD)(eccBuf[3]<<16) | (DWORD)(eccBuf[2]&0xff)));
// WRITE_REGISTER_ULONG(pNFMECCD0, (DWORD)((eccBuf[5])<<24) | (DWORD)((eccBuf[1])<<16) | (DWORD)((eccBuf[4])<<8) | (DWORD)((eccBuf[0]&0xff)));
// WRITE_REGISTER_ULONG(pNFMECCD1, (DWORD)((eccBuf[7])<<24) | (DWORD)((eccBuf[3])<<16) | (DWORD)((eccBuf[6])<<8) | (DWORD)((eccBuf[2]&0xff)));
SetChipSelect(mode,HIGH);
// RETAILMSG(1, (TEXT("4 \r\n")));
if ((READ_REGISTER_ULONG(pNFESTAT0)&0x3) == 0x0){
}
else {
RETAILMSG(1, (TEXT("FMD(FMD_LB_ReadSector): ECC ERROR - Page #: 0x%x \r\n"), startSectorAddr));
return FALSE;
}
SetKMode(bLastMode);
// RETAILMSG(1, (TEXT("FMD::FMD_LB_ReadSector -- \r\n")));
return TRUE;
}
//
// LB_IsBlockBad
//
// Check to see if the given block is bad. A block is bad if the 517th byte on
// the first or second page is not 0xff.
//
// blockID: The block address. We need to convert this to page address
//
//
BOOL LB_IsBlockBad(BLOCK_ID blockID, int mode)
{
DWORD dwPageID = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
BOOL bRet = FALSE;
BYTE wFlag;
BOOL bLastMode = SetKMode(TRUE);
// Enable the chip
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Issue the command
NF_CMD(CMD_READ);
// Set up address
NF_ADDR((2048+VALIDADDR)&0xff);
NF_ADDR(((2048+VALIDADDR)>>8)&0xff);
NF_ADDR((dwPageID) & 0xff);
NF_ADDR((dwPageID >> 8) & 0xff);
if (LB_NEED_EXT_ADDR) {
NF_ADDR((dwPageID >> 16) & 0xff);
}
NF_CMD(CMD_READ3);
// Wait for Ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
// Now get the byte we want
wFlag = (BYTE)(NF_DATA_R());
if(wFlag != 0xff) {
RETAILMSG(1, (TEXT("FMD: IsBlockBad - Page #: 0x%x \r\n"), dwPageID));
bRet = TRUE;
}
// Disable the chip
SetChipSelect(mode,HIGH);
SetKMode(bLastMode);
return bRet;
}
//
// FMD_LB_GetBlockStatus
//
// Returns the status of a block. The status information is stored in the spare area of the first sector for
// the respective block.
//
// A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
//
DWORD FMD_LB_GetBlockStatus(BLOCK_ID blockID, int mode)
{
SECTOR_ADDR sectorAddr = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
SectorInfo SI;
DWORD dwResult = 0;
// RETAILMSG(1, (TEXT("FMD_LB_GetBlockStatus (0x%x)0x%x \r\n"), blockID, sectorAddr));
if(!FMD_LB_ReadSector(sectorAddr<<2, NULL, &SI, 1, mode))
{
return BLOCK_STATUS_UNKNOWN;
}
if(!(SI.bOEMReserved & OEM_BLOCK_READONLY))
{
dwResult |= BLOCK_STATUS_READONLY;
}
if(SI.bBadBlock != 0xFF)
{
dwResult |= BLOCK_STATUS_BAD;
}
return dwResult;
}
// FMD_LB_EraseBlock
//
// Erase the given block
//
BOOL FMD_LB_EraseBlock(BLOCK_ID blockID, int mode)
{
BOOL bRet = TRUE;
DWORD dwPageID = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
// RETAILMSG(1, (TEXT("FMD_LB_EraseBlock 0x%x \r\n"), blockID));
BOOL bLastMode = SetKMode(TRUE);
// Enable the chip
SetChipSelect(mode,LOW);
NF_CLEAR_RB();
// Issue command
NF_CMD(CMD_ERASE);
// Set up address
NF_ADDR((dwPageID) & 0xff);
NF_ADDR((dwPageID >> 8) & 0xff);
if (LB_NEED_EXT_ADDR) {
NF_ADDR((dwPageID >> 16) & 0xff);
}
// Complete erase operation
NF_CMD(CMD_ERASE2);
// Wait for ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
if ( READ_REGISTER_USHORT(pNFSTAT) & STATUS_ILLACC )
{
RETAILMSG(1, (TEXT("LB######## Error Erasing block (Illigar Access) %d!\n"), blockID));
WRITE_REGISTER_USHORT(pNFSTAT, STATUS_ILLACC); // Write 1 to clear.
bRet = FALSE;
}
else
{
// Check the status
NF_CMD(CMD_STATUS);
if(NF_DATA_R() & STATUS_ERROR) {
RETAILMSG(1, (TEXT("LB######## Error Erasing block %d!\n"), blockID));
bRet = FALSE;
}
}
SetChipSelect(mode,HIGH);
SetKMode(bLastMode);
return bRet;
}
// FMD_LB_WriteSector
//
// Write dwNumPages pages to the startSectorAddr
//
BOOL FMD_LB_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors, int mode)
{
DWORD i;
BOOL bRet = TRUE;
volatile DWORD wrdata;
DWORD Mecc0;
int NewSpareAddr = 2048 + 16*(startSectorAddr%4);
int NewDataAddr = 512*(startSectorAddr%4);
int NewSectorAddr = startSectorAddr/4;
// RETAILMSG(1, (TEXT("FMD::FMD_LB_WriteSector 0x%x \r\n"), startSectorAddr));
// Sanity check
// BUGBUGBUG: I need to come back to support dwNumSectors > 1
//
if((!pSectorBuff && !pSectorInfoBuff) || dwNumSectors != 1) {
RETAILMSG(1, (TEXT("Invalid parameters!\n")));
return FALSE;
}
if(!pSectorBuff) {
// If we are asked just to write the SectorInfo, we will do that separately
bRet = NAND_LB_WriteSectorInfo(startSectorAddr, pSectorInfoBuff, mode);
return bRet; // Do not write the actual sector information...
}
BOOL bLastMode = SetKMode(TRUE);
// Initialize ECC register
NF_RSTECC();
NF_MECC_UnLock();
// Enable Chip
SetChipSelect(mode,LOW);
// Issue command
NF_CMD(CMD_WRITE);
// Setup address
NF_ADDR((NewDataAddr)&0xff);
NF_ADDR(((NewDataAddr)>>8)&0xff);
NF_ADDR((NewSectorAddr) & 0xff);
NF_ADDR((NewSectorAddr >> 8) & 0xff);
if (LB_NEED_EXT_ADDR) {
NF_ADDR((NewSectorAddr >> 16) & 0xff);
}
// Special case to handle un-aligned buffer pointer.
//
if( ((DWORD) pSectorBuff) & 0x3) {
// Write the data
for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++) {
wrdata = pSectorBuff[i*4+0];
wrdata |= pSectorBuff[i*4+1]<<8;
wrdata |= pSectorBuff[i*4+2]<<16;
wrdata |= pSectorBuff[i*4+3]<<24;
NF_DATA_W4(wrdata);
}
}
else {
#ifndef USENANDDMA
WritePage512(pSectorBuff, pNFDATA);
#else // USENANDDMA
#ifdef USESETKMODE
SetKMode(TRUE);
v_pINTregs->rSRCPND=BIT_DMA3; // Init DMA src pending.
#endif // USESETKMODE
memcpy(pDMABuffer, pSectorBuff, 512);
// Nand to memory dma setting
v_pDMAregs->rDISRC3 = (int)SDI_DMA_BUFFER_PHYS; // Nand flash data register
v_pDMAregs->rDISRCC3 = (0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -