嵌入式VxWorks学习总结报告 控制端PC 机Socket APISocket API受控端命令接收任务普通命令命令接收缓冲队列命令发送任务紧急命令紧急命令命令发送缓冲队列命令解释任务图5-3 基于缓冲队列的通信模式
控制端接收试验单元的操作信息,将其转换为受控端额可以理解的命令格式,通过Socket接口传到受控端,然后等待返回信息;受控端通过Socket接口由信息接收任务接收命令,将其添加到信息接收缓冲队列,信息解释任务从信息接收缓冲队列取出信息,根据具体情况执行特定的软硬件操作,操作结束后将执行结果添加到信息发送缓冲队列,信息发送任务从信息发送缓冲队列取出信息,通过Socket接口将其返回给控制端。
信息接收缓冲队列的主要作用是缓存从控制端发下来的命令,保证所有的命令得到尽快的接收,避免由于接受速度慢造成控制端网络发送模块的阻塞,从而给控制端的软件带来不必要的麻烦。
信息发送缓冲队列则是将所有需要发送的命令缓存再发送,这样分离了网络发送和可能的硬件中断,在控制端软件接收模块阻塞而导致网络阻塞的情况下,不会影响中断处理的速度或者网络通断的监测。
3.1.4 命令通道与任务优先级
网络连接建立以后,服务器端与客户端之间就可以互相发送消息了。如果使用socket通信,则用户不需要关心TCP/IP层以下的协议,编程使用的recv()和send()操作的信息流就是字符串。为了通信双方可以互相理解对方传递过来的字符串,必须事先建立通信协议。规定特定位置上字符所表示的含
33
… ...… ...命令执行1命令执行2普通命令命令执行m…
嵌入式VxWorks学习总结报告 义,以保证下传命令和返回信息能够得到正确的接收和解释。VxWorks主机与目标机之间的通信主要以命令和数据为主,其中大多是命令形式,命令传输的通道就是命令通道。
VxWorks端的命令通道的建立,是通过对命令的不同处理而建立相应的任务来完成的,主要有命令接收、处理和发送任务。如果需要服务器保持随时准备好通信,一般还需要加上网络监控的部分。所以得到的VxWorks端得命令通道的软件整体结构可参考如下:
网络初始化各任务发起网络监测命令接收命令处理命令发送网络出错通知各任务删除 多任务中的各个任务执行时,要遵照任务调度机制。信号量可以用来实现各个同等级任务对系统资源的占有,而任务优先级的划分就是不同等级优先级的任务执行顺序的安排。
在实际的优先级划分中,为了保证所有的信息被尽快的从套接字通道取出,在多个任务并行运行的时候,应当优先考虑信息接收任务,由于采用缓冲队列,信息发送任务可以在别的任务不执行的情况下再执行。一般情况下,用户优先级不小于50。如果用户程序的优先级过高,超过了系统任务的优先级,可能会影响系统的运行。为了调试方便,一般由程序发起的任务优先级应当低于Shell下sp发起的任务的优先级,以保证Shell的优先相应。所以,可将用户任务优先级设定为低于100。
根据任务划分优先级的先后次序,可参考划分:初始化任务主要是其他各任务的发起,优先级设置最高为110;网络检测任务优先级设置在其他各任务之上112;为了保证所有信息被尽快的套节字通道取出,应该优先考虑信息接收任务,设置优先级为114;信息解析任务和信息发送任务优先级分别设置为116和118。
3.1.5 双网卡通信
在主机与目标机的交叉调试开发中,我们总是要进行一些网络调试与测试操作。因此,目标机一般会与主机相连接的同时,也会有自己独自接入到另一个局域网的情况。此时,就需要对目标机上增加一块网卡,以期满足此种情况,也就出现了VxWorks开发中的双网卡(乃至多网卡,原理与双网卡类似)配置。
下面我们假设在pentium目标机上有3张网卡,2张intel 82559, 1张3Com
34
嵌入式VxWorks学习总结报告 3C905。
1 修改bsp的config.h(Tornado2.2下)文件,应该有下列定义: #define INCLUDE_FEI_END #define INCLUDE_EL_3C90X_END 其它网口应该都是 #undef 的。
2 修改bsp的configNet.h的END_TBL_ENTRY endDevTbl结构体,其中应该有:
#ifdef INCLUDE_EL_3C90X_END {0,
EL_3C90X_LOAD_FUNC,
EL_3C90X_LOAD_STR,
EL_3C90X_BUFF_LOAN, NULL, FALSE},
#endif /* INCLUDE_EL_3C90X_END */
#ifdef INCLUDE_FEI_END {0,
FEI82557_LOAD_FUNC,
FEI82557_LOAD_STRING,
FEI82557_BUFF_LOAN, NULL, FALSE},
{1,
FEI82557_LOAD_FUNC,
FEI82557_LOAD_STRING,
FEI82557_BUFF_LOAN, NULL, FALSE},
#endif /* INCLUDE_FEI_END */
3 完成上述修改后,重新制作bootrom。在引导vxworks之前,就可以指定从某个网口来加载vxworks。比如,可以是elPci(0,0),fei(0,0)或fei(1,0),分别对应3Com 3C905,第一张intel 82559和第二张intel 82559。
4 在tornado中创建vxworks的工程,设置IP_MAX_UNITS,使其大于等于3。
vxworks启动完毕后,可以在usrAppInit中,以如下的方式来启动和配置每个网卡:
ipAttach(0, \lPci\
ifMaskSet(\lPci0\ ifAddrSet(\lPci0\\168.0.100\ ipAttach(0, \i\
ifMaskSet(\ei0\ ifAddrSet(\i0\\2.168.1.100\ ipAttach(1, \i\
ifMaskSet(\ei1\
35
嵌入式VxWorks学习总结报告 ifAddrSet(\i1\\2.168.2.100\
注意:这些网口的ip地址不要在同一个子网内。在实际的插卡过程中,尤其是PCI插拔的网卡,一定要安装主板上默认的网卡顺序进行插拔,以免造成网卡不能驱动,影响调试。
在开发过程中,我采用的双网卡是两块RTL8139网卡,配置步骤大致如上所示,这里不再赘述。双网卡的测试主要是分别在主机与目标机所在的局域网内,在其他主机上的cmd窗口中使用ping命令,如果可以ping到相应的主机或目标机,则表明双网卡通信是可以实现的。至于具体的VxWorks在目标机所在的网络通信,会在后续的开发中实现。
3.1.6 中西文混合输出
在之前的
WindML界面开发中,我们已经提到,可以通过对
uglTextDrawW()函数的修改,实现汉字显示。基本思想是,在uglTextDrawW()函数中,对中西文混合字体进行预处理,将其中单字节西文扩展为双字节,和汉字在内存编码空间一致,主要是通过在西文编码前增加0x00实现,这样在使用uglTextDrawW()函数时,就可以顺利实现中西文混合输出。
uglTextDrawW()函数的修改:
UGL_STATUS uglTextDrawW (
UGL_GC_ID gc, /* graphics context */ UGL_POS x, /* left position of the text */ UGL_POS y, /* top position of the text */
UGL_SIZE length, /* number of characters in text */ const UGL_WCHAR *text /* double-byte text array */ ) {
UGL_STATUS status;
UCHAR *strTemp; int leng;
leng = (int)strlen((const char *)text) + 1; if ((strTemp = malloc(2*leng)) == NULL) return (UGL_STATUS_ERROR);
leng = myHzStrInit((UCHAR *)text,strTemp,leng-1);
/* Lock GC and graphics driver */
if ((status = uglBatchStart(gc)) == UGL_STATUS_OK)
36
嵌入式VxWorks学习总结报告 {
UGL_FONT_DRIVER * pFontDriver = UGL_NULL; if (gc->pFont) {
pFontDriver = gc->pFont->pFontDriver; }
if (pFontDriver != UGL_NULL && pFontDriver->textDrawW != UGL_NULL) {
/* status = (*pFontDriver->textDrawW)(gc, x, y, length, text);*/
status = (*pFontDriver->textDrawW)(gc, x, y, -1, (const UGL_WCHAR *)strTemp); } else {
status = UGL_STATUS_ERROR; }
uglBatchEnd(gc); }
free(strTemp); return (status); }
其中添加myHzStrInit()函数:
UGL_LOCAL int myHzStrInit(UCHAR *inStr,UCHAR *outStr,int leng) {
int i=0; int j=0;
while((i if(inStr[i]<0x80) { outStr[j+1] = 0x00; outStr[j] = inStr[i]; i+=1; j+=2; } else { if((i+1) 37