基于S3C2440的WinCE Bootloader的分析与设计
扫描二维码
随时随地手机看文章
摘要:针对BootLoader严格依赖于具体的嵌入式硬件系统,并且从头开发一套适合特定硬件系统的BootLoader又相当复杂这一问题,分析设计了基于S3C2440的WinCE操作系统的引导程序的实现方法。结合飞凌公司的嵌入式产品TE2440的硬件特性,对BootLoader启动的两个阶段和配置文件进行了详细的分析和设计,最终实现了系统引导加载程序的构建。为项目后续的开发奠定了良好的基础。
关键词:嵌入式系统;引导程序;WinCE;EBoot
Bootloader的开发是嵌入式系统开发必不可少的环节,一个好的Bootloader不仅可以给项目的后续开发工作带来很大便利,而且在项目开发结束后对用户使用产品也提供了很多方便。但是,由于嵌入式的硬件是无标准、非规范的,Bootloader的功能又是直接与微处理系统相关的,所以给开发人员的工作带来了许多不便。在实际的项目开发中,一般都需要对特定的硬件系统进行Bootloader的设计,可是从头开发一套系统的Bootloader是非常复杂并且耗时的,针对这一难点,微软公司推出的面向嵌入式应用领域的操作系统Windows CE体现了非常大的优势,Windows CE具有强大的操作系统功能、稳定可靠的性能、高度的模块化、可定制性、与桌面Windows平台一致的开发特性。它最大的优势是具有高度的模块化,可以提供与硬件无关的软件框架,把与硬件无关但是又代表普遍通用性的内容抽取出来,形成标准函数库。而与硬件相关的不具有通用意义的BootLoader代码则由开发人员具体负债开发,这样就给开发人员带来了相当大便利。并且开发出的Bootloader因是严格按照微软提供的模板开发,所以又有很好兼容性且效率高。
由于Bootloader的实现依赖于CPU的体系结构,因此从固态存储设备上启动的BootLoader大多都是两个阶段的启动过程。本文以飞凌嵌入式公司的产品TE2440为例,详细分析Windows CE BootLoader开发的两个阶段过程。TE2440的微处理器采用三星公司的S3C2440A,主频400MH-z,内置64 MB SDRAM和64 MB NANDFLASH,10 M网口,采用CS8900Q3。S3C2440支持2种启动模式:一种是从NandFlash启动;另一种是从NorF-lash启动,TE2440支持从NandFlash启动。
1 Bootloader的第一阶段分析
为了防止给后来的调试工作带来更多的麻烦,要尽量使第一阶段做尽可能少的工作,只要使CPU正常工作起来即可,然后把大量复杂的初始化工作留给第二阶段来做。第一阶段是在ADS(ARM Developer Suite)环境下开发的。S3C2440系统引导加载程序包括2440init,s、2440-lib.s函数库、2440lib.c函数库、mmu,c、dma,c函数库等几个主要的文件。因为与硬件密切相关。所以通常采用汇编语言编写,本文主要分析s3c2440系统在加电后的硬件设置处理过程,即2440init.s文件中的程序执行过程。
第一阶段主要包括如下步骤:
(1)进入启动程序的入口地址,禁止看门狗、屏蔽所有中断。因为为中断提供服务通常是操作系统设备驱动程序的责任,所以在Bootlo-ader的执行全过程中可以不必响应任何中断。中断屏蔽可以通过写CPU的中断屏蔽寄存器或状态寄存器来完成。
[!--empirenews.page--]
(2)设置CPU的速度和时钟频率
根据工作频率设置时钟、PLL,2440内部3个时钟:FCLK、HCLK、PCLK,分别供CPU、AHB总线和APB总线使用,一般都选择周期比为1:2:8的设置。
(3)初始化基本硬件和存储器系统
(4)设置堆栈并跳转至第二阶段的入口。将FLASH中的代码段、数据段拷贝到RAM中,将初始化数据段,跳入C语言的main函数执行,结束Bootloader初步引导;Bi的主要功能是引导和加载操作系统,不会用到很多种类型及数量的外设,如果在BL中启用中断反而会使对问题的处理复杂化。
[!--empirenews.page--]
2 Bootloader的第二阶段分析
第一阶段结束之后,函数跳转到由C语言写的main()函数,也就是Bootloader开发的第二阶段EBoot,该阶段的开发环境是Platform Builder,简称PB,它是微软提供给开发人员进行基于Windows CE平台下嵌入式操作系统定制的集成开发环境。main()函数实现代码为:
该函数主要功能就是调用BootloaderMain()函数,其实main函数不是必须的,实际上程序也可以直接跳转到BootloaderMain()函数,在第一阶段的汇编代码后加入main()函数可以更好地提高程序的性能。本文主要分析BootloaderMain()调用的一些关键的函数,函数调用关系如图1所示。
最早被BootLaderMain()调用的OEM函数是OEMDebugInit(),它负责初始化BootLoader的调试功能串口,在它被调用运行之后BootLoader的代码才可以调用它的调试输出功能函数。OEMDebugInit()调用OEMInitDebugSerial()来初始化调试串口。[!--empirenews.page--]
OEMPlatformInit()函数是BootLoader的最重要的OEM函数,所有与BootLoader所需硬件功能有关的目标平台板级外设如以太网接口、Fl-ash存储器等都在这里进行初始化,包括嵌入式CPU芯片内置的外设。它结束后就开始下载工作了。函数代码如下:
OEMPreDownload():所有在硬件初始化完成以后、开始下载操作系统镜像之前所需要处理的任务都可以放在该函数完成。它主要任务是以太网下载前的准备工作。DownloadImage()的任务是从远程开发机上下载操作系统镜像到RAM。它通过调用OEMReadData()从下载端口读取操作系统镜像的数据,在本文的EBoot中,该函数主要负责从以太网端口读取操作系统镜像数据;它还调用OEMShowProgress()函数用来向用户显示BootLoader下载操作系统镜像时的下载状态。OEMMapMemAddr()函数用于当下载得到的操作系统镜像自身所记录的目的地址是Flash存储设备时该OEM函数要负债将镜像的数据以重定位的方式暂存到RAM内存缓冲区中。
OEMLaunch()是最后一个被BootLaderMain()函数调用的。它的主要功能是实现目标嵌入式系统程序执行流跳转。无论BootLoader是通过以太网端口下载操作系统镜像还是从本地读取操作系统镜像到内存,都要依靠该函数将程序的执行流从BootLoader转移到Windows CE的操作系统。Downloadlmage()函数下载的操作系统镜像是暂存在RAM中的,所以我们还需要在OEMLaunch()函数指令执行跳转之前保存下载所得的操作系统镜像以及用户配置数据到Flash,以便系统从新启动或者复位时可以直接从本地存储读取镜像数据。
3 配置文件
Bootloader源代码编译后会产生一个名为eboot.exe的可执行文件,但写入Flash的Bootloader是一个二进制的映像文件,也就是.bin文件或.nbO文件,所以需要把eboot.exe文件转换成.bin文件或.nbO文件。
4 烧写Bootloader
配置好了之后,在PC机中编译产生了Eboot.bin文件,把Bootloader烧写到目标机中。利用三星公司的sjf2440工具烧写,使用JTAG实现下载。BootLoader下载后再通过以太网口把操作系统内核镜像文件下载到目标机中。下载镜像所使用的软件是DNW,DNW是三星公司为S3C2 440芯片配置的一款专用软件,它可以在Windows下通过USB方式烧写Flash。如图2所示,内核镜像已下载到NandFlash中。
5 结语
BootLoader的设计和实现是一个非常复杂并且重要的过程,一个好的Bootloader可以给嵌入式产品的开发调试工作带来许多便利。本文从源代码人手详细分析了Wince Bootloader启动的两个阶段以及配置文件信息。实验达到了预期的效果,为项目后续的开发奠定了良好的基础。