VxWorks设备驱动开发详解
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

3.4 VxWorks BSP文件组成

BSP是Board Support Packet的简称,即板级支持包,主要由平台初始化代码文件、外设驱动文件构成。当然,这主要是从BSP开发人员实际所需工作的角度而言的。实际上,BSP开发人员真正要完成的是VxWorks操作系统向特定平台的移植工作。这些工作除了包含平台初始化代码和外设驱动代码的编写外,还需要关心其他一系列文件并理解这些文件的功能,如此当出现相关问题时,可以快速定位问题的所在。本节从VxWorks操作系统移植的角度详细介绍一个典型BSP的文件构成以及文件具体的功能。

一个典型BSP的文件组成有如下类型:

● 源文件。

● 头文件。

● Makefile文件。

● 扩展文件(编译过程中生成的文件,如.o文件)。

● 说明文件(可选)。

其中,源文件和头文件主要存在于target/config目录下,这是源文件和头文件包括内核提供的以及由BSP开发人员提供的文件;Makefile文件指target/config/<bspName>以及target/h/make目录下的文件,<bspName>下的Makefile是属于某个特定BSP工程的文件,而target/h/make目录下的相关文件被所有的BSP工程使用;扩展文件指编译过程中生成的文件,这部分文件主要存在于<bspName>目录下;说明文件指存在于<bspName>目录下说明BSP信息的相关文件。

对于源文件和头文件,需要另外说明的一点是,除了target/config目录下的文件,内核提供(安装Tornado开发环境时安装的文件)的源文件主要存在于target/src目录下,而内核头文件则存在于target/h目录下。BSP开发人员在进行相关代码的查看时,可以到这些目录下去寻找。注意:禁止对内核源文件和头文件进行修改。BSP开发主要是修改和完善target/config目录下相关的源文件和头文件。

安装Tornado开发环境时,BSP是作为一个产品独立进行安装的,这是由Wind River公司针对一些平台提供的官方BSP,如integrator946es,前文中<bspName>就表示一个特定BSP的目录名称,可以使用任何对用户有意义的名称作为<bspName>。

3.4.1 源文件

Tornado开发环境安装完成后,在target/config目录下就包含由官方提供的一些BSP以及共用目录All,BSP开发人员一般复制一个近似平台的BSP,对其中的文件进行修改以及添加一些文件来开始BSP的开发过程,不要从零开始创建BSP,如此可以大大缩短BSP的开发时间,降低开发难度。target/config/all目录被config目录下所有的BSP使用,这个目录下的文件被所有的BSP使用,所以不要直接修改其中的文件。下文将介绍在修改all目录中的文件时如何进行处理。target/config/all目录下定义有如下源文件,所有这些都是BSP的一个组成部分。

① bootConfig.c。只被bootrom使用,VxWorks内核则使用usrConfig.c文件。

② usrConfig.c。只被VxWorks内核使用,bootrom则使用bootConfig.c文件。

注意

bootConfig.c和usrConfig.c文件中定义的函数基本类似,如usrInit、usrRoot等函数。有关各函数在初始化过程中被调用的时机,请参考本书前面章节的内容。

③ bootInit.c。其中包含romStart函数定义,该函数(romStart)将被romInit函数调用,负责将代码从ROM复制到RAM中。对于压缩映像,在复制过程中,其还将完成解压缩的工作。

④ version.c。版本信息文件。使用_DATA_和_TIME_宏来表示映像的创建时间,这些信息将在内核启动过程中被显示。

⑤ dataSegPad.c。当使用vxVMI组件时,该文件中的代码确保数据段和代码段使用不同的物理页面,避免共享同一个页面。该文件实现的功能在操作系统运行过程中起作用,在启动过程中不会用到该功能。

⑥ configAll.h。该头文件定义了一系列系统默认组件和系统常量。用户可以打开configAll.h文件查看,即可明白该文件的意义。注意:禁止修改该头文件,用户可以在BSP目录下的config.h文件中对configAll.h文件中的一些默认设置进行修改。

⑦ console.c和usrShell.c。终端交互功能支持文件。

再次提醒注意:all目录下定义的以上这些文件被所有的BSP共享,且每个文件都是不可缺少的,该目录下所有的文件都是由开发环境提供的,无须用户编写,但是在某些条件下,用户可能需要修改这些文件中的某些代码,以显示针对某个特定BSP的某种机制或功能。VxWorks提供了这种修改机制,而同时又不影响其他BSP。如用户需要修改usrConfig.c文件中的代码,此时可从all目录下复制一份usrConfig.c到BSP目录下(如integrator946es),并在BSP的Makefile文件中,添加宏定义语句:BOOTCONFIG=./usrConfig.c,此时Tornado编译环境将使用当前BSP目录下的usrConfig.c文件作为all目录下usrConfig.c文件的替代,即all目录下的usrConfig.c文件将不再被这个BSP使用。当然用户可以在复制过程中修改文件名,如将usrConfig.c改为myUsrConfig.c,则相应的宏定义就为BOOTCONFIG= ./myUsrConfig.c,只要维持BOOTCONFIG宏名称不变,至于指定的文件名称则不做要求,即不一定非要命名为“usrConfig.c”。

对于all目录下的其他文件的修改类似,如对应bootConfig.c文件的BOOTCONFIG宏定义,对应bootInit.c文件的BOOTINIT宏定义。一般而言,只需要对这三个文件进行修改。

除了all目录下的共用文件外,Tornado编译环境还对BSP目录下的文件提出了要求,即对于某些文件包括文件名以及文件中定义的函数都做了要求,这些文件有以下三个。

① romInit.s。

该文件定义romInit函数,该函数是整个系统启动的入口函数,系统上电时,执行的第一行代码就是romInit函数实现的第一条语句。基于处理器的特殊需求,一般在romInit函数实现的开始处放置一个系统异常表。可以参考arm平台下BSP的romInit函数实现。该文件完全使用汇编代码编写,文件实现的功能主要完成平台的初始化(如RAM控制器初始化、屏蔽系统中断等),此后初始化C函数调用环境(主要指栈寄存器的初始化),调用romStart函数。romInit.s文件中一般只定义一个romInit函数,基于romInit函数特殊的执行环境(即在ROM中执行),该函数的代码编写必须始终保持PIC,即位置无关。实现PIC的根本原因请参考本书前文中“深入理解bootrom”章节。该文件被bootrom和ROM型VxWorks内核映像使用。

② sysALib.s。

该文件中定义了sysInit函数,该函数完成的功能类似于romInit,且sysALib.s文件只被下载型VxWorks内核映像使用。此时bootrom完成VxWorks内核映像的下载,所以romInit函数已在bootrom中被执行,故诸如RAM控制器初始化工作无须再在sysInit函数中进行,这应该可以说是sysInit函数与romInit函数实现上的一个区别,且sysInit函数是直接运行在RAM中的,所以其实现上不需要做到PIC。这两点区别可以说是二者的不同之处,实际上可以将romInit函数实现完全复制到sysInit函数实现中,当然要删除RAM控制器初始化的一段代码,对于PIC,则无须关心。

③ sysLib.c。

该文件名称必须定义为sysLib.c。换句话说,Tornado编译环境要求BSP目录下必须有一个文件命名为sysLib.c,且对该文件中定义的函数进一步做出了要求,即该文件必须实现一些具有指定函数名和指定功能的函数。这些函数如下。

● sysBspRev( ) - return the BSP version and revision number:返回BSP版本号和子版本号。

● sysClkConnect( ) - connect a routine to the system clock interrupt:注册系统时钟中断处理函数。

● sysClkDisable( ) - turn off system clock interrupts:禁止系统时钟中断。

● sysClkEnable( ) - turn on system clock interrupts:使能系统时钟中断。

● sysClkInt( ) - handle system clock interrupts (internal):系统时钟中断处理函数。

● sysClkRateGet( ) - get the system clock rate:返回系统时钟中断间隔时间。

● sysClkRateSet( ) - set the system clock rate:设置系统时钟中断间隔时间。

● sysHwInit( ) - initialize the system hardware:外围设备初始化函数。在该函数中必须完成所有外围设备的基本初始化工作,使得设备处于待工作状态。注意:此阶段不可进行中断相关的任何工作,因为VxWorks内核尚未准备好中断相关的内核管理组件。

● sysHwInit2( ) - initialize additional system hardware:所有需要中断配合的外围设备二次初始化函数。该函数中必须完成所有涉及中断的初始化工作。

● sysMemTop( ) - get the address of the top of logical memory:返回VxWorks内核可用内存的最大地址值。

● sysModel( ) - return the model name of the CPU board:返回平台CPU标识符。

● sysNvRamGet( ) - get the contents of non-volatile RAM:获取指定NVRAM地址处的内容。

● sysNvRamSet( ) - write to non-volatile RAM:向指定NVRAM地址处写入内容。

● sysSerialHwInit( ) - initialize the BSP serial devices to a quiescent state:串口设备初始化。该函数在sysHwInit调用期间被调用,要求如同sysHwInit函数。

● sysSerialHwInit2( ) - connect BSP serial device interrupts:串口设备二次初始化。该函数在sysHwInit2函数调用期间被调用,要求如同sysHwInit2函数。

● sysSerialChanGet( ) - get the SIO_CHAN device associated with a serial channel:获取串口通道对应SIO_CHAN结构。

● sysToMonitor( ) - transfer control to the ROM monitor:重新热启动。

除了以上必需的函数外,还有一些函数是可选的,但一旦要在sysLib.c中包含这些函数,函数名和实现功能依然是固定的。这些可选函数如下。

● sysAbortInt( ) - handle the ABORT button interrupt:Abort按键中断处理函数。

sysAuxClkConnect( ) - connect a routine to the auxiliary clock interrupt:辅助时钟中断注册函数。辅助时钟是指区别于系统时钟的另一种时钟,专用于某些特殊情况,一般无须使用。除了系统时钟外,在硬件上必须另有一个对应的时钟定时器对应。

● sysAuxClkDisable( ) - turn off auxiliary clock interrupts、sysAuxClkEnable( ) - turn on auxiliary clock interrupts、sysAuxClkInt( ) - handle auxiliary clock interrupts、sysAuxClkRateGet( ) - get the auxiliary clock rate、sysAuxClkRateSet( ) - set the auxiliary clock rate:函数的意义同系统时钟,不过这些函数是针对辅助时钟的。

● sysPhysMemTop( ) - get the address of the top of physical memory:返回物理内存的最大地址。

除了romInit.s、sysALib.s、sysLib.c三个文件必须按这些名称命名外,还包括其他可选文件,这些文件的文件名并没有固定的要求,但一般都有约定的名称,故也建议用户按约定名称进行命名。这些可选文件如下。

● sysSerial.c:串口驱动相关代码。

● sysScsi.c:SCSI驱动相关代码。

● sysNet.c:局域网LAN驱动相关代码。

以上三个文件中的代码主要在sysHwInit和sysHwInit2函数执行期间被调用。这些文件中的代码通过在sysLib.c文件中包括到内核映像中。例如,针对以上三个文件,可以在sysLib.c文件的某个位置中添加如下语句:

        #include "sysSerial.c"
        #include "ysScsi.c"
        #include "sysNet.c"

用户也可从此处看出为何不对这些文件的命名加入硬性限制。

除了以上文件外,对于BSP,当然还需要特定平台上一些外设的驱动文件,这些文件也包含了BSP目录下,如网口驱动文件可以命名为myEndDriver.c,SPI口驱动文件可命名为mySPIDriver.c,那么此时在sysLib.c文件中加入如下语句,即可将这些驱动代码加入内核映像中。

        #include myEndDriver.c
        #include mySPIDriver.c

除了直接在sysLib.c文件中加入以上include语句外,还可以通过Makefile中MACH_EXTRA宏定义来将某个文件代码包含到内核映像中。如以上的例子中,还可以通过如下方式将myEndDriver.c、mySPIDriver.c文件代码包含到内核映像中。

        MACH_EXTRA=myEndDriver.o mySPIDriver.o

3.4.2 头文件

头文件主要有三个:all/configAll.h、<bspName>/config.h和<bspName>/<bsp>.h,当然一些驱动文件还配有各自的相关寄存器的头文件。

configAll.h文件是Tornado开发环境提供的,禁止对其进行修改。这个头文件定义内核构成的所有默认选项和系统常量。如果需要修改一些默认选项,则通过config.h文件进行修改。<bsp>.h文件则是针对特定平台寄存器地址和结构的相关定义。configAll.h和<bsp>.h文件都被config.h文件使用:configAll.h文件被config.h包含在最开始处,这一点是必需的,因为只有如此,才能通过config.h文件的后续定义改变某些选项的定义,<bsp>.h文件一般被config.h文件包含在最尾处。

上述三个头文件中,configAll.h文件被禁止修改,<bsp>.h文件与平台相关,只有config.h文件具有操作的灵活性。config.h文件必须包括以下功能或者定义。

① BSP版本号以及子版本ID号。

可以使用BSP_VERSION宏定义BSP版本号,如下所示。

        #define BSP_VERSION “1.2”

子版本号通过BSP_REV宏进行定义,如下所示。

        #define BSP_REV “/0”

注意

子版本号定义中包括一个反斜杠,因为最后的发行号(release number)是版本号和子版本号的字符串连接,所以必须加反斜杠隔离。前文中我们讨论到sysLib.c文件中必须定义的函数时,其中之一就是sysBspRev函数,该函数即返回BSP的发行号。其实现如下。

                  char * sysBspRev (void)
                        {
                        return (BSP_VERSION BSP_REV);
                        }

根据以上定义,其返回“1.2/0”字符串,这正是我们想要的结果。

注意

BSP版本号和子版本号必须位于config.h文件的最开始处,在包含configAll.h文件之前,因为configAll.h中某些组件行为可以依赖于版本号。

② configAll.h文件。

configAll.h文件定义内核所需的一系列默认组件,特定BSP所属的config.h文件必须以此为基础构建VxWorks内核,故包含configAll.h文件是必需的,而且应该放在config.h文件的开始处,紧接着,版本号定义之后,因为我们需要对一些默认行为进行重新定义,故必须将组建功能的修改宏定义放在configAll.h文件之后。

③ 内存cache和MMU策略(即是否使能系统cache以及是否使能MMU)。

此处所指内存cache策略是整个系统的cache策略,是由CPU相关寄存器对所有的cache的一种全局控制。我们知道,MMU使能后具有面向页面的cache策略控制,但是这个控制必须是在全局cache使能的情况下,如果全局cache不使能,那么无论MMU页表项中的属性为何,都无法达到cache的目的。内存cache策略对指令和数据分别进行控制,由USER_I_CACHE_MODE、USER_D_CACHE_MODE进行控制,如下所示。

        #undef  USER_I_CACHE_MODE
        #define USER_I_CACHE_MODE       CACHE_WRITETHROUGH
        #undef  USER_D_CACHE_MODE
        #define USER_D_CACHE_MODE       CACHE_COPYBACK

由于configAll.h文件中已经定义了默认的cache行为,故此处为了修改这个默认的行为,首先必须取消默认行为(undef语句),此后重新定义cache行为(define语句),这是config.h文件对configAll.h文件中默认行为进行修改的通用方式。

MMU机制的控制通过INCLUDE_MMU_FULL和INCLUDE_MMU_BASIC两个宏进行控制。值得注意的是,不同版本的VxWorks内核用以控制相关行为的宏名称并不相同。这一点在开发BSP时特别要注意,要弄清楚BSP移植所基于的VxWorks内核版本。

④ 平台RAM基地址和大小。

涉及平台RAM的宏定义如下。

● LOCAL_MEM_LOCAL_ADRS:平台RAM基地址。

● LOCAL_MEM_SIZE:平台RAM总大小。

● USER_RESERVED_MEM:在RAM顶部用户预留的内存大小,这部分内存将排除在VxWorks内核的管理之外,即VxWorks内核将“看不到”这部分内存空间。

● RAM_HIGH_ADRS:bootrom压缩代码复制到RAM中的目的地址。当为非压缩形式时,bootrom映像所有的代码将复制到RAM_HIGH_ADRS指定的地址。

● RAM_LOW_ADRS:VxWorks压缩代码复制到RAM中的目的地址。当为非压缩形式时,VxWorks映像的所有代码(包括romInit、romStart函数)都将被复制到RAM_LOW_ADRS指定的RAM地址处。

注意

有关RAM_HIGH_ADRS和RAM_LOW_ADRS的具体使用,请参考本书前文中“映像类型”章节的说明,此处的叙述不甚准确。

另外一个宏用以支持RAM容量的动态改变,我们一般不使用这种工作方式,这个宏为LOCAL_MEM_AUTOSIZE。感兴趣的用户可以参考文献“VxWorks bsp programmer’s guide”。

⑤ 平台ROM基地址和大小。

当采取bootrom + VxWorks下载启动方式时,bootrom将被烧录到ROM中;或者采用ROM型VxWorks内核直接启动方式时,VxWorks内核映像本身(一般为压缩版本)将被直接烧录到ROM中。可以说,ROM是系统上电后跳转的目的地址,其中存储着上电后运行的第一条指令。基本上所有的平台都必须存在某种形式的ROM存储介质。ROM是“Read Only Memory”,即只读存储器的简称,但是现今平台上几乎都在使用Flash替代ROM,一方面由于Flash的存储容量大,另一方面,成本也比较低。当然Flash从工作方式上主要分为两大类:Nor Flash和Nand Flash。为了能在其中在线执行EIP(Execute In Place),都是用Nor Flash作为启动介质(虽然现在有号称直接从Nand Flash启动,但是都必须借助中间bootloader代码,并非完全意义上的EIP,事实上,Nand Flash不可能达到真正意义上的EIP)。Nor Flash支持重新擦除后编程,编程次数可达10万次。故使用Nor Flash作为启动介质较为普遍,反而真正意义上的ROM基本上已经退出开发阶段,可能在产品发布时,为了进一步降低成本,会使用ROM。虽然使用的是Flash,但是在定义上还是被看做是ROM,涉及相关的宏如下。

● ROM_BASE_ADRS:ROM基地址。

● ROM_TEXT_ADRS:存放启动代码的首地址。一般ROM_TEXT_ADRS会相对ROM_BASE_ADRS做一个偏移,以存放一些参数(如Bootline)。但是很多平台直接将ROM_TEXT_ADRS定义为ROM_BASE_ADRS的值。

● ROM_SIZE:ROM大小。

● ROM_COPY_SIZE:当代码非压缩时,所有的代码将被一次性复制到RAM中,ROM_COPY_SIZE即指定复制代码的大小。一般将这个值直接设置为ROM_SIZE,虽然在复制时会多做一些无用功,但是较为方便,而且对于复制代码的大小会随着代码的改变而改变,经常性修改这个参数也比较麻烦,而且一旦忘记时,如果实际代码的大小大于此处定义的副本大小时,还会出一些异常的错误,故还是建议用户将其直接设置为ROM_SIZE。

如下给出了以上宏定义的简单示例。

        #define ROM_BASE_ADRS     0x02000000     /* base of Flash/EPROM */
        #define ROM_TEXT_ADRS     ROM_BASE_ADRS  /* code start addr in ROM */
        #define ROM_SIZE             0x00200000     /* size of ROM holding VxWorks*/
        #define ROM_COPY_SIZE      ROM_SIZE

⑥ 非易失性RAM(NVRAM)大小。NVRAM一般容量较小或者直接从存储启动代码的Flash中预留一段空间,用以存储诸如Bootline之类的参数。VxWorks启动过程中,有一个倒计时的过程,在这个过程中,用户如按下键盘上任何一个按键,就会进入bootline修改模式,用户可以动态地修改bootline的参数值,如可以修改启动方式,在下载启动中,可以修改下载文件名、主机IP、目标机IP等。修改后的参数一般被写入NVRAM中,这样就可以保存本次修改,而当下次启动时,将使用修改后的参数进行启动。涉及NVRAM的相关宏如下。

● NV_RAM_SIZE:NVRAM大小。如果平台不包括NVRAM,则将这个宏定义为NONE。

● BOOT_LINE_SIZE:NVRAM中预留给Bootline参数的存储空间,这个预留值不可以大于NVRAM本身的大小NV_RAM_SIZE。这个参数在configAll.h中的默认值被设置为255B。

● NV_BOOT_OFFSET:这个常量定义了Bootline参数存储在NVRAM中相对于NVRAM基地址的偏移量。这个参数将被sysNvRamGet和sysNvRamSet函数使用用以获取和修改Bootline参数。

注意

以上并没有表示NVRAM基地址的宏。因为实际的平台上基本没有单独使用一片存储介质去存储参数,大多是从启动代码存储介质中(如使用较多的Nor Flash中)预留一段空间供Bootline参数使用,故并没有一个内核特定常量来表示NVRAM基地址,这个基地址完全由用户决定,用户可以定义一个NV_RAM_ADRS常量来表示NVRAM的基地址,这个基地址和NV_BOOT_OFFSET以及BOOT_LINE_SIZE将被sysNvRamGet和sysNvRamSet两个函数使用。

⑦ 默认Bootline参数定义。

Bootline定义了VxWorks启动过程中的一些参数,如目标板的IP地址。如果使用下载启动方式,则定义了下载源、下载文件名等。当然,在Bootline中还可以定义一些平台特定参数,用户可以在bootConfig.c或者usrConfig.c文件中对Bootline中自定义的参数进行解析,用以决定启动过程中的某些自定义行为。内核提供了bootStringToStruct函数将Bootline以特定格式进行解析并返回解析后的数据结构,这个结构中的字段将决定内核启动行为。

一个实际应用中的BSP Bootline定义如下所示。

        #define  DEFAULT_BOOT_LINE       "atemac(0,0)  vxw:VxWorks  h=192.168.1.6  e=192.168.
    1.254:ffffff00 g=192.168.1.1 u=www pw=www tn=AT91RM9200 o=00:00:0a:0b:0d:00"

其中定义了启动方式是通过EMAC网口启动,VxWorks内核映像名为VxWorks,映像所在主机IP地址为192.168.1.6,要求目标机IP地址设置为192.168.1.254,子网掩码设置为255.255.255.0,网关IP地址为192.168.1.1,用户名和密码都是www,要求目标机网卡MAC地址设置为00:00:0a:0b:0d:00。

⑧ 其他对默认组件的宏定义以修改configAll.h文件中定义的默认选项。

默认行为的修改由两条语句完成:undef和define。undef取消组件默认行为,define重新定义组件行为。

⑨ bspname.h文件,即特定平台外设寄存器结构和地址定义、外设中断号分配等平台特定常量定义。

3.4.3 Makefile文件

BSP目录下的Makefile文件决定了VxWorks和Bootrom的映像类型以及对一些参数的定义,这个Makefile是一个上层封装文件,其底层将调用Tornado开发环境提供的Makefile文件,这些文件存在于h/make目录下,主要有两个:rules.bsp和defs.bsp。rules.bsp文件定义了针对各种不同映像类型的编译规则,以及BSP中模块的编译规则;defs.bsp文件定义了控制编译行为的一些标志位和常量的定义。h/make目录下其他一些文件定义了针对不同特定平台的编译时参数和标志位。如下给出了一个实际的BSP的Makefile文件,这个BSP已经完成移植且运行稳定。

        CPU = ARMARCH5
        TOOL = gnu
        EXTRA_DEFINE = -Wcomment -DCPU_926E \
                -DARMMMU=ARMMMU_926E -DARMCACHE=ARMCACHE_926E
        TGT_DIR = $(WIND_BASE)/target
        include $(TGT_DIR)/h/make/defs.bsp
        include $(TGT_DIR)/h/make/make.$(CPU)$(TOOL)
        include $(TGT_DIR)/h/make/defs.$(WIND_HOST_TYPE)
        ## Only redefine make definitions below this point, or your definitions will
        ## be overwritten by the makefile stubs above.
        TARGET_DIR= arm926ejs_bsp
        VENDOR= HFei
        BOARD= seed dm6446
        MACH_EXTRA = Dm644x.o
        #BOOT_EXTRA=
        RELEASE+=  bootrom.bin
        #
        # The constants ROM_TEXT_ADRS, ROM_SIZE, and RAM_HIGH_ADRS are defined
        # in config.h and Makefile.
        # All definitions for these constants must be identical.
        #
        ROM_TEXT_ADRS= 0x02000000 # ROM entry address
        ROM_SIZE = 0x00200000 # 16M number of bytes of ROM space
        RAM_LOW_ADRS= 0x80004000 # 32M RAM text/data address
        RAM_HIGH_ADRS= 0x86000000 # RAM text/data address
        VMA_START     = 0x$(ROM_TEXT_ADRS)
        # Binary version of VxWorks ROM images, suitable for programming
        # into Flash using tools provided by ARM.  If other ROM images need to
        # be put into Flash, add similar rules here.
        bootrom.bin: bootrom
            - @ $(RM) $@
            $(EXTRACT_BIN) -O binary bootrom $@
        bootrom_res.bin: bootrom_res
            - @ $(RM) $@
            $(EXTRACT_BIN) -O binary bootrom_res $@
        bootrom_uncmp.bin: bootrom_uncmp
              - @ $(RM) $@
              $(EXTRACT_BIN) -O binary bootrom_uncmp $@
        VxWorks_rom.bin: VxWorks_rom
            - @ $(RM) $@
            $(EXTRACT_BIN) -O binary VxWorks_rom $@
        VxWorks.st_rom.bin: VxWorks.st_rom
            - @ $(RM) $@
            $(EXTRACT_BIN) -O binary VxWorks.st_rom $@
        VxWorks.res_rom.bin: VxWorks.res_rom
            - @ $(RM) $@
            $(EXTRACT_BIN) -O binary VxWorks.res_rom $@
        VxWorks.res_rom_nosym.bin: VxWorks.res_rom_nosym
            - @ $(RM) $@
            $(EXTRACT_BIN) -O binary VxWorks.res_rom_nosym $@
        ## Only redefine make definitions above this point, or the expansion of
        ## makefile target dependencies may be incorrect.
        include $(TGT_DIR)/h/make/rules.bsp
        include $(TGT_DIR)/h/make/rules.$(WIND_HOST_TYPE)

Makefile文件中必须定义如下宏。

● CPU:平台CPU架构,如上定义为ARMARCH5,即ARM V5。

● TOOL:主机编译工具链。

● TARGET_DIR:BSP目录名。

● VENDOR:生产商。

● BOARD:平台代号。

● ROM_TEXT_ADRS:启动代码存储介质基地址。

● ROM_WARM_ADRS:热启动基地址,这个地址相对于ROM_TEXT_ADRS将存在一个小的偏移。热启动时将保留当前RAM中的所有内容。

● ROM_SIZE:ROM容量。

● RAM_LOW_ADRS、RAM_HIGH_ADRS:RAM_LOW_ADRS和RAM_HIGH_ADRS两个常量定义启动过程中,从ROM向RAM复制时的RAM目的地址,具体含义参考本书前文中的“映像类型”章节。

注意

Makefile文件中定义的一些常量如ROM_TEXT_ADRS、ROM_SIZE、RAM_LOW_ADRS、RAM_HIGH_ADRS在config.h文件中也有相同的常量定义,两个文件中对于这些常量必须定义为相同的值,这一点非常重要。某些用户可能认为只需在一个文件中进行定义即可,两个文件中进行定义岂不是重复?事实上并非如此,两个文件中定义的宏被不同的部分使用,config.h文件中的宏定义被内核组件使用控制内核的某些行为或者初始化内核的某些变量,而Makefile中的定义则控制编译过程,如链接地址。所以对于以上重复的常量定义并非有意重复,而是使用在不同的地方,由于最后在运行时都要汇集在一起,所以两个文件中相同的常量必须保证相同的值。

3.4.4 扩展文件

扩展文件主要存在于BSP目录下,如果使用Tornado开发环境,则存在于工程目录default子目录下。扩展文件主要是在编译过程中生成的一些中间目标文件(如bootInit.o之类)、动态创建的文件(如符号表文件symTbl.c),以及最终编译得到的链接文件,如bootrom、VxWorks映像。用户一般不用关心具体的扩展文件,本书前文“深入理解bootrom”一节较为详细地介绍了bootrom的生成过程,用户可以借此对这些文件进行理解,感兴趣的用户也可以参见文献“VxWorks bsp developer’s guide”2.2.2节的内容了解扩展文件方面的内容,此处不再讨论。

3.4.5 说明文件

说明文件位于BSP目录下,对一个BSP的相关信息进行介绍,主要有两个文件:README和target.nr。其中README文件包含BSP的发行记录、每次发行的版本号;target.nr文件包含运行VxWorks内核映像的平台特定信息,这些信息包括:平台名称、平台简要介绍、平台支持的功能、平台可用硬件资源、平台布局(如跳线器等信息)、参考资源信息等。

说明文件在将一个BSP作为产品发布时是必要的。然而,大多数情况下,底层开发人员开发某个平台的BSP,只是作为平台上层应用软件开发的操作系统基础,在产品进行发布时,一般只发布应用层软件和平台本身,底层操作系统包括BSP作为二进制代码固化在平台硬件中(通常为Flash),不作为产品进行发布。BSP只是作为公司内部资料对相关开发人员开放,故对于说明文件的格式,在官方(Wind River公司)没有约定的情况下,各开发公司的要求各异,此处只做简单说明。