Nboot程序详细分析

基本上吧Nboot的程序看完了,总结一下。

主要包含以下文件:

  1. 2410init.s  
  2. 2410slib.s  
  3. nand_s.s  
  4.   
  5. 2410loader.c  
  6. 2410lib.c  
  7. nand.c  

其中最重要的是2410init.s和2410loader.c。

2410init.s是汇编程序,所作的工作有:屏蔽所有中断、设置CPU的速度和时钟频率、RAM的初始化、LED的初始化等。

2410loader.c是C语言程序,下面着重介绍。

首先,入口程序main():

  1. void  Main( void )  
  2. {  
  3.     DWORD err;  
  4.    
  5.     DWORD dwEntry = 0;        // 定义入口方式,是直接进入WinCE内核,还是启动Eboot   
  6.   
  7.     MMU_EnableICache();         //MMU_Cache On   
  8.   
  9.     Uart_Init();            //初始化串口   
  10.     Uart_SendString(SIGN_ON);            //打印启动信息   
  11.   
  12.     NF_Init();              //初始化Nand Flash   
  13.   
  14.     Uart_SendString("/ndwEntry is " );  
  15.     Uart_SendDWORD(dwEntry, TRUE);  
  16.   
  17.     err = ReadImageFromNand(dwEntry,0); //读TOC信息、将Image写入内存等   
  18.   
  19.     if  (ERR_SUCCESS == err) {  
  20.         Uart_SendString("/nDone!" );  
  21.         Uart_SendDWORD(JumpAddr, TRUE);  
  22.          Launch(JumpAddr);      // 执行指定地址的程序(RAM中,物理地址)   
  23.         err = ERR_JUMP_FAILED;  
  24.     }  
  25.   
  26.     Uart_SendString("/nBoot ERROR:" );  
  27.     Uart_SendDWORD(err, TRUE);  
  28.     while  (1);  
  29. }  

里面重要的有两个程序Uart_Init()和ReadImageFromNand()。

先来看Uart_Init():

  1. //***************************[ UART ]******************************   
  2. void  Uart_Init( void )  
  3. {  
  4.     int  i;  
  5.   
  6.     rUFCON0 = 0x0;      // FIFO disable   
  7.     rUMCON0 = 0x0;      // AFC disable   
  8.   
  9.     rULCON0 = 0x3;      // Normal,No parity,1 stop,8 bits   
  10.     rUCON0  = 0x245;     
  11.       
  12.     rUBRDIV0=( (int )(PCLK/16./BAUD_RATE) -1 );  
  13.   
  14.     for (i=0;i<100;i++);  
  15.       
  16. }  

注意其中的rUFCON0、rUMCON0等参数里的数字0,这代表初始化的是UART0端口,而所有的打印输出也是向UART0的,所以在计算机 上用超级终端监控时,串口一定要接到UART0上。

接下来是最重要的ReadImageFromNand():

  1. DWORD  
  2. ReadImageFromNand(DWORD dwEntry, DWORD dwSig)  
  3. {  
  4.     DWORD dwSectorsNeeded;  
  5.     DWORD dwSector, dwLength;         // Start Sector & Length   
  6.     DWORD dwRAM, i;  
  7.   
  8.     Uart_SendString("TOC_SECTOR: /n" );  
  9.     Uart_SendDWORD(TOC_SECTOR,TRUE);  
  10.   
  11.     //读TOC内容,确定拷贝Image所需空间、拷贝的起始地址、跳转位置等信息   
  12.     if  ( !FMD_ReadSector(TOC_SECTOR,(LPBYTE)&toc,NULL, 1) )  
  13.     {  
  14.         Uart_SendString("ERR_DISK_OP_FAIL1/n" );  
  15.         return  ERR_DISK_OP_FAIL1;  
  16.     }  
  17.   
  18.     //验证TOC是否合法   
  19.     if  ( !VALID_TOC(&toc) ) {  
  20.         Uart_SendString("ERR_INVALID_TOC: " );  
  21.         Uart_SendDWORD(toc.dwSignature, TRUE);  
  22.         return  ERR_INVALID_TOC;  
  23.     }  
  24.   
  25.     //拷贝到RAM的Image所占的Page   
  26.     dwSectorsNeeded = toc.id[dwEntry].dwTtlSectors;  
  27.       
  28.     Uart_SendString("Sector addr on NAND: " );  
  29.     Uart_SendDWORD(toc.id[dwEntry].sgList[0].dwSector, TRUE);  
  30.     Uart_SendString("TotalSector: " );  
  31.     Uart_SendDWORD(dwSectorsNeeded, TRUE);  
  32.   
  33.     //dwRAM:拷贝Image到RAM的起始地址   
  34.     //JumpAddr:拷贝完成后的执行程序地址   
  35.     dwRAM = VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwLoadAddress);  
  36.     JumpAddr = VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwJumpAddress);  
  37.   
  38.     // 将Image拷贝到RAM中   
  39.     i = 0;  
  40.     while  (dwSectorsNeeded && i < MAX_SG_SECTORS)  
  41.     {  
  42.         dwSector = toc.id[dwEntry].sgList[i].dwSector;  
  43.         dwLength = toc.id[dwEntry].sgList[i].dwLength;  
  44.         // read each sg segment   
  45.         while  (dwLength) {  
  46.   
  47.             if  ( !FMD_ReadSector(dwSector,  
  48.                                 (LPBYTE)dwRAM,  
  49.                                 NULL, 1) )  
  50.             {  
  51.                 Uart_SendString("ERR_DISK_OP_FAIL2: " );  
  52.                 Uart_SendDWORD(dwSector, TRUE);  
  53.   
  54.                 dwSector++;  
  55.                 continue ;  
  56.             }  
  57.               
  58.             dwSector++;  
  59.             dwLength--;  
  60.             dwRAM += SECTOR_SIZE;  
  61.         }  
  62.   
  63.         dwSectorsNeeded -= toc.id[dwEntry].sgList[i].dwLength;  
  64.         i++;  
  65.     }  
  66.   
  67.     return  ERR_SUCCESS;  
  68. }  

里面有一个函数FMD_ReadSector(),它的功能是读取一个Page的内容到RAM中,里面调用的是一个汇编程序 __RdPage512。

等ReadImageFromNand()程序成功返回后,由Launch(JumpAddr)调用一个汇编程序,执行RAM指定地址的程序。

这样就基本上把Nboot的流程讲完了。当然,还有ECC验证、Chain.bin等,以后再说。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值