NAND读取页函数的解析说明
此解析只针对于stepldr阶段的nand页读取函数,nand启动的stepldr位于D:\WINCE600-old\PLATFORM\SMDK2416\Src\Bootloader\Stepldr_NAND路径下的main.c里,该段代码主要是针对Stepldr从nand启动的做相应的配置;
void main(void)
{
registernBlock;
registernPage;
registernBadBlocks;
volatileBYTE *pCopyPtr;
MMU_EnableICache();
Uart_Init();
NF_Init();
/*此处是对stepldr阶段需要用到的一些功能进行初始化,包括MMU、串口、时钟*/
//---------------------------------
// Copyimage from NAND flash to RAM.
//
pCopyPtr= (BYTE *)LOAD_ADDRESS_PHYSICAL;
if (ReadFlashID() != TRUE)/*此处是读取NAND FLASH的ID,如果读取失败则进入while死循环*/
{
while(1);
}
//
/*下面是对nand的block、page和sector的一些初始化判断*/
nBadBlocks= 0;
for(nPage = NAND_COPY_PAGE_OFFSET ; nPage < (LOAD_SIZE_PAGES +NAND_COPY_PAGE_OFFSET) ; nPage++)
{
nBlock= ((nPage /((bLARGEBLOCK==TRUE)?NAND_LB_PAGES_PER_BLOCK:NAND_SB_PAGES_PER_BLOCK)) +nBadBlocks);
if (!NF_ReadPage(nBlock, (nPage %((bLARGEBLOCK==TRUE)?NAND_LB_PAGES_PER_BLOCK:NAND_SB_PAGES_PER_BLOCK)),pCopyPtr))
/*此处调用页读取函数*/
{
if((nPage %((bLARGEBLOCK==TRUE)?NAND_LB_PAGES_PER_BLOCK:NAND_SB_PAGES_PER_BLOCK)) != 0)
{
while(1)
{
}
}
//ECC error on a block boundary is (likely) a bad block - retry the page 0 readon the next block.
nBadBlocks++;
nPage--;
continue;
}
pCopyPtr+= ((bLARGEBLOCK==TRUE)?NAND_LB_PAGE_SIZE_BYTES:NAND_SB_PAGE_SIZE_BYTES);
}
((PFN_IMAGE_LAUNCH)(LOAD_ADDRESS_PHYSICAL))();//读取完成之后标志stepldr执行完毕了,此处直接跳转到EBOOT的存放地址处开始执行
}
下面解析一下NF_ReadPage函数,该函数在D:\WINCE600-old\PLATFORM\SMDK2416\Src\Bootloader\Stepldr_NAND下的nand.c里,代码如下,入口参数为读取的block数,sector数和所需要分配的内存大小;
int NF_ReadPage(UINT32 block,UINT32 sector,UINT8*buffer)
{
registerUINT8 * bufPt=buffer;
unsignedint RowAddr, ColAddr;
DWORDMECCBuf, rddata1, rddata2;
UINT32nRetEcc;
int nRet= FALSE;
intnSectorLoop;
NF_nFCE_L();
//for(nSectorLoop = 0; nSectorLoop < (bLARGEBLOCK==TRUE?4:1); nSectorLoop++)
for (nSectorLoop = 0; nSectorLoop <(bLARGEBLOCK==TRUE?1:1); nSectorLoop++)//此处是对nand内部参数的判断,判断页是否可以再分为sector操作,如果可以,则分为四个sector,每次操作512byte。
{
//ColAddr= nSectorLoop * 512;
ColAddr =nSectorLoop * 2048; // add by zhang ,20141227
NF_CMD(CMD_READ); // Read command
if(bLARGEBLOCK == TRUE)
{
RowAddr = (block<<6) + sector;//此部分代码为获取需要读取的页的行地址和列地址
NF_ADDR((ColAddr) &0xff); // 1st cycle
NF_ADDR((ColAddr>>8)&0xff); // 2nd cycle
NF_ADDR((RowAddr) &0xff); // 3rd cycle
NF_ADDR((RowAddr>>8)&0xff); // 4th cycle
if(LB_NEED_EXT_ADDR)
NF_ADDR((RowAddr>>16)&0xff); // 5th cycle
}
else
{
RowAddr= (block<<5) + sector;
NF_ADDR((ColAddr) &0xff); // 1st cycle
NF_ADDR((RowAddr) &0xff); // 2nd cycle
NF_ADDR((RowAddr>>8)&0xff); // 3rd cycle
if(SB_NEED_EXT_ADDR)
NF_ADDR((RowAddr>>16)&0xff); // 4th cycle
}
NF_CLEAR_RB();
NF_CMD(CMD_READ3); // Read command
NF_DETECT_RB();
//NF_WAITRB();
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
__RdPage512(bufPt+nSectorLoop*512); // Read 512 bytes.
NF_MECC_Lock();
if(bLARGEBLOCK == TRUE)
{
ColAddr= 2048;
NF_CMD(CMD_RDO); // Random Data Output In a Page, 1stCycle
NF_ADDR((ColAddr) &0xff); // 1st cycle
NF_ADDR((ColAddr>>8)&0xff); // 2nd cycle
NF_CMD(CMD_RDO2); // Random Data Output In aPage. 2nd Cycle
}
rddata1= NF_RDDATA32(); // check bad block
rddata2= NF_RDDATA32();
if(bLARGEBLOCK == TRUE)
{
ColAddr= 2048 + 8 + nSectorLoop*4;
NF_CMD(CMD_RDO); // Random Data Output In a Page, 1stCycle
NF_ADDR((ColAddr) &0xff); // 1st cycle
NF_ADDR((ColAddr>>8)&0xff); // 2nd cycle
NF_CMD(CMD_RDO2); // Random Data Output In aPage. 2nd Cycle
}
MECCBuf= NF_RDDATA32();
NF_WRMECCD0(((MECCBuf&0x0000ff00)<<8) | ((MECCBuf&0x000000ff) ) );
NF_WRMECCD1(((MECCBuf&0xff000000)>>8) | ((MECCBuf&0x00ff0000)>>16) );
nRetEcc= rNFECCERR0;
nRet= ECC_CorrectData(RowAddr, bufPt+nSectorLoop*512, nRetEcc, ECC_CORRECT_MAIN);
if(!nRet) return nRet;
}
NF_nFCE_H();
returnnRet;
}