Wince stepldr代码解析

Wince  stepldr代码解析

Wince系统启动之后最开始执行的代码就是stepldr,当然stepldr之前还有一段汇编,这里着重讲stepldr,stepldr又分为两个部分,Stepldr_NAND和Stepldr_SD,顾名思义,Stepldr_NAND为从nand启动的stepldr引导,Stepldr_SD为从SD启动的stepldr引导。先说Stepldr_NAND,Stepldr_NAND开始部分是对小页和大页sector、 page 、block大小等的一些宏定义,大小页定义之后是对stepldr执行之后的下载地址和地址大小的定义。


这里牵扯到一个bLARGEBLOCK这个变量,该变量定义为bool型,在执行ReadFlashID()函数是被赋值。

DWORD ReadFlashID(void)

{

         BYTEMfg, Dev, i;

         volatileint ReadID;

         UINT32nRet;

 

         bLARGEBLOCK= FALSE;

        

         nRet= TRUE;

        

         NF_nFCE_L();

 

         NF_CMD(0x90);                                   // Send flashID read command.

 

         NF_ADDR(0);  

         for(i=0; i<10; i++);

 

         Mfg  = NF_RDDATA8();              // Maker code

         Dev  = NF_RDDATA8();              // Devide code(K9S1208V:0x76), (K9K2G16U0M:0xca)

 

         NF_nFCE_H();

        

         //if(Mfg == (UINT8)0xEC || Mfg == 0xAD)

         if(Mfg == (UINT8)0xEC || Mfg == (UINT8)0x1)

         {

                   if(Dev >= (UINT8)0xA0){

                            bLARGEBLOCK= TRUE;

                            Uart_SendDWORD(bLARGEBLOCK,1);

                            }

         }

/**********************************addend*************************/  

         elseif (Mfg == (UINT8)0x98)

         {

         }

         else

         {

                   nRet= FALSE;

         }

 

         ReadID= (DWORD)((Mfg<<8)+Dev);

         Uart_SendDWORD(ReadID,1);

 

         returnnRet;

}

 

下来就是main函数了,main函数开头有三个函数

         MMU_EnableICache();

 

         Uart_Init();

        

         NF_Init();

其中MMU_EnableICache()为使能ICache指令,汇编代码如下;

; void MMU_EnableICache(void);

 

         LEAF_ENTRY    MMU_EnableICache

 

         mrc           p15, 0, r0, c1, c0, 0

         orr             r0, r0, #R1_I

         mcr           p15, 0, r0, c1, c0, 0

         mov           pc, lr

 

Uart_Init()和NF_Init()分别为串口初始化和nandflash初始化,完成这三部分初始化之后,代码继续向下执行到flash ID判断函数;

if (ReadFlashID() != TRUE)

         {

                   WrUTXH2('I');

                   while(1); 

         }

此时如果读取失败的话就会在串口打印一个’i’,然后进入死循环,也就是说如果读取ID失败的话,程序就会卡死在这里了;

如果读取ID正确,那么就会循环读取相应块中的数据,执行代码如下:

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)

                            {

                                     WrUTXH2('E');

                                     while(1)

                                     {

                                     }

                            }

 

                            //ECC error on a block boundary is (likely) a bad block - retry the page 0 readon the next block.

                            nBadBlocks++;

                            nPage--;

                            continue;

                   }

 

此处有个nBadBlocks++,就是说如果读取失败的话会增加一个坏块,但是NF_ReadPage读取函数里并没有判断坏块,所以说,stepldr里的读是不判断坏块的,这个和nand驱动里的读函数不同,两者定义如下所示:

int NF_ReadPage(UINT32 block,UINT32sector,UINT8 *buffer);

BOOL RAW_LB_ReadPage(SECTOR_ADDRstartSectorAddr, LPBYTE pSectorBuff, LPBYTE pSectorInfoBuff);

后者参数里的pSectorInfoBuff里既包含有坏块信息;

((PFN_IMAGE_LAUNCH)(LOAD_ADDRESS_PHYSICAL))();

Main函数最后的这一段代码是一个长跳转,跳转到EBOOT的物理地址。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值