关闭

关于EBoot和NBoot及.bin文件和.nb0文件的差别 12K Nboot-->4K

标签: flashwincebuffermakefileimagemicrosoft
921人阅读 评论(1) 收藏 举报
分类:

关于EBoot和NBoot及.bin文件和.nb0文件的差别

1
关于EBoot和NBoot的区别:
 S3C2410处理器支持将启动代码存储在NAND Flash中。为了实现这一功能,2410配备了一个名为“Steppingstone”的内部SRAM。在启动时,NAND Flash中第一个4K字节的内容将被加载到Steppingstone中并执行。这个工作由MCU主动完成,而我们只需将NAND Flash配置为Auto Boot模式即可。
 一般来说,启动代码会拷贝存储在NAND Flash中的内容至SDRAM中。在使用ECC校验时,NAND Flash中数据的有效性将被确认。在完成拷贝的工作后,启动代码将跳转到已加载到SDRAM中的主程序中,这时启动代码的使命完成,MCU由主程序来控制。
 WinCE操作系统从文件的组成来看一般分为两部分:BOOTLOADER和NK.bin。在WinCE中,BOOTLOADER一般为EBOOT。它的主要功能是初始化硬件设备,主要包括CPU内部的相关控制器、内存、网络、串口甚至USB口和LCD。在初始化完成后,它将通过网络或USB从外部下载 NK.bin,或从本地Flash中加载NK.bin并执行,从而启动WinCE操作系统。可以看到Eboot虽然是启动代码,但它得完成相当多的工作,最终的映像文件也将超过4K。所以,我们不能直接将Eboot存放在NAND Flash的第一个4K字节中。我们需要一个更小的启动代码,这就是通常所说的NBOOT(NAND BOOT)。
 通过上面的介绍,我们知道了NBOOT在整个系统中扮演的角色,它负责将EBOOT加载到内存并运行。在EBOOT开始执行后,NBOOT就退出了历史的舞台,事实上也不再有上场的机会。
 在NBOOT的代码实现中,我们必须完成以下几个部分。
1. 初始化CPU内部相关控制器,如设置GPIO,关闭Watch Dog,关闭中断,设置系统时钟。
2. 初始化内存。
3. 初始化串口,主要用来输出调试信息。
4. 初始化NAND Flash,因为在MCU启动时默认是Auto Boot模式,为了从NAND Flash中读取EBOOT,需要将其配置成 NAND Flash Mode。
5. 读取NAND Flash中的EBOOT映像文件,并放在内存指定的位置,这个地址是跟EBOOT有关,介绍EBOOT时再详细说明。
6. 完成读取之后,跳转到EBOOT的起始位置,执行EBOOT代码。
一般来说,前面两个功能在startup.s中实现,WinCE6.0下可以参考文件 C:"WINCE600"PLATFORM"DEVICEEMULATOR"SRC"BOOTLOADER"EBOOT"startup.s的相关代码。后面四个功能可在main.c中实现。总之,在实现必备功能的情况下,尽可能减少代码量,以将最后的NBOOT映像文件控制在4K以内。
NBOOT 的编译环境一般有两种,ADS1.2(或RVDS)、Platform Builder。用ADS1.2编译NBOOT是比较方便的,需要注意的就是RO Base和RW Base的设置,RO Base必须设置为0x0。否则,系统启动时NBOOT将不被运行。在Post-Linker中选择ARM from ELF,在Linker——ARM fromELF——Output Format中选择Plain Binary,这样,编译完成后最终生成NBoot.bin。该文件就可以固化在NAND Flash的第0个BLOCK中。Platform Builder 6.0是作为VS2005的插件来用的,所以,我们现在也可以用VS2005来编译NBOOT,这样就免得再安装ADS或RVDS等软件。用VS2005 来编译NBOOT也有两种方法,第一种跟编译EBOOT映像文件类似,第二种是自己写makefile文件,然后用命令行的方式调用ARM编译器来编译。两种方法各有优点,第一种方法在编译OS时,会自动编译生成映像,而第二种方法可由ADS下的程序直接移植过来,不过,要写好makefile文件是相当困难的事情。一般还是少用为好。
----------------------------------------------------------
.bin文件和.nb0文件的差别

eboot.nb0
eboot.bin
nk.nb0
nk.bin
.bin文件和.nb0文件的差别:
.nb0是可以直接烧到FLASH/ROM中的,是代码镜像,可以直接跳转到其入口执行。
.bin是Microsoft binary image格式的文件,必须按其格式定义解开到其指定的地址空间的位置才能执行。
两个都是CE的镜像,通过串口直接下载用nb0,pb下载用bin,nb0文件要大一些。
nb0是非压缩的数据,里面的数据是实际的NK展开以后在内存里面的数
bin是有压缩的数据,里面的数据是压缩以后类似于成块形的数据,被loader拷贝到内存以后没有区别。



2
nboot 是从NAND flash读image到内存并执行,eboot是从以太网(用tftp)下载image到内存并执行。将nboot.nb0烧到第0块,将 eboot.nb0烧到第2块。启动时nboot从flash读出eboot并执行之,如何就可以通过pb把nk.bin下载到目标板上执行了,开发机和目标板可以用交叉线直接连接。

nboot是nand flash bootloader的意思。S3C2410可以直接从nand flash 启动,但是不能超过4k。nboot是系统启动后最先执行的代码,它有两种,一种是跳转到eboot;一种是跳转到nk。主要的功能其实是在eboot里。

NBOOT的结构以及生成方法

以前的nboot都是用ADS编译链接,简单明了。这次BSP包含的nboot是WinCE的工具链生成,结果出来的.nb0竟然有12KB,而三星的Steppingstone只有4KB,怎么剪裁涅?花了点时间把.log .map .rel .bib .bin .nb0仔细看了下,终于搞清楚12KB的nboot包含了些东西。

startup.s文件:
OPT 2
INCLUDE kxarm.h
OPT 1
OPT 128
IMPORT main
STARTUPTEXT
LEAF_ENTRY StartUp
b main
END
main.c文件:
#include
#include
#include
ROMHDR * volatile const pTOC = (ROMHDR *)-1;
static int gI1;
static char *gBuf = "global str";
static int gI2 = 2;
int test(char *str)
{
int ret = 0;
while(*str)
{
ret += *str++;
}
return ret;
}
void main(void)
{
gI1 = 1;
test("is .rdata str?");
test(gBuf);
}

.map信息:
Preferred load address is 00010000
Start Length Name Class
0001:00000000 00000004H .astart CODE
0001:00000010 0000003bH .rdata CODE
0001:0000004c 00000024H .rdata$debug CODE
0001:00000070 0000004cH .text CODE
0001:000000bc 00000000H .edata CODE
0002:00000000 00000008H .data DATA
0002:00000008 00000004H .bss DATA
0003:00000000 00000008H .pdata DATA
entry point at 0001:00000000
其中
.rdata:pTOC、2个字符串
.data:gBuf、gI2
.bss:gI1

build.log信息:
Module Section Start Length psize vsize Filler
nk.exe .text 00001000 4096 512 188 o32_rva=00001000
nk.exe .pdata 00002000 4096 512 8 o32_rva=00003000
nk.exe .data 000010bc 5 5 12 FILLER->33ff0000
nk.exe E32 000010c4 112 FILLER
nk.exe O32 00001134 72 FILLER
Module Section Start Length psize vsize Filler
nk.exe FileName 0000117c 7 FILLER
Unfilled ROM holes (address, length):
00002008 4088 00001184 3708
total space 7796 in 2 ranges

结合.map信息可知:
.text包含:.astart .rdata .rdata$debug .text .edata,也就是0xBC(188)
.pdata包含:.pdata
.data包含:.data .bss,psize之所以是5,是因为"static int gI2 = 2"只占1B
注意:.bin文件的.text和.data节是连续的。

查看.bin的record info:
Image Start = 0x00000000, length = 0x00002008
Record [ 0] : Start = 0x00000000, Length = 0x00000004, Chksum = 0x000001EB
Record [ 1] : Start = 0x00000040, Length = 0x00000008, Chksum = 0x000001A5
Record [ 2] : Start = 0x00000048, Length = 0x00000004, Chksum = 0x00000095
Record [ 3] : Start = 0x00001000, Length = 0x00000184, Chksum = 0x000046D8
Record [ 4] : Start = 0x00001184, Length = 0x00000054, Chksum = 0x000007B2
Record [ 5] : Start = 0x000011D8, Length = 0x00000030, Chksum = 0x000008F6
Record [ 6] : Start = 0x00002000, Length = 0x00000008, Chksum = 0x000000C3
Record [ 7] : Start = 0x00000000, Length = 0x00001000, Chksum = 0x00000000
Start address = 0x00001000
Checking record #4 for potential TOC (ROMOFFSET = 0x00000000)
Found pTOC = 0x00001184
ROMOFFSET = 0x00000000

用ADS反汇编展开后的.nb0:
0KB~4KB:REC[0]是 b 0x1000 跳转指令;REC[1/2]似乎是签名之类。
4KB~8KB:REC[3]包含所有Section(除.pdata外);REC[4]是ROMHDR;REC[5]未知
8KB~12KB:REC[6]是.pdata
REC[7]的Start和Chksum都是0,则Length指明EntryPoint。

假如不考虑重定位,把.nb0的0x1000开始的4KB烧入NAND Flash就大功告成了。

简化main.c文件:
#include
#include
#include
ROMHDR * volatile const pTOC = (ROMHDR *)-1;
void test(char * str)
{
while(*str)
{
*(volatile unsigned char *)0x1234 = *str++;
}
}
void main(void)
{
test("Step ldr/r/n");
}

.rel信息:
0003 0001 00001088 00000000
也就是0x1088处需要重定位。

用ADS反汇编展开后的.nb0:
0x1064 ldr r2,0x00001088 ; = #0x00000030
0x1088的值是0x30,根据.map文件可知0x1030存放字符串"Step ldr/r/n"

因此去掉.nb0的开始4KB页后,0x30就是字符串的地址。
假如把.bib文件中的,RAMIMAGE的Start和ROMSTART都从0->0x1000,则0x1088的值是0x2030,就不能去掉.nb0的开始4KB页

Nboot (Nand flash bootloader) 主要的作用就是初始化硬件,把后面的功能比较完善的引导程序像eboot之类的映像拷贝到SDRAM中让后跳到SDRAM中继续跑eboot。

为什么要有nboot这个东西呢,其实主要是因为现在的soc上考虑到成本的问题,基本是都是自带一个nand flash的控制器并支持开机nand flash引导来取代相对来说昂贵的nor flash。


一般来说nand flash的控制器都会内置一个SRAM之类的buffer来支持nand flash的开机引导,在nand启动的方式下,板子上电的时候,nand控制器会自动把nand flash最前面的buffer大小的数据自动拷贝到buffer中然后让pc指针可以从buffer中直接读取指令。一般来说这个buffer不会很大,2410的芯片是4k,而像freescale的imx21更是只有2k,所以由于这个局限性,我们只能把bootloader拆分成两部分,前面一部分来完成基本初始化功能,而后面一部分来完成比较完善的功能,让控制器自动拷贝前一部分,然后前一部分再拷贝后一部分到RAM中,这样引导程序就可以做任何它想做的事情了。


其实,实现一个nboot并没有多大难度,以下是一个大概流程:

1. 当然是配置时钟了,没这个系统跑不起来啊 o(∩_∩)o…


2. 不用说SDRAM的配置也是少不了,不然我们怎么把程序拷贝到SDRAM中。


3. 就是flash控制器的配置了,一般来说就是GPIO和相应的控制器寄存器配一下。


4. 拷贝文件从nand到SDRAM中,nand flash读的话一般来说都是先拉片选位,然后发命令,接着是地址,最后就是读数了。


上面几步做完,其实整个nboot也就差不多了,不过在WinCE下开发的话有几个点需要特别注意:

1. 因为要用PB来编译,所以为了能生成.nb0文件,所以一定要在 代码里加上:

pTOC DCD -1

EXPORT pTOC

这个是让ROMIMG.exe做image时用的.



2. 生成.nb0文件,bib文件也是不能少的。


3. 因为微软编译器的原因,导致了我们按一般方法来编译.nb0时,前面的4K都是空的,所以如果直接把编译出来的.nb0烧进去的话是不能用的,所以的在bib改一下:

把: NBOOT 00000000 00002000 RAMIMAGE 这个定义成8k的大小,然后后面的

ROMSTART=00001000

ROMSIZE=1000

把start地址往后移一下,然后大小改为4k,这样出来的nb0就会 把前面空的4k给截掉了。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:376380次
    • 积分:5914
    • 等级:
    • 排名:第4269名
    • 原创:201篇
    • 转载:56篇
    • 译文:3篇
    • 评论:58条
    我的新书

    《嵌入式Linux系统开发入门宝典》已出版,新书基于ARM Cortex-A8处理器编写,全书从拿到开发板如何上电开始讲起循序渐进,通俗易懂。

    网上购买:京东 当当 天猫 亚马逊
    博客专栏
    最新评论