注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

男儿当自强的博客

每天进步一点

 
 
 

日志

 
 
 
 

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件  

2012-12-06 14:41:10|  分类: wince的bootloade |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

备注:FLASH为K9K8G08U0D-SCB0

   CSDN的博文链接:http://blog.csdn.net/loongembedded/article/details/8264799

1.       烧录镜像文件

相关部分见我之前的博文:http://blog.csdn.net/loongembedded/article/details/6648270

我们知道烧录nboot、eboot和nk的实现主要是在eboot部分,所以,我们就直接从eboot来学习这部分。

1.1   Eboot烧录stepldr

刚出厂时FLASH的单元除了坏块的标识(非0xFF)之外,其他单元保存的都是0xFF的值,也就是说并没有有效的数据,为了把nboot的数据写入FLASH中,而且S3C2451支持TF卡启动,所以开就就从TF卡启动,然后通过读取出TF卡中的nboot镜像文件烧录到FLASH中,下面就学习烧录过程中涉及的主要动作。

1.1.1          OEMPlatformInit函数

不管是通过FLASH启动还是TF卡启动,都会执行到OEMPlatformInit函数,此函数很重要,内容页很多,下面介绍重点及之前没有深入涉及的部分:

1.1.1.1    BP_Init函数

 

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图1

BP_Init函数是BootPart模块的初始化函数,初始化Flash设备并初始化一块内存。该函数一般会在OEMPlatformInit函数中被调用。pMemory指向一块内存来存放MBR信息,dwSize为内存的大小,lpActiveReg,pRegIn和pRegOut会被FMD_Init用到,一般可以设置为NULL。先来看此函数中相关的FLASH结构体:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图2

Windows CE下的FLASH驱动分为两层,分别为FMD层和FAL层(flash abstraction layer),FMD(Flash Media Driver)属于底层,直接操作Flash硬件,比如读、写和擦除等,不同的Flash硬件则FMD_XXX接口实现函数各不相同,上层则是FAL (Flash Abstraction Layer)层,该层是由微软实现并提供的,是一个与硬件无关的层,可用于FAL层实现扇区的动态分配和坏块管理等。FAL层向应用层(如API)提供DSK接口。例如CreateFile中调用的设备即是调用该FAL层提供的接口。FMD层暴露FMD_XXX让FAL层调用。

微软NAND FLASH块驱动的FAL部分使用此8字节的SectorInfo结构体模拟flash实际扩展区域的典型物理布局,也就是说此结构体描述了spare area所保存的内容。下面是此函数主要实现部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图3

调用BP_Init函数后,内存中一些变量被初始化为指向具体的内存单元处,如下图:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图4

该函数可以说是BootPart模块的初始化函数,看看代码就知道他会调用FMD_Init来初始化Flash设备并初始化一块内存。该函数一般会在OEMPlatformInit函数中被调用。pMemory指向一块内存来存放MBR信息,dwSize为内存的大小,lpActiveReg,pRegIn和pRegOut会被FMD_Init用到,一般可以设置为NULL。

 

1.1.1.2    TOC_Read函数

接下来调用TOC相关的函数:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图5

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图6

TOC_Read函数主要是从TOC所在的第1block中读取第1页的TOC数据,根据获取的TOC数据来指导下面的执行流程,根据FMD_ReadSector函数的实现部分,此函数的描述可参考我的博文:http://blog.csdn.net/loongembedded/article/details/6015302,我们可以初步指导每512bytes main area对应的16bytes的布局,在此先借用三星《spare_assignment_standard.pdf》中的一张图:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图7

有了这种图就可以很好理解spare area中的布局,但我们的这16bytes布局如下:

bBadBlock(1)+ dwReserved1(4)+ bOEMReserved(1)+ wReserved2(2)+ECC0~3(4)+S_ECC0~1(2)+

RESERVED(2),其中括号中的数据表示多少个字节,可知每512bytes main area的数据产生4个字节的MECC校验码,16bytes spare area的数据产生2个字节的SECC校验码。

1.1.1.3     

 

1.1.2          第一次烧录前需要对FLASH进行的操作

 

 

 由于NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生产中及使用过程中会产生坏块。为了检测数据的可靠性,在应用NAND Flash的系统中一般都会采用一定的坏区管理策略,而管理坏区的前提是能比较可靠的进行坏区检测。

 

1.1.2.1    坏块的定义和产生。

FLASH出厂时一般都有坏块,最初坏块被定义为某块中,如果包含一位或多位初始无效的位就认为此块为坏块。

NAND FLASH中坏块的出现有下面四种情况:

⑴出厂时的坏块。

⑵操作过程中由于擦除失败造成的。

⑶擦除过程中写入操作失败引起的。

⑷出现超出ECC校验算法纠正能力的错误时,也认为出现了坏块。

 

1.1.2.2    标示坏块

在大部分情况下,最初的坏块信息是可擦除的,在块擦除的时候很有可能会恢复(recover)这些坏块信息,这样就会因为没有正确判别坏块造成这样的问题:把数据写入到坏块中,这样肯定会留下安全和性能隐患。所以,系统必须能够根据最初的坏块信息来识别最初的坏块(也就是统计出哪些块是坏块),并且创建最初的坏块表,并且确保禁止对最初坏块信息的擦除。

         对于大页面(2K Bytes)的FLASH来说,比如K9K8G08U0D,初始坏块的状态定义在spare area的第一个字节,也就是第2048个字节,三星确保每个初始坏块的第1或是第2页的第2048个字节的数据位非0xFF,所以系统就是根据此字节的内容来判断的,下面是识别出初始坏块的流程:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图8

在第一次向FLASH写入镜像文件时,而且在写入之前需要执行“F) Low-level format the Smart Media card”和“9) Format Boot Media for BinFS\r\n”,然后再是烧录镜像文件,先来看F对应的内容:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图9

这样就可以把FLASH初始的坏块标识出来了,当然这里,对于bootloader所占用的块(前6个blcok)没有做判断,而是直接标识为坏块、预留与只读块。

 

⑴FMD_WriteSector函数

FMD_WriteSector函数主要是通过调用NAND_LB_WriteSectorInfo函数来把SectorInfo结构体数据及ECC校验码写入到nbootC和EBOOT之间占用块的spare area中,我们先来看NAND_LB_WriteSectorInfo函数的主要实现部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图10

结合图7和10的实现,可知每页中spare area的数据布局如下图所示:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图11

⑵FMD_GetBlockStatus函数

此函数主要是最终通过调用NAND_LB_ReadSectorInfo函数来读取block中spare area data来判断块的状态,下面来看NAND_LB_ReadSectorInfo函数的主要部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图12

图12中提到从NFSECC寄存器中读出spare area数据的ECC校验码之后,为什么还要写入到NFSECCD寄存器中呢?NAND FLASH控制器中有一段这样的描述:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图13

也就是说为了比较ECC硬件模块产生的ECC校验码,从FLASH中读取的ECC数据必须写入到NFMECCDn寄存器(对应于main area)和NFSECCD寄存器中(spare area),只有这样NAND FLASH控制器才能比较出写入和读取出来的数据是由一致。

 

接着看“9) Format Boot Media for BinFS\r\n”对应的动作:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图14

 

该函数用于低级格式化,它会格式化Flash设备中的Block,重新创建MBR并将MBR存到第一个Blockd的第一个扇区中。dwStartBlock为起始Block,dwNumBlocks为多少个Block,dwFlags为格式化标记位,表示采用何种格式化方式。该函数会根据需要来由EBOOT中的函数调用,下面来看此函数体:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图15

⑴EraseBlocks函数

此函数内容很多,分下面几部分说明:

第一部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图16

第二部分:

因为指示坏块的标识位能够被擦除,我们采取了谨慎的做法,就是对block写数据并读取出来来验证是否为好快,但此动作需要额外的时间,我们用的是1Gbytes大小的SLC FLASH,此动作需要约为10分钟的时间,下面看具体的实现细节:

 WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图17

到此就已经能够全部把坏块找出来,并且确保把好块的数据写入0xFF。

 

⑵ CreateMBR

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图18

其中,硬盘有效标志为(55AA),这样可知,WINCE的MBR数据布局如下所示:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图19

接下来看WriteMBR函数

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图20

因为我们FLASH的布局是:nboot(第0block)+TOC(第1block)+EBOOT(第2到第5block)+MBR(从第6block开始的第一个好块)+NK+用户数据,而我假设第6block就是好块,结合图15可知,g_dwMBRSectorNum=6*64=384page,也就是第6个block的第0个page。

 

// end of sector - 2 bytes for signature - maximum of 4 16-byte partition records

1.1.3          DownloadImage函数

接下来我们选择S来通过TF卡下载镜像文件,BootloaderMain函数调用DownloadImage函数来实现下载,就是把nboot文件从TF卡中读取出来保存在SDRAM中。

⑴从TF卡中读取stepldr.nb0读取出来。

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图21

主要是把nb0文件的7字节的magic number、校验和、文件数、文件起始地址、文件大小、文件名称和文件内容读取或是计算出来拷贝到0xA4500000开始的内存单元中,这段内部的数据布局如下所示:

 

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图22

 

⑵DownloadImage函数

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图23

下面分几部分就来学习DownloadImage函数:

第一部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图24

这部分主要是读取文件7字节的magic number来判断文件的类型,读取要烧录的文件数、校验和、文件开始地址、文件大小和文件名。

第二部分:

 WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图25

第三部分:

*pdwImageStart  = pCurDownloadFile->dwRegionStart;

*pdwLaunchAddr  = pCurDownloadFile->dwRegionStart;

*pdwImageLength = pCurDownloadFile->dwRegionLength;

主要是把stpeldr.nb0文件的开始地址,长度复制给这些指针放回去,这样就知道了stepldr.nb0的这些信息。

1.1.4          OEMLaunch函数

OEMLaunch函数主要是通过调用WriteRawImageToBootMedia函数来实现的,下面就来看WriteRawImageToBootMedia函数的主要实现部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图26

接下来看WriteBlock函数体:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图27

下面就来看FMD_LB_WriteSector_Steploader函数是如何把stepldr.nb0文件写入到FLASH中的:

第一部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图28

 

第二部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图29

为了理解这部分的内容,我们来看NAND FLASH控制器中的相关描述:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图30

因为我们采用的FLASH页大小为2048+64的,大于512,所以需要先分别从NF8MECC0~NF8MECC3中拷贝ECC校验码到临时数组变量t8MECC中,然后再写入到spare area中,接下来看第三部分:

WINCE6.0+S3C2451 eboot烧录stepldr.nb0文件 - 男儿当自强 - 男儿当自强的博客

图31

到此这三部分可知,把stepldr.nb0写入第0block的过程中,没有写spare data到spare area中,这也是因为读取第0block的stepldr数据的ECC校验在IROM中已经check的原因吗?目前还不是很清楚,学习到这里,回到图9中,这里如果是从第64页,也就是第1block开始,也就是可以理解。

 

  评论这张
 
阅读(1464)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017