NAND读取页函数的解析说明

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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值