我这菜鸟水平折腾了3个月,今天终于看得懂一点点东西
NandFlsh使用的是三星的K9K8G08U0A
首先是\wince600\platform\smdkv210\src\common\nandflash\fmd\Cfnand.h下的小分析
以下结构体用于存储NandFalsh的信息
typedef struct
{
UINT8 ucMID;// Manufacturer ID厂家ID
UINT8 ucDID;// Device ID设备ID
UINT8 ucType;// SLC / MLC类型,分SLC和MLC,在百度百科可以搜到2者大致的差别
UINT16 usNumberOfBlocks; // Number of blocksBlock的数量,芯片手册第九页可以查到是8192
UINT16 usPagesPerBlock; // Number of pages per blockPage的数量
UINT16 usBytesPerPage; // Number of bytes per page
UINT16 usMainBytesPerPage; // Main area size per page主区的页大小
UINT16 usSpareBytesPerPage; // Spare area size per page扩展区的页大小
//三个时序 要特别理解还是谈不上
DWORD dwTACLS;
DWORD dwTWRPH0;
DWORD dwTWRPH1;
} NAND_FLASH_SPEC;
static NAND_FLASH_SPEC g_supportedNAND[] =
{
/* 8Gbit DDP NAND Flash */
{0xEC, 0xD3, SLC_NAND, 8192, 64, 2112, 2048, 64, 7, 7, 7},// Samsung 2Gbit SLC - K9K8G08U0A
//这是添加Nand支持列表 其元素的顺序是按上面的结构体填写
/* 4Gbit DDP NAND Flash */
{0xEC, 0xDC, SLC_NAND, 4096, 64, 2112, 2048, 64, 7, 7, 7},// Samsung 2Gbit SLC - K9F4G08U0A
{0xEC, 0xDA, SLC_NAND, 2048, 64, 2112, 2048, 64, 7, 7, 7},// Samsung 2Gbit SLC - K9F2G08U0A
{0xEC, 0xF1, SLC_NAND, 1024, 64, 2112, 2048, 64, 7, 7, 7},// Samsung 1Gbit SLC - K91FG08U0C
{0x00, 0x00, SLC_NAND, 0, 0, 0, 0, 0}//必须有这个,初始化的时候进行循环检测,此处0标识结束
};
某些大神中的文章,大概理解到Nand和普通WinCE的驱动有点区别,不是普遍的PDD和MMD
而是FAL和FMD两层
FAL是抽象层,FMD就是实际对硬件进行操作的
不过我手头的BSP怎么都找不到FAL
只有很明显的\wince600\platform\smdkv210\src\common\nandflash\fmd\fmd.cpp下的
FMD_XXX函数,而且多数被FMD_LB_XXX函数调用
我的水平只能理解FMD_LB_XXX比FMD_XXX高一层
在初始化之前是注册这三个东西
static volatile NAND_REG *v_pNFCONregs = (NAND_REG *)NAND_BASE;
static volatile NAND_ECC_REG *v_pECCregs = (NAND_ECC_REG *)ECC_BASE;
NAND_FLASH_SPEC *g_pNANDSpec = NULL;
首先看的是函数
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
其操作先后是
1.初始化注册
if (pRegIn && pRegIn->MemBase.Num && pRegIn->MemBase.Reg[0])
v_pNFCONregs = (NAND_REG *)(pRegIn->MemBase.Reg[0]);
else
v_pNFCONregs = (NAND_REG *)NAND_BASE;
2.ECC的注册 ECC是校检用的 据我所知有硬件校检和软件校检之分,这里看来这么简单的样子我才不是软件校检...
v_pECCregs = (NAND_ECC_REG *)ECC_BASE;
3.接着设置时序
v_pNFCONregs->NFCONF = (NAND_TACLS << 12) | (NAND_TWRPH0 << 8) | (NAND_TWRPH1 << 4);
v_pNFCONregs->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
v_pNFCONregs->NFSTAT = (1<<4);
4.读ID,检测
// 读Nand的MID(厂家ID)和DID(设备ID)
rdid = ReadFlashID();
//分离
nMID = (UINT8)(rdid >> 8);
nDID = (UINT8)(rdid & 0xff);
for (nCnt = 0; g_supportedNAND[nCnt].ucMID != 0; nCnt++)
{
if (nDID == g_supportedNAND[nCnt].ucDID && nMID == g_supportedNAND[nCnt].ucMID )
//查看支持列表中有没有与nand读到对应的(cfnand.h)
{
g_pNANDSpec = &(g_supportedNAND[nCnt]);
break;
}
}
if(g_pNANDSpec == NULL)//没有支持的
{
FMDERR(TRUE, (TEXT("Failed to find a supported NAND flash memory.\r\n")));
FMDERR(FMD_INFO, (TEXT("Manufacturer code : 0x%2X\r\n"), nMID));
FMDERR(FMD_INFO, (TEXT("Device code : 0x%2X\r\n"), nDID));
// error return
v_pNFCONregs = NULL;
goto CleanUp;
}
5.设置
dwTotalNumberOfPages = g_pNANDSpec->usNumberOfBlocks * g_pNANDSpec->usPagesPerBlock;
dwTACLS = g_pNANDSpec->dwTACLS;
dwTWRPH0 = g_pNANDSpec->dwTWRPH0;
dwTWRPH1 = g_pNANDSpec->dwTWRPH1;
// -- SLC or MLC
// -- FMD driver supports SLC NAND flash memory only.
if(g_pNANDSpec->ucType == SLC_NAND)
{
if(g_pNANDSpec->usMainBytesPerPage == 2048)
{
if(dwTotalNumberOfPages > (1 << 16))
{
// SLC, Large block, 5 address cycle
v_pNFCONregs->NFCONF = (dwTACLS << 12) | (dwTWRPH0 << 8) | (dwTWRPH1 << 4)
| ECC_1BIT | SLC_NAND | LARGE_BLOCK | EXT_ADDR;
NEED_EXT_ADDR = TRUE;
}
else
{
// SLC, Large block, 4 address cycle
v_pNFCONregs->NFCONF = (dwTACLS << 12) | (dwTWRPH0 << 8) | (dwTWRPH1 << 4)
| ECC_1BIT | SLC_NAND | LARGE_BLOCK;
NEED_EXT_ADDR = FALSE;
}
}
else if(g_pNANDSpec->usMainBytesPerPage == 512)
{
// Small block NAND
FMDERR(TRUE, (TEXT("FMD doesn't support the small block NAND flash memory.\r\n")));
v_pNFCONregs = NULL;
goto CleanUp;
}
else
{
// page size > 2KB
FMDERR(TRUE, (TEXT("FMD doesn't support the NAND flash memory whose page size is larger than 2KB\r\n")));
v_pNFCONregs = NULL;
goto CleanUp;
}
}
else
{
// MLC NAND flash memory
FMDERR(TRUE, (TEXT("FMD doesn't support the MLC NAND flash memory.\r\n")));
v_pNFCONregs = NULL;
goto CleanUp;
}
某次调试中发现,依旧还是提示失败,不支持的NandFlash
顺藤摸瓜的找到
switch(cMID)
{
case 0xEC:
{
switch(cDID)
{
case 0xDA://Samsung 2Gbit SLC - K9F2G08U0A 在这里添加对应的DID
case 0xDC://Samsung 2Gbit SLC - K9F4G08U0A
case 0xD3://Samsung 2Gbit SLC - K9K8G08U0A
{
g_bLargeBlock = TRUE;
NEED_EXT_ADDR = TRUE;
break;
}
case 0xF1://Samsung 1Gbit SLC - K91FG08U0C
{
g_bLargeBlock = TRUE;
NEED_EXT_ADDR = FALSE;
break;
}
default:
// Not supported NAND
while(1);
break;
}
break;
}
我的文章基本上都是看到哪写到哪,看了什么写什么...思路混乱,谨慎阅读