加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSSRSS-巴斯仪表网
您当前的位置:首页 > 电子发烧 > 单片机学习

基于VxWorks的bootrom代码改进

时间:2013-09-03  来源:123485.com  作者:9stone

1 问题的提出
    VxWorks是WindRiver公司开发的一种嵌入式操作系统,具有强大的功能和友好的用户界面。VxWorks软件应用非常广泛, 不仅应用在网络设备、家用电器当中,而且还应用在航天、导弹等高端领域。在网络设备应用领域中,通常利用VxWorks来开发bootrom代码、BSP (Board Support Packet)代码以及上层的网络协议代码。
    通常,Bootrom软件有以下功能:

  1. 通过串口下载操作系统映像;
  2. 通过串口升级自身映像;
  3. 通过串口下载系统配置文件、系统信息文件;
  4.  加载操作系统映像,使其正常启动;
  5. 其它的辅助功能,如地址内容查看功能、地址内容修改功能和bootrom菜单显示信息控制的功能等。

    对于通常的bootrom代码编译,大多数用户选择使用GNU make的DOS命令来进行。因为如果bootrom不提供网口功能的话, 单纯的CPU驱动部分代码量是不大的;但如果提供网口功能的话,代码量相对较大,文件之间的内在关系比较复杂,因此,系统使用GNU make的DOS命令来编译生成bootrom就显得有点麻烦。Makefile文件主要是由“目标”(target)、“依赖性”(dependencies)和“动作” 组成的一系列规则, 而VxWorks提供的GNU make工具就是根据Makefile指定的规则来编译和链接程序的。Makefile基本结构虽然简单,但正确、灵活地运用这些规则并不是那么轻松的事情。即使根据GNU Makefile规则书写出适当的Makefile文件,但随着代码的改变,Makefile还需要经常修改,这就增加了BSP开发人员的负担。而且,对于交换产品而言,其成本控制是非常严格的。对于存放boot rom软件的Flash来说,通常要求大小为512KB,这样就需要考虑到容量的限制。
    因此,必须使用新的方法来简化bootrom代码编译,而且要在保证提供网口功能的情况下,系统提供的bootrom软件小于512KB。

2 实现方法
2.1 通过建立工程生成bootrom映像
    采用建立工程的方式可以有效地解决这个问题。首先依据bootrom中的BSP代码来新建一个工程,然后将网口驱动代码加入到建好的工程中。这样就可以通过编译工程实现带有网口下载功能的bootrom软件。但对于VxWorks嵌入式系统而言,它有自己一套规范,要求bootrom软件在加电后必须从romInit()函数开始运行,而建立工程所得的入口函数为sysInit()。因此需要增加一个系统壳代码,这个壳代码所要完成的任务就是加载bootrom工程的映像,并从romlnit()开始执行bootrom代码。通过建立工程来调试bootrom代码有以下优点。
(1)责任分明
    开发产品是一个复杂的工程,需要多人合作完成。对于CPU子系统和网口驱动系统这两块内容来说,更需要责任明确。通过建立工程来调试代码,可以准确地定位错误文件和函数的位置。是BSP代码出现问题,还是网口驱动代码出现问题,可以一目了然,做到责任明确。
(2)提高效率
    通过建立工程可以节省书写Makefile文件时间,并可以让VxWorks软件的友好图形界面这一优点得到更好的体现。另外,建立工程也可以减少文件编译排错的难度,方便工程文件的调试以及功能的验证,从而大大提高工作效率,加快工作进度。

2.2 编写壳代码并实现加载
    建立工程生成映像文件的入口函数为sysInit(),而VxWorks规范中要求系统加电后要从romInit()函数开始运行。因此,需要设计一个方案来加载编译工程得到的映像,而且要具备初始化CPU和SDRAM 存储空间的功能。
    首先,系统从romInit()函数中开始运行,完成CPU和SDRAM 初始化,跳转到函数romStart()运行。然后,加载第二份bootrom代码到系统的低地址处,运行壳代码中的sysInit()函数, 并调用自己构造的解压函数usrInit(),将压缩后的工程映像文件解压缩到系统高地址处,之后系统继续运行解压后的bootrom代码。此时,系统开始运行sysInit()函数,调用VxWorks系统中的usrInit()函数,开始初始化系统硬件、内核以及其它外围设备。壳函数usrInit()代码如下:

代码
  1. void usrInit(void){   
  2. volatile FUNCPTR absEntry;   
  3. if(inflate((UCHAR*)ROM_OFFSET(_binArrayStart),   
  4. (UCHAR *)(RAM_LOW_ADRS),&_binArrayEnd-binArrayStart)!=OK)   
  5.   return;   
  6. absEntry=(FUNCPTR)(RAM_LOW_ADRS);   
  7. (absEntry)();   
  8. }  

    其中RAM_LOW_ADRS为系统低地址,是操作系统运行的起始地址,但bootrom 可以利用低地址来实现在系统高地址的运行。宏ROM_OFFSET用于准确定位函数地址,因为在bootrom 中运行的代码要求以相对地址方式来寻址,而不能以绝对地址方式寻址。
    _binArrayStart 为压缩后二进制代码的开始符,_binArrayEnd为压缩后二进制代码的结束符。Inflate()是VxWorks软件的解压缩函数,用于解压缩由deflate()压缩函数压缩的二进制文件映像。同时, 需要将下述代码添加到编译规则文件rules.vxWorks中的相应部分:
$(CC)-c$(CFLAGS)$(BSP_DIR)/unzip.c-o$(BSP_DIR)/unzip.o
$(LD)$(LDFLAGS)-e sysInit -Ttext $(RAM_LOW_ADRS) /-o
unzip_obj.o sysALib.o$(BSP_DIR)/unzip.o$(LIBS)flex.z.o
    其中,unzip.c中包含构造的壳函数usrInit()。SysInit()为解压软件的入口函数。上述语句的功能:第一行完成壳文件的编译, 第二、三行完成壳目标代码与第二份bootrom代码的链接。这样, 一个具有解压功能的壳函数就被链接到第二份bootrom映像中了。图1、图2是修改前的系统运行方式与修改后的系统运行方式比较。
 
 
    通过这两种方式的比较可以看出, 修改前系统运行方式与修改后的运行方式有下面两点差异:

  1.  第一份bootrom启动后, 前者存在解压缩自身映像的操作, 而后者没有;
  2. 对于第二份bootrom,前者没有壳代码,而后者有。

2.3 缩减文件长度
    通常第一份bootrom代码只有两个文件, 一个是包含CPU和SDRAM初始化文件romInit.s, 另外就是包含romStart()函数的bootInit.c文件。另外,根据需要还可以添加提供串口轮询显示功能的文件。对于第一份bootrom代码,通常只有10KB左右(这是针对系统修改后的方式), 而对于包含壳函数代码的,通过建立工程并编译而生成的第二份bootrom比较大,通常为570KB左右。(注意:这几个数值是通过特定的产品来得出的结论,并不应用于所有产品,但遇到类似的情况可以借鉴处理。)而其后面的一部分完全是0,可以考虑去掉这些0,但不能影响软件的功能。经过测试得出结论:去掉后面的0对系统功能和性能没有任何影响。通过文件的操作来实现两份bootrom合并,合并后的大小要求小于或等于512KB。如果不采用任何措施,直接将两个文件合并起来要在580KB左右, 大于512KB,这是很多系统不能满足的。第二份bootrom映像的后面部分的内容类似表1所列的信息。

表1 bootrom映像部分二进制内容
000 210h EB E2 BD 95 BD 15 87 AE 3C 74 FD 5C 5F 6A FD 8B
000 220h D6 BD 3A EB FF 6F CF 2A D2 69 95 E9 34 AF E7 EF
000 230h 86 94 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000 240h 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000 250h 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

    从表1可以看出,在地址0x00078233处就是0值了。这样可以通过对文件内容的操作将0x00078240后面的内容全部剔除,从而可将合并后的bootrom代码控制在512KB以内。当然,我们通常会选择一个整数值进行操作,即将0x00078240后的所有值去掉即可。这样处理,可以减少维护和开发的工作量。如果按照以往的做法,bootrom软件对外将有第一份和第二份的区别,无论是生产、上层软件调试还是开发, 都需要分别对待,这样维护量和开发量将会加大。而经过修改后,可以把区别只控制在开发阶段,在线升级时,可以按照一个软件来通过串口或网口来进行升级。通过对bootrom最后生成文件大小的控制,可以简化生产流程,加快生产进度。

3 小结
    在嵌入式操作系统中进行程序开发,需要经常开辟新的思路, 以一些简单的实现方式代替复杂易错的方式。在本次产品开发过程中,将bootrom映像生成方式由惯用的GNU make命令行实现,修改为按照新建工程的方式来实现,是一个相对好的方法,对整个产品的后续批量生产、用户维护和后续开发都奠定了一个良好的基础。


分享到:
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
栏目导航->单片机学习
  • 电子应用基础
  • 电源技术
  • 无线传输技术
  • 信号处理
  • PCB设计
  • EDA技术
  • 单片机学习
  • 电子工具设备
  • 技术文章
  • 精彩拆解欣赏
  • 推荐资讯
    使用普通运放的仪表放大器
    使用普通运放的仪表放
    3V与5V混合系统中逻辑器接口问题
    3V与5V混合系统中逻辑
    数字PID控制及其改进算法的应用
    数字PID控制及其改进
    恶劣环境下的高性价比AD信号处理数据采集系统
    恶劣环境下的高性价比
    栏目更新
    栏目热门