Chinaunix首页 | 论坛 | 博客
  • 博客访问: 588785
  • 博文数量: 169
  • 博客积分: 2656
  • 博客等级: 少校
  • 技术积分: 1685
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 13:03
文章分类

全部博文(169)

文章存档

2011年(1)

2010年(135)

2009年(33)

我的朋友

分类: 嵌入式

2010-10-19 12:44:01

这个项目在历经一年的时间总算是要结束了.这一年没有白做,算是学了点东西.现在我就把这一年工作所积累的一些653的细节和调试技巧来个简要总结.
首先,听说过vxWorks的大有人在,但知道vxWorks 653的恐怕不多。简单的说vxWorks 653是风河公司开发的针对关键性安全应用的嵌入式操作系统平台,平台集成了653内核,workbenchice等各种软硬组件。目前大的客户有波音的飞机和GE的医疗设备。

vxWorks 653
其实是一个双层的操作系统,和vmware有点类似,只是上下层都是基于vxworks,下层是从vxworks AE移植过来的,而上层基于vxworks 5.5.
vxworks AE
vxworks5.5移植过来,在5.5的基础上增加了分页机制和保护域等实现,而且代码经过验证。但是AE也存在松耦合特性,针对每个模块都需要一个AE系统,软硬件代价比较大,于是653诞生了,一套主系统之上支持若干个子操作系统,每个系统负责一个模块,各子系统之间互相隔离,一个子系统崩溃也不会干扰到整个主系统和其他子系统。子系统之间通过port通信。主子系统之间通过系统调用,事件和伪中断通信。风河美国的几个牛人研发了这套系统,但是好像这几个牛人都闪了,剩下我们这些小兵还在修修补补。

目前653只支持ppc, 现在要把vxworksx86 arch相关的代码移植到653中。关于arch的移植,基本上对c代码的改动相对较少,主要是bsp和内核中汇编的改动。这包括像调度器,任务管理,信号量,中断处理,系统调用等等用到汇编的地方都需要参照ppc的相关代码进行修改。
整个移植分为三大步,首先是对bootapp进行移植,其实它相当于一个简化版的vxworks5.5,开机后bios加载bootsect0x7c00bootsect会识别fat文件系统中的第一个文件,这个文件必须是连续的簇,这个文件叫bootrom.sys,其实就是bootapp的二进制版本,bootsectbootrom.sys载入内存的0x80000位置,然后跳到0x80000执行,bootapprom_compressed,rom_copy,rom_resident三种启动方式,和vxworks一样,以rom_copy为例,bootapp会将自己的代码段数据段拷贝到RAM_HIGH地址,RAM_HIGH我们设定为0x800000.这样在拷贝之前其实代码如果要访问数据段需要对数据段的位置进行重定位后再访问,而代码段也不允许绝对跳转,要么就得重定位。在拷贝完毕后再跳转到RAM_HIGH的位置,从RAM_HIGH开始进行系统硬件的初始化。在硬件初始化完毕后会调用kernelInit手动创建一个任务。其实就是将当前的初始化流程规范到一个任务中执行,之后在这个跟任务中会调用一些信号量,驱动,中断钩子等的软件初始化,最后打开中断,这样调度机制发挥作用,然后整个系统运转起来,创建一些核心任务像异常任务,工作者线程等。最后启动loader任务,此任务负责建立tcp连接,并加载653镜像。
653
镜像有两种,第一种包括coreOS,ssl1...sslm,partition1...partitionn,boot.txt,configrecord, sdRgn1...sdRgnp.
第二种是sms_ramPayload,其实就是将coreOS,ssl,partitionconfigrecord的二进制版本合为一体并在前面增加一个小的引导器。这样使653的主系统和子系统支持软件级别的重启动。configrecord记录coreOS,ssl,partition的各个段的虚实地址,访问属性,调度策略,端口信息等等。

以第一种方式为例,我们只分析最简单的情况,即coreos上只有一个partition, 一个ssl, 而且不印射任何共享内存。bootapp在加载完镜像后跳到0x108000位置,这是coreos的默认加载位置。coreos的初始化类似于bootapp,只是在开启第一个任务后进行了分页机制,虚拟页物理页管理器和partition系统的初始化,这包括为每个partition分配虚实地址范围,印射共享内存等。
coreos
运转后会调度partition,在coreos看来每个partition就是它的一个任务,但在partition内部,又会进行类似于bootappcoreos的初始化,最后开启子任务,coreos收到的中断在自身处理完后会以伪中断的方式传给partition,即在coreos中断处理程序退出时直接返回到partition的伪中断处理程序,而伪中断处理程序退出时返回到被中断的子任务。当每个partition时间片用完后会保存其上下文,调度下一个partition,其中浮点上下文采用lazy-save方式。如果ready队列空闲时进入idle状态,即不断的在一个0级栈上调用reschedule,直到有partition被换醒。partition的子任务调度稍微复杂,在伪中断的处理程序中检索到当前子任务时间片用完后以系统调用的方式提交切换申请和idle状态申请。另外当一个partition空闲时可以调度另一个partition来运行,这是可配的。
关于调试,我们用的是arium公司出的ECM-XDP3,对应主机软件为sourcepoint,这是专门针对x86处理器的硬件调试器,其功能超级强大,可以从开机第一条指令一直调到任务结束运行,没有它这个项目无法完成。关于这个调试器倒是有不少技巧。首先要在软件中设定重启后停止运行,否则重启后一直运行且断点失效。能用软断点的地方尽量用软断点,因为硬断点只能设4个。在存在代码段覆盖的地方软断点会失效,此时只能用硬断点。如果被调代码中会设定调试寄存器的话会干扰sourcepoint,因为sourcepoint也使用相同的调试寄存器。有时会莫名的进入smm状态,这时不用管,可以直接run出去。有时会弹出对话框说TF标记被清,sourcepoint无法正常使用,此时有个补救办法,就是将软断点对应位置的指令恢复,然后继续运行,因为那个位置被sourcepoint强制写了一个0xf1进去。这是多任务环境中单步过程中触发中断,而中断处理中又被软中断断下来导致的。系统崩溃通常是由异常造成的,这时在异常处理程序上设断点,从堆栈中可以看到发生异常的代码位置,然后可以进一步定位根源所在。堆栈框架也是一个不错的选择,可以修改中断处理那块的指令使其直接返回,然后看堆栈调用的框架。另外看trace也可提供一些信息,trace功能可以查看之前被执行的若干汇编指令。另外这个调试器对浮点寄存器的显示好像有问题,各个st寄存器都不正确,而且根据ftags的值来看,它是以fxsave的方式来取浮点的上下文的。

好了,就此打住,再写就又成流水账了。

 

阅读(2055) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~