跳至主要内容

【转】S3c2410/2440的Eboot流程介绍

对于嵌入式系统来说,一般都需要一个bootloader来下载和引导操作系统,常用的bootloader有eboot,uboot以及vivi等,对于windows ce来说最理想的bootloader当然是eboot(我也做了利用uboot下载和引导ce,以后我会介绍)。下面我就把自己开发eboot的过程和大家分享。eboot的流程可以如下图所示:

1)eboot和nk公用一段起始代码fw.s,所以我们会在eboot文件夹下的arm子文件夹找到fw.s,里面就一句话: INCLUDE ..\\..\\kernel\\hal\\arm\\fw.s,对于这段起始代码我就不详细分析,无非是建立好中断向量表,设置好系统的工作频率,设置MMU等,然后就跳转到eboot的main函数

2)eboot的main函数在eboot文件夹的main.c里面,代码如下:

void main (void)

{

BootloaderMain ();

SPIN_FOREVER;

}

是不是觉得很简单,好像什么也没有做,但是注意这个BootloaderMain函数,这个就是eboot真正的main函数,这个函数在

$(_WINCEROOT)\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BLCOMMON\blcommon.c里面,这个函数是微软的ce对eboot的通用函数,它会调用在eboot文件夹里面由OEM商或者自己写的一些函数。那既然我们知道了真正的main函数在哪里,那么下面我们跟着BootloaderMain走吧。

3)在BootloaderMain 函数里面首先执行KernelRelocate,这是把一些全局变量存放到ram里面去,这个函数不是很重要。

4)下面就是执行OEMDebugInit,看到OEM三个字母了没有,这就说明这个函数是OEM商,或者我们自己需要实现的,在eboot下的main函数里面可以找到这个函数,这主要是提供给blcommon一些回调函数如下所示:

BOOL OEMDebugInit()

{

// Assign callback functions to be usec by blcommon.

g_pOEMReportError = OEMReportError;//错误报告函数

g_pOEMVerifyMemory = OEMVerifyMemory;// 下载映象时检测内存是否正常

g_pOEMMultiBINNotify = OEMMultiBINNotify; //通知需要下载的所有bin文件

OEMInitDebugSerial();//初始化串口调试输出

return TRUE;

}

这些被调用的函数也是OEM商或者我们自己编写的。前面三个函数都可以在main.c里面找到,代码比较罗唆,而且基本上和硬件没有太大关系,我们看看最后一个初始化串口调试输出的函数,这个文件在D:\WINCE420\PLATFORM\smdk2410eboot+rtc\KERNEL\HAL\debug.c里面,我这里是设置串口0为调试输出口,三星自带的用的是串口1,并且把波特率设置为115200,大家如果需要用串口0作为调试输出口可以参考我的修改:

#define UART0BaudRate 115200

void OEMInitDebugSerial(void)

{

volatile UART1reg *s2410UART0 = (UART0reg *)UART0_BASE;

volatile IOPreg *s2410IOP = (IOPreg *)IOP_BASE;

s2410IOP->rGPHCON &= ~((3 << 8) | (3 << 10));

s2410IOP->rGPHCON |= ((2 << 4) | (2 << 6)); //

s2410IOP->rGPHUP |= (1 << 2) | (1 << 3);

s2410UART0->rUFCON = 0x0; // Disable the FIFO

s2410UART0->rUMCON = 0x0; // Disable AFC.

s2410UART0->rULCON = 0x3; // Normal mode, N81.

s2410UART0->rUCON = 0x245;

s2410UART0->rUBRDIV = ( (int)(S2410PCLK/16.0/UART0BaudRate + 0.5) -1 );

}

调用完这个调试输出初始化函数以后,eboot的调试信息就会从串口0出来(当然nk的调试信息也会从这个串口出来了,因为这一部分是和nk复用的^_^)

5)BootloaderMain调用完OEMDebugInit后就调用下一个函数了-OEMPlatformInit,这个函数也在eboot的main.c里面可以找到,主要是初始化你的硬件平台,包括设置RTC时钟,初始化一下你的NANDflash,然后就是读TOC (table of contents),一般TOC都会烧到nand的block1里面,如果读TOC失败,就会用默认的参数重写TOC,读TOC这段代码比较简单,在fmd.cpp里面,大家可以自己研究。然后就是进入倒计时,如果在你设置的延迟时间内按键盘的话就会进入BootMonitor这个函数,这个函数主要是输出eboot的选择菜单,根据你的选择进行操作,如果在延迟时间结束你没有按键盘的话就会根据你设置的是Download new(下载新的映象)还是Launch existing(加载在nand中的映象)来进行下一步操作,我们先看看BootMonitor这个函数,这个函数虽然代码很多,但是其实非常简单,就是根据你的输入来设置改变一些全局变量,eboot在后面会根据这些变量来进行相应的操作。

如果选择了下载映象,在OEMPlatformInit函数里会调用InitEthDevice初始化网卡,然后返回true,InitEthDevice函数在ether.c里面,具体需要根据你使用的网卡,把一些接口提供给eboot,下面是我的InitEthDevice函数,我使用的是DM9000网卡:

BOOL InitEthDevice(PBOOT_CFG pBootCfg)

{

USHORT wMAC[3];

PBYTE pBaseIOAddress = NULL;

DWORD dwMultiplier = 0;

// Boot CS8900.

//

if (!pBaseIOAddress)

{

// Use the MAC address programmed into flash by the user.

//

memcpy(wMAC, pBootCfg->EdbgAddr.wMAC, 6);

pfnEDbgInit = DM9000DBG_Init;

pfnEDbgGetFrame = DM9000DBG_GetFrame;

pfnEDbgSendFrame = DM9000DBG_SendFrame;

pBaseIOAddress = (PBYTE)CS8900DBG_IOBASE;

dwMultiplier = CS8900DBG_MEMBASE;

memcpy(pDriverGlobals->eth.TargetAddr.wMAC, pBootCfg->EdbgAddr.wMAC, 6);

pDriverGlobals->misc.EbootDevice = (UCHAR)DOWNLOAD_DEVICE_CS8900;

}

// Initialize the built-in Ethenet controller.

//

if (!pfnEDbgInit((PBYTE)pBaseIOAddress, dwMultiplier, wMAC))

{

EdbgOutputDebugString("ERROR: InitEthDevice: Failed to initialize Ethernet controller.\r\n");

return(FALSE);

}

// Make sure MAC address has been programmed.

//

if (!wMAC[0] && !wMAC[1] && !wMAC[2])

{

EdbgOutputDebugString("ERROR: InitEthDevice: Invalid MAC address read from NIC.\r\n");

return(FALSE); }

memcpy(&pDriverGlobals->eth.TargetAddr.wMAC, &wMAC, (3 * sizeof(USHORT)));

return(TRUE);

}

DM9000DBG_Init; DM9000DBG_GetFrame; DM9000DBG_SendFrame;这几个函数都需要在你的网卡驱动里面实现,这里只需要把这几个函数提供给eboot就行了。

6)BootloaderMain下面就调用OEMPreDownload进行一些下载前的准备工作,之后就会调用DownloadImage下载内核,下载完了后就调用OEMLaunch启动RAM里面的内核,注意OEMLaunch里面会需要和PB建立连接,如果我们要绕过PB下载nk(我在以前的文章里面已经介绍过实现的方法了)我们就需要屏蔽这段代码(在#ifndef SIMULATOR

评论

此博客中的热门博文

【转】AMBA、AHB、APB总线简介

AMBA 简介 随着深亚微米工艺技术日益成熟,集成电路芯片的规模越来越大。数字IC从基于时序驱动的设计方法,发展到基于IP复用的设计方法,并在SOC设计中得到了广泛应用。在基于IP复用的SoC设计中,片上总线设计是最关键的问题。为此,业界出现了很多片上总线标准。其中,由ARM公司推出的AMBA片上总线受到了广大IP开发商和SoC系统集成者的青睐,已成为一种流行的工业标准片上结构。AMBA规范主要包括了AHB(Advanced High performance Bus)系统总线和APB(Advanced Peripheral Bus)外围总线。   AMBA 片上总线        AMBA 2.0 规范包括四个部分:AHB、ASB、APB和Test Methodology。AHB的相互连接采用了传统的带有主模块和从模块的共享总线,接口与互连功能分离,这对芯片上模块之间的互连具有重要意义。AMBA已不仅是一种总线,更是一种带有接口模块的互连体系。下面将简要介绍比较重要的AHB和APB总线。 基于 AMBA 的片上系统        一个典型的基于AMBA总线的系统框图如图3所示。        大多数挂在总线上的模块(包括处理器)只是单一属性的功能模块:主模块或者从模块。主模块是向从模块发出读写操作的模块,如CPU,DSP等;从模块是接受命令并做出反应的模块,如片上的RAM,AHB/APB 桥等。另外,还有一些模块同时具有两种属性,例如直接存储器存取(DMA)在被编程时是从模块,但在系统读传输数据时必须是主模块。如果总线上存在多个主模块,就需要仲裁器来决定如何控制各种主模块对总线的访问。虽然仲裁规范是AMBA总线规范中的一部分,但具体使用的算法由RTL设计工程师决定,其中两个最常用的算法是固定优先级算法和循环制算法。AHB总线上最多可以有16个主模块和任意多个从模块,如果主模块数目大于16,则需再加一层结构(具体参阅ARM公司推出的Multi-layer AHB规范)。APB 桥既是APB总线上唯一的主模块,也是AHB系统总线上的从模块。其主要功能是锁存来自AHB系统总...

搞笑

1.55岁的周润发宣布死后将捐出99%的财产,什么都不想带走。作家顾晓军评论道:千万不要捐到大陆来,不要害了无辜的官员。 2.发改委成立至今只做过两件事:1)涨价,2)替涨价辩护。 3.目前中国有效的反腐手段有:1夫妻反目;2家中被盗;3情人举报;4狗咬狗,5站错队 4.国外奶粉热销中国的原因:1没有三聚氰胺;2如果有,可以索赔巨款;3如果索赔不成,不会坐牢 5.1955年中国的人均收入是韩国的3.2倍,日本的1.1倍。但经过50多年翻天覆地的增长,2008年中国的人均收入是日本的3%,韩国7%,但韩国、日本从来没宣布自己经济怎么翻番,只有中国是天天说自己翻了很多番。 6.中国人固有一死,或死于地沟油,或死于石灰面粉,或死于结石奶粉,或死于毒疫苗,或死于危房,或死于拆迁,或死于躲猫猫,或死于日记,或死于酒色,或死于车轮下,或死于被自杀……死并不可怕,可怕的是你根本不知道自己是怎么死的! 7.中国不一定是和邻国土地争端最多的国家,但肯定是和本国公民土地争端最多的国家。 8.在谈所谓大国崛起之时,请扪心自问:你的收入崛起没有、你的住房面积崛起没有、你的护照免签国家数量崛起没有、你的食品安全崛起没有、你的医保社保崛起,你的国防力量增强了没有...如果都没有,那么大国再崛起关你P事。 9.日本人冈本真夜1997年的一首歌无耻地抄袭了我们2010年世博会的会歌,太可恶了!!? 10.什么是奇迹?我建了一座豆腐渣大楼,然后雇了150个短工装修,很多人说这房子容易塌,我充耳不闻。结果「哗啦」的塌了,把他们埋在废墟里整整八天八夜,我找人挖开塌坍时,有一百多人活着。这是个奇迹,更奇迹的是我他妈不但无罪,表彰会上我还成了救人的大英雄! 11.统计局宣布:中国城市人均月收入已突破9000人民币大关。拖祖国后腿的请自觉转发。 看到这个消息我不禁黯然神伤,仔细算算,我何止才拖了祖国的大腿,我都扒到祖国的臀部了,对不起,祖国---我是否扯到你的蛋了!! 

【转】select问题

问: 该串口初始化如下 ioctl(comm2Fd,FIOBAUDRATE,9600) ioctl(comm2Fd,FIOSETOPTIONS,OPT_RAW) 使用如下 FD_ZERO   (&readFds); FD_SET   (comm2Fd,   &readFds);   width   =   comm2Fd   +   1; FD_ISSET   (comm2Fd,   &readFds); FOREVER { if(timeoutvalue==0) { printf("\nselect   start!\n"); selectnum   =   select   (width,   &readFds,   NULL,   NULL,   NULL); printf("\nselect   over!\n"); }                                 ........... } 现在的状况是程序跑一段时间后会死机或这个串口通讯任务死掉,每次死机都是"select   start!"打印出来,而"select   over!"打印不出来,在仅这个串口通讯任务死掉的情况下,用comm1Fd超级终端登陆,查询任务状态,会发现tExcTask任务居然处于挂起状态??? 哪位大哥帮忙分析一下或给予一点提示,小弟不胜感激!! 答: sele...