又到了周末,今天是2010年7月31日,很纠结。。。。。。因为串口接收大数据包丢失问题,还没有清晰的办法。
暂且放下它,还是把以前做过的比较有意思的东西重新整理下:
很多处理器,都支持大容量的NAND,拿三星6410处理器来讲,从资料上看,支持大容量8G NANDFLASH,也说明了需要加片选来控制,这次做的是2GNAND的支持,需要2个片选。OK ~~~~~~~硬件上,NANDFLASH上增加一路片选信号,增加一路R/B控制。
我这个是由2个8G08构成的2GNAND
软件上调整:
1, 让系统判断出NAND的容量大小:在初始化NAND的时候,读2个片选对应的NAND的ID,读出两个NAND的相关信息,然后把这些信息告诉系统
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();
NF_nFCE_H();
return ((DWORD)(Mfg<<8)+Dev);
}
//增加一个读片选2的函数
static DWORD ReadFlashID2(void)
{
BYTE Mfg, Dev;
int i;
NF_nFCE_L1(); // 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();
NF_nFCE_H1();
return ((DWORD)(Mfg<<8)+Dev);
}
NF_nFCE_L1()为增加的那个片选的控制。
2, 把第1步中得到的2GNAND的信息,重新赋给全局变量,即告诉系统新的NAND信息。
在NAND初始化函数中 添加对第2快NAND的初始化
RETAILMSG(1, (TEXT("[FMD:INF] FMD_Init() : Read ID = 0x%08x/n"), nNandID2));
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;
}
int NUM_OF_BLOCKS2 = astNandSpec[nCnt].nNumOfBlks;
int PAGES_PER_BLOCK2 = astNandSpec[nCnt].nPgsPerBlk;
int SECTORS_PER_PAGE2 = astNandSpec[nCnt].nSctsPerPg;
RETAILMSG(1, (TEXT("[FMD] FMD_Init() : NUM_OF_BLOCKS2 = %d/n"), NUM_OF_BLOCKS2));
RETAILMSG(1, (TEXT("[FMD] FMD_Init() : PAGES_PER_BLOCK2 = %d/n"), PAGES_PER_BLOCK2));
RETAILMSG(1, (TEXT("[FMD] FMD_Init() : SECTORS_PER_PAGE2 = %d/n"), SECTORS_PER_PAGE2));
RETAILMSG(1, (TEXT("[FMD] --FMD_Init()2/n")));
//相加
NUM_OF_BLOCKS = NUM_OF_BLOCKS1+NUM_OF_BLOCKS1;
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));
return((PVOID)g_pNFConReg);
}
3,增加读写操作中的地址转换:
例如现在第1个NAND的大小是8192个BLOCK,那么当我们想去读/写第16000个BLOCK进行操作的时候,我们要做个判断,让系统去操作第2片 NAND的第(16000-8192)个BLOCK。
接下来就是细心的完全驱动相关函数的修改;
由于NAND的驱动相关函数很多,我这个就不全贴出,思路是一样的,注意这个地址转换就可以了(加个判断就OK了),仅列举读NAND函数
//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 )
{
if(8192*64<=startSectorAddr)
{
startSectorAddr=(startSectorAddr-8192*64);//转换为第2块NAND的地址,调用第2块NAND的函数
bRet = FMD_LB_ReadSector2(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);//!!!!
}
else
bRet = FMD_LB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
}
else
{
if(8192*64<=startSectorAddr)
{
startSectorAddr=(startSectorAddr-8192*64);//转换为第2块NAND的地址,调用第2块NAND的函数
bRet = FMD_SB_ReadSector2(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);//!!!!
}
else
bRet = FMD_SB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
}
#ifdef SYNC_OP
LeaveCriticalSection(&g_csNandFlash);
#endif
#if (NAND_DEBUG)
RETAILMSG(1, (TEXT("[FMD] --FMD_ReadSector()/n")));
#endif
return bRet;
}
这样编译后,重启,擦出/低格/高格信息:
Reserving Blocks [0x0 - 0x5] ...
...reserve complete.
Low-level format Blocks [0x6 - 0x3fff] ...
LB######## Error Erasing block 1462!
LB######## Error Erasing block 2011!
LB######## Error Erasing block 5027!
LB######## Error Erasing block 5687!
LB######## Error Erasing block 8048!
2LB######## Error Erasing block 1005!
2LB######## Error Erasing block 1366!
2LB######## Error Erasing block 3396!
2LB######## Error Erasing block 5239!
2LB######## Error Erasing block 7557!
...erase complete.
//高格
Enter LowLevelFormat [0x6, 0x3fff].
Erasing flash block(s) [0x6, 0x3fff] (please wait): EraseBlocks: found a bad block (0x5b6) - skipping...
EraseBlocks: found a bad block (0x7db) - skipping...
EraseBlocks: found a bad block (0x13a3) - skipping...
EraseBlocks: found a bad block (0x1637) - skipping...
EraseBlocks: found a bad block (0x1f70) - skipping...
EraseBlocks: found a bad block (0x23ed) - skipping...
EraseBlocks: found a bad block (0x2556) - skipping...
EraseBlocks: found a bad block (0x2d44) - skipping...
EraseBlocks: found a bad block (0x3477) - skipping...
EraseBlocks: found a bad block (0x3d85) - skipping...
Done.
WriteMBR: MBR block = 0x6.
Done.
这样就可以了,做的时间久了 ,可以有些细节会忘记了,但是思路就是这样,很简单。其他4G/8G如果需要片选,则也可以用这个思路做,只不过驱动可能代码又长了很多~呵呵