文献标识码:A
文章编号: 0258-7998(2012)02-0014-04
Windows Embedded Compact 7(以下简称Compact 7)操作系统在访问底层硬件时,不直接访问硬件,而是通过抽象出来的函数访问。抽象出来的函数层,就是通常所说的板支持包BSP(Board Support Package)[1]。BSP介于底层硬件和操作系统之间,完成硬件初始化并将控制权切换给操作系统。由于嵌入式系统的底层硬件具有无标准、非规范等特性,操作系统都存在着BSP移植的问题,这就要求BSP开发人员在BSP开发过程中熟练掌握具体的硬件原理和软件实现方法。
Compact 7与之前的Windows CE版本一样,提供了一整套平台开发工具Platform Builder,使开发人员能够快速灵活地创建解决方案[2]。而且Platform Builder本身也提供了多种目标板的BSP样例,可以在开发移植BSP时作参考。
1OMAP3530处理器
TI公司推出的OMAP3530是一款技术先进的高性能嵌入式异构双核处理器,主要由一个600 MHz的CortexTM-A8 ARM核和一个430 MHz的DSP 核组成。嵌入式操作系统在ARM核上运行,与数字信号处理相关的任务则由DSP核负责。尽管OMAP3530是一个异构多核架构的微处理器,但DSP核对于基于ARM核开发的工程师而言是透明的。在软件工具链中,TI引入了DSP桥的概念。DSP桥是针对ARM应用程序开发提供的一组面向DSP算法的应用程序接口(API),以便应用程序获取DSP核的计算资源和数据资源。
2 Compact 7操作系统
Windows Embedded Compact 7是Windows CE 6.0的后续产品,它不仅是一个功能强大的实时操作系统,而且还为开发者提供了全套开发工具。作为Windows CE家族的换代产品,Compact 7继承了之前Windows CE系统的优良传统,又在其上增加了对ARMv7构架的支持;对Windows CE先前版本的强大功能进行了进一步的扩充和丰富,如支持多点触控、优化电源管理等。
与Windows CE 6.0不同,Compact 7的平台开发工具Platform Builder依托于Visual Studio 2008,内嵌的Silverlight for Windows Embedded有利于减轻开发者开发界面的负担。在软件开发上,Compact 7彻底摒弃传统的MFC程序框架,转而全面支持.Net framework。高效的开发框架,将最大限度地提高开发者的工作效率,有助于提高产品的市场竞争力。
3 OMAP3530开发板硬件构成
开发板硬件平台主要以TI公司的OMAP3530双核处理器为核心,配有256 MB SDRAM和512 MB Nand Flash用以启动系统和存储运行程序。同时,还配有电源管理、USB、UART、以太网控制器、液晶屏等外围电路。基于OMAP3530处理器开发板的硬件结构框图如图1所示。
4 Compact 7操作系统下BSP开发与移植
Compact 7中BSP是由Boot Loader、OEM适配层、设备驱动程序、内核独立传输层(KITL)以及镜像配置文件五部分组成[3]。关于各部分之间的相互联系以及与硬件平台之间的关系如图2所示。
4.1 Clone BSP
Compact 7提供了两种方法开发BSP,一种是从零开始进行BSP开发的方法,另一种是克隆已有的BSP再进行移植的方法。Clone BSP实质就是对现有的BSP进行复制并按照开发者要求改变BSP的名称等信息。Clone BSP保留了原有BSP的程序架构和全部代码,开发者只需对BSP中部分代码进行修改添加即可实现新开发板的功能,简化了开发流程,提高了开发效率。考虑到从零开始开发BSP相当困难,OMAP3530开发板的BSP开发就采用Clone相似平台的BSP的方法进行移植。这样的实现方法可以大幅度降低开发BSP的难度并缩短开发周期。
具体方法是,在Platform Builder中使用其自带的Clone BSP工具,克隆TI公司提供的OMAP3530样例BSP,并自行定义名称(如MyBSP),然后设置相关描述(如平台目录名称、供应商名称以及版本号等信息)。如果设置信息合法,单击Clone按钮后会提示成功克隆BSP。克隆出的BSP位于%_WINCEROOT%\PLATFORM目录下。
4.2 移植Boot Loader
BSP移植首先要实现Boot Loader的功能。Boot Loader是一段启动引导程序,主要在Compact 7系统加载前初始化相关硬件,并把系统镜像加载到内存中运行。根据镜像boot的方式,Boot Loader分为nboot、eboot和uboot等。
OMAP3530处理器内嵌的RAM只有64 KB,对Boot Loader生成的可执行文件而言过于小,无法将其加载到内部RAM中,所以只能使用外部RAM进行加载。但OMAP3530上电时不能自动初始化memory controller,无法读写外部RAM。因此,需要一个程序负责初始化外部的RAM控制器,把可执行文件从 Nand Flash或者SD卡中读取到外部RAM中,然后跳转到入口处执行。实现这一功能的程序称为x-Loader,x-Loader是Compact 7启动之后运行的第一段程序,实质上是一个精简版的Boot Loader。x-Loader运行的第一个函数是startup()函数,startup()采用汇编语言编写,首要功能是对目标系统的CPU进行最基本的初始化。例如,清空TLB和cache、关闭中断、配置PLL、设置内存控制器、设置跳转到main的函数地址等。OMAP3530开发板上电后,CPU会自动从Nand Flash或者SD卡中加载x-Loader到内部RAM,然后执行初始化任务,最后将控制权交给Boot Loader。Startup()函数实现main函数跳转地址代码如下:
ldr sp, =( XLDR_STACK_PA+XLDR_STACK_SIZE)
b XLDRMain
其中,XLDR_STACK_PA和XLDR_STACK_ SIZE是任务堆栈起始地址和大小,系统通过使sp指针指向x-Loader中的任务堆栈起始地址的方法实现程序的跳转。
x-Loader位于BSP目录下的boot文件夹中,需要修改其中的platform.c和main.c两个文件。platform.c的作用是对OMAP3530功能进行设置,文件中包括PinMuxSetup()、GpioSetup()、ClockSetup()、MemorySetup()等几个重要的函数。
PinMuxSetup()函数专门用于设置引脚功能,这样做的好处是可以有统一的启动代码并且不必担心在启动过程中对复用引脚功能的再度修改。其实现样例代码如下:
OUTREG16(&pConfig->CONTROL_PADCONF_SDRC_D0,
(INPUT_ENABLE | PULL_INACTIVE | MUX_MODE_0));
OUTREG16函数用于设置OMAP3530 中的16 bit寄存器,该函数通过CONTROL_PADCONF_SDRC_D0获得处理器相应管脚的寄存器地址;通过设置INPUT_ENABLE、PULL_INACTIVE等参数来实现对管脚属性的定义;通过设置MUX_MODE_X的方法实现管脚功能的定义。具体MUX_MODE_X代表的功能定义,可参阅OMAP3530技术手册。
MemorySetup()函数用于初始化通用存储控制器(GPMC)和外部RAM(SDRC)。由于GPMC信号在Flash和以太网控制器上都用到。因此,在MemorySetup()函数中需要对GPMC片选信号进行设置。实现样例代码如下:
OUTREG32(&pGpmc->GPMC_CONFIG1_3,
BSP_GPMC_LAN_CONFIG1);
OUTREG32函数用于设置OMAP3530 中的32 bit寄存器,通过GPMC_CONFIG获得设置寄存器的地址;通过宏定义BSP_GPMC_LAN+CONFIG1设置具体数值。
main.c文件是x-Loader的主程序,在RELEASE模式下能够生成MLO执行文件,在DEBUG模式下编译配置文件 sources 跳过了对其的编译。因为x-Loader对大小有要求, 若DEBUG 编译文件过大,即使生成可执行文件也无法加载到OMAP3530内部RAM中。
x-Loader移植完成后,需要进行Boot Loader的移植。为了与x-Loader一致,Boot Loader下执行的第一个函数也是Startup()函数。Boot Loader下的Startup()函数同样是采用汇编语言编写的,主要完成静态逻辑地址到物理地址的映射以及跳转到BootloaderMain函数执行的功能。
Boot Loader开发重点是实现OEMPlatformInit()函数用以硬件初始化,这个函数与硬件具有高度的相关性[4]。总的来说,OEMPlatforminit()函数需要完成五项初始化任务:首先是通过OEMEthGetSecs()函数初始化定时器,其次初始化Nand Flash存储器,再次是复位外围设备,然后初始化用于下载镜像的以太网控制器,最后初始化操作系统的内存空间。
为了使Boot Loader支持以太网下载方式,需要实现与以太网控制器相关的函数。开发板以太网控制器选用SMSC公司的Lan9220芯片。其具体的实现过程如下:
(1)在%_WINCEROOT\PLATFORM\MyBSP\SRC\BOOT\
EBOOT下添加Lan9220dbg.c。
(2)在Lan9220dbg.c文件中实现LAN9220_Init、LAN-
9220_SendFrame和LAN9220_GetFrame 3个函数。
(3)在%_WINCEROOT\PLATFORM\MyBSP\SRC\INC下的kitl_cfg.h文件中声明上述3个函数,并定义BSP_ETHDRV_LAN9220结构体。结构体定义如下:
#define BSP_ETHDRV_LAN9220 {
(OAL_KITLETH_INIT) LAN9220_Init, NULL, NULL,
(OAL_KITLETH_SEND_FRAME) LAN9220_SendFrame,
(OAL_KITLETH_GET_FRAME) LAN9220_GetFrame,
NULL, NULL, NULL, NULL, NULL, NULL }
(4)在%_WINCEROOT\PLATFORM\MyBSP\SRC\BOOT\
EBOOT下的boot_cfg.h文件中添加BSP_ETHDRV_LAN-
9220到g_bootDevices内容中即可。
初始化传输端口通过修改OEMPreDownload()函数实现,在OEMPreDownload函数中首先需要为硬件平台指点一个静态IP地址,其次通过设置g_bootCfg.kitlFlags变量来设置IP协议,然后将boot方式设置成以太网下载模式,最后调用OEMLaunch函数来下载镜像。OEMLaunch函数的功能是下载镜像,并将程序计数器的指针直接设置到操作系统镜像的开始地址。它是启动操作系统前Boot Loader的最后一个函数,没有返回值。可以参考微软提供的标准BSP中的代码实现该函数。实现此函数后,Boot Loader的功能基本完成。
4.3 移植OEM适配层
OEM适配层OAL(OEM Adaptation Layer)逻辑上位于Compact 7内核和硬件平台之间。物理上可以生成可执行文件(NK.EXE)。OAL的出现大大方便了操作系统和硬件平台之间的通信。OAL还用来处理中断、控制时钟、管理电源、控制I/O接口等。
通常情况下,OAL创建的方法就是复制与自己开发平台相近且已经成功应用的OAL文件,然后进行适当的修改,OAL文件位于%_WINCEROOT\PLATFORM\MyBSP\SRC\OAL目录下。移植过程中需要修改OEMInit函数,该函数是在OEM适配层中初始化中断、时钟、KITL、计数器以及看门狗功能的。需要注意的是,如果要打开串口的debug功能,也要在OEMInit函数中进行设置,将OEMDeinitDebugSerial()函数注释掉。
4.4 开发设备驱动程序
BSP驱动程序属于内置驱动,与流驱动不一样的是,它不用设备管理器来管理,也不用导出与流驱动程序类似的API接口。此类驱动通常放在硬件平台的目录之下,如LCD显示、USB接口驱动就放在SRC\DRIVERS目录下。
以Touch的开发为例,简要介绍Compact 7下内置驱动的开发过程。Compact 7中Touch驱动采用分层方式实现,分为MDD(Model Device Driver)层和PDD(Platform Dependent Driver)层,分层结构方便了驱动程序的维护和移植。Touch驱动分层示意图如图3所示。
Touch驱动程序接收用户的触摸信息,并将其转换为触摸屏上的位置坐标信息,再传给图形、窗口和事件的子系统GWES(Graphics,Windowing, and Events Subsystem)模块。主要的工作是处理用户交互和图形输出等任务。触摸屏驱动就是被它加载的,同时被GWES加载的还有鼠标驱动、键盘驱动以及显示设备驱动。
对于初学者只需实现PDD层函数以及与MDD层通信的DDSI函数即可。MDD层与GWES模块通信的DDI函数已由微软实现。这样驱动开发的工作量会少很多,而代码的可靠性则有了更好的保证。
Compact 7触摸屏驱动程序采用中断方式对按下状态进行检测,如果检测到触摸动作时将产生中断并触发一个事件通知一个工作线程开始采集数据。同时,驱动将打开一个定时器,若触摸动作仍然存在,则定时触发同一个事件通知工作线程采集数据。驱动中采用了触摸屏中断以及定时器中断2个中断源,不仅可以监控触摸笔按下和抬起的动作,还可以检测到触摸屏按下时的拖动轨迹[5]。
由于OMAP3530开发板与触摸屏之间采用I2C总线通信,而Compact 7提供的样例是以SPI接口进行数据通信,因此,需要修改PDDInitializeHardware函数和PDDGetControllerData函数。对SPI接口的读写改为对I2C总线的读写;之后在PDDTouchPanelGetPoint函数中修改代码,按照具体触摸屏控制芯片的数据定义格式进行坐标转换;最后更改.reg文件中的注册信息,定义管脚号、驱动加载位置等。Compact 7系统启动过程中加载GWES模块后,GWES模块将根据注册表的信息加载触摸屏驱动。
4.5 移植内核独立传输层
在Windows CE系统中使用了内核独立传输层KITL(Kernel Independent Transport Layer)技术,其设计目标是向开发者提供一种简单的开发方式以支持调试服务。从Windows CE 6.0开始,KITL模块已经独立出OAL,在操作系统运行时已经有了一个独立的KITL.dll动态链接库。Compact 7操作系统继承了这一特性,同时也提供了大量的程序样例用于开发参考。
KITL的开发过程只需要完善OEM部分代码即可,这部分代码位于\SRC\KITL目录下。用户需要实现OEMKitlStartup函数、OEMKitlInit函数,同时需要构造相关结构体数据。OEMKitlStartup的功能是构造实际参数的数据,如代表KITL连接设备的标识符字符串、记录用户对系统KITL功能配置的数据以及所有可选KITL连接设备的硬件位置。OEMKitlInit的功能是构造一个设置KITL传输层端口的结构体数据。
OMAP3530开发板的KITL采用中断方式进行驱动。中断方式在OEMKitlStartup函数中设置。具体代码如下:
// Prepare interrupt
pGPIORegs = OALPAtoUA(BSP_ETHER_GPIO_PA);
SETREG32(&pGPIORegs->OE,
1 << (BSP_IRQ_ETHER_KITL % 32));
// Interrupt on falling edge
SETREG32(&pGPIORegs->FALLINGDETECT,
1 << (BSP_IRQ_ETHER_KITL % 32));
OEMKitlEnableClocks(FALSE);
之后在OEMKitlEnableClocks函数中修改IRQ管脚对时钟的响应。具体代码如下:
// IRQ pin
clockRoutines.pfnEnableDeviceFClock(OMAP_DEVICE_GPIO,
bEnable);
其中宏定义BSP_IRQ_ETHER_KITL和OMAP_DEVICE_GPIO的值由开发板上实际连接到LAN9220的中断信号的管脚决定。移植过程中对这两个宏定义进行修改即可实现KITL的功能。
4.6 设置配置文件
当创建一个Compact 7的工程时,可以通过添加环境变量、修改.bib和.reg等文件来重新配置BSP。Compact 7将配置文件分为两类,一类是源代码配置文件,如Dirs文件、Makefile文件以及Sources文件;另一类是镜像配置文件,如.bib文件、.reg文件、.dat文件等。开发人员必须理解相关配置文件的作用和使用方法才能合理地配置系统资源。
至此,BSP的开发流程已基本完成。开发移植好的BSP要在Platform Builder中编译生成可以在硬件开发平台上运行的二进制代码,通过SD卡将MLO和eboot.nb0下载到Nand Flash上,然后再通过以太网下载NK.bin到开发板上。
开发BSP 是一个基于具体硬件和软件的复杂过程,需要开发者对硬件和软件知识都有较为深入的了解[6]。BSP开发的正确性将直接影响到系统运行的稳定性。
参考文献
[1] 周建设.Windows CE设备驱动及BSP开发指南[M].北京:中国电力出版社,2009.
[2] 陈瑞,张永瑞,欧阳雄.基于XSCALE架构处理器WinCE系统BSP开发[J].电子科技,2006(2).
[3] Microsoft.BSP porting guide for Windows Embedded Compact 7[Z].2010.
[4] 李大为.Windows CE工程实践完全解析[M].北京:中国电力出版社,2008.
[5] 张毅,王海涛.基于S3C2410A的WinCE 5.0下触摸屏驱动的实现[J].重庆邮电大学学报(自然科学版),2008(6).
[6] 李海林,赵惠林,熊文峰.基于XScale PXA255处理器WinCE 420系统BSP开发[J].舰船电子工程,2006(3).