从VxWorks 6.x开始风河引入了RTP(VxWorks real time process project)模式编程,这种模式的优点是应用程序相互独立,互不影响,而且增加了内核的稳定性,缺点是由于“内核态”与“用户态”的内存拷贝,其执行效率有所降低,随着CPU速度越来越快,这点效率的牺牲已经越来越不重要。相比较于传统的DKM(downloadable kernel module project),RTP适合多个团队独立运作,然后汇总联试,这种模式除了全局函数不能再shell里直接调用外,其对应用程序几乎不做任何约束,原有的DKM工程代码稍作修改即可正常运行。内核变化较大,需要添加较多的组件,内存需要较好的划分,为保持应用程序直接调用函数调试的习惯,需要封装接口供用户使用。

现简单的介绍RTP使用方法,并给出demo代码供参考。

1.新建并编译工程:

(1) File->New->VxWorks real time process project,如下图

VxWorks RTP Create New Project

(2) 一路next后,选择如下图所示的编译器

VxWorks RTP Choose Compiler

(3) 选择Finish后,工程新建完毕。

(4) 导入源文件:这里的源文件名称是fooRtpApp.c,一种较快捷的方式是选中新建的工程,按下F5,源文件会出现在工程中.

(5) 右键选择编译,出现如下图所示,选择Continue继续

1. 首先,需要在目标机上实现文件系统,比如使用trueFFS,用dosFS初始化tffs设备。在完成tffs驱动之后,可以调用 usrTffsConfig(0,0,"/tffs0/vxworks"); 如果成功,就可以创建TFFS文件系统了,那你就成功了一大半了,恭喜你!!!

2. 板子上首先应该有bootrom,如果没有,使用仿真器写入。

3. 让板子flash中的bootrom启动,通过网络加载vxworks。更新vxworks,应该使目标机在vxworks操作系统的支撑之下。即在运行vxworks时更新存储在flash中的vxworks映象。该vxworks中包含了tffs组件,并用usrTffsConfig创建一个tffs设备。如果创建不成功,先调用sysTffsFormat格式化该设备,再创建。这个vxworks中,应该包含下列代码(也可以启动完毕之后,通过target server动态下载):

 
 
STATUS myftp(char* host, char* user, char* passwd, char* srcFile, char* desFile)  
{  
 
int fd, total = 0;  
int ctrlSock;  
int dataSock;  
char buf [1024];  
int nBytes;  
remove ( desFile);  
fd=open(desFile,0x202,0);  
if (ERROR==fd)  
{  
return ERROR;  
}  
if (ftpXfer (host,user,passwd , "", "RETR s",NULL, srcFile, &ctrlSock, &dataSock) == ERROR)  
{  
return (ERROR);  
}  
while ((nBytes = read (dataSock, buf, 512)) > 0)  
{  
 
total = nBytes;  
write(fd, buf, nBytes);  
}  
 
close(fd);  
close (dataSock);  
close (ctrlSock);  
if(total > 0)  
{  
return ERROR;  
}  
return OK;  
} 
 

各参数的含义为:



#include "vxworks.h"
#include "sockLib.h"
#include "inetLib.h"
#include "MyServer.h"

#define DEFAULT_SERVER_PORT 6699
int server;
SEM_ID Server_SM;
/*
* Start the function Server() as a task in AppInit() like this:
* int ret = 0;
* ret = taskSpawn("tServer", 165, 0x0002, 1024,(FUNCPTR) Server,
* 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
*/
void Server()
{
    int rc = 0, sd = 0;
    int addr_len = 0;
    int server_sock = 0;
    struct sockaddr_in server_addr, client_addr;

    memset(&server_addr, 0, sizeof(struct sockaddr_in));
    memset(&client_addr, 0, sizeof(struct sockaddr_in));
    server_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (server_sock < 0) {
        printf("Failed to create Socket.\n");
        return;
    }
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(DEFAULT_SERVER_PORT);
    rc = bind(server_sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));
    if (rc == -1) {
        close(server_sock);
        printf("Failed to bind socket\n");
        return;
    }
    rc = listen(server_sock, 2);
    if (rc == -1) {
        printf("socket listen error\n");
        return;
    }
    printf("TCP server is ready for receive connection request\n");
    while (1) {
        addr_len = sizeof(struct sockaddr_in);
        sd = accept(server_sock, (struct sockaddr *)&client_addr, &addr_len);
        if (sd <= 0) {
            printf("socket accept error\n");
            return;
        } else {
            printf("Socket connect success\n");
            server = sd;
            server_proc(sd);
        }
    }
}

void server_proc(int sock)
{
    int rc = 0;
    char buffer[32];
    fd_set socket;
    struct timeval wait;

    wait.tv_sec = 0;
    wait.tv_usec = 500000;

    while (server > 0) {
        FD_ZERO(&socket);
        FD_SET(sock, &socket);

        rc = select(FD_SETSIZE, &socket, (fd_set *) 0, (fd_set *) 0, &wait);
        if (rc == 0)
            continue;
        if (FD_ISSET(sock, &socket)) {
            semTake(Server_SM, WAIT_FOREVER);
            memset(buffer, 0, sizeof(buffer));
            rc = recv(sock, buffer, sizeof(buffer), 0);
            if (rc > 0) {
/* you can add your application specific code here */
                printf("RecvMsg:%s\n", buffer);
                semGive(Server_SM);
            } else {
                printf("Socket closed\n");
                close(sock);
                server = 0;
                semGive(Server_SM);
                break;
            }
        }
        taskDelay(10);
    }

}

/* end of the file */
 
摘要:结合嵌入式实时操作系统VxWorks实现风洞测控系统的实际应用,以其中的串口通信为例,讨论了在VxWorks下实现串口通信的关键技术,给出了基本原理、环境配置和程序示例。 关键词:VxWorks; 实时操作系统; 嵌入式操作系统;串行通信 [Abstract] Combining with the application of wind tunnel measure and control system with embedded real-time operating system VxWorks , with the serial communication in it as an example ,the key techniques about realization of the serial communication in VxWorks are discussed. Communication mechanism, environment configure and corresponding program examples are provided. [Key words] VxWorks;RTOS;embedded operating system; Serial Communication

1前言

目前市场上比较著名的实时操作系统有:VxWorks、PSOS、Nucleus、QNX、VRTX、Windows CE、Palm 0S、Lynx0S等。 其中,VxWorks是一个具有微内核、可裁剪的高性能强实时操作系统,在实时操作系统市场上处于领先地位。它以其良好的可靠性和卓越的实时性被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中,如卫星通讯、弹道制导、飞机导航等。在美国的 F-16战斗机、B-2 隐形轰炸机和爱国者导弹上,甚至火星探测器上都使用了VxWorks实时操作系统。在嵌入式实时操作系统中使用串口通信,不仅可扩展嵌入式设备通信能力,而且可扩大其应用范围。

2 VxWorks简介

VxWorks是由wRS(wind River Systems,Inc.)公司开发的一套具有微内核、高性能、可伸缩的实时操作系统,支持广泛的网络通信协议,并能够根据用户的需求进行组合,其开放式的结构和对工业标准的支持使开发者只需做最少的工作即可设计出有效的适合于不同用户要求的系统。除了性能出众的操作系统之外,wRS公司还提供了优秀的实时操作系统开发工具Tornado。Tornado由三个高度集成的部分组成:Tornado工具,一整套强有力的交叉开发工具;VxWorks运行系统,是运行在目标机上的高性能、可裁剪的实时操作系统;连接目标机和宿主机的通信选项,加以太网、串行线路、在线仿真等。Tornado能够支持Windows、Unix等流行的工作平台和PowerPC、X86、ARM等几乎所有的目标处理器,所提供的工具可用于所有目标机,并具有两种调试模式(系统模式和任务模式)。除了基本的功能和开发工具外,Tornado还具有先进的系列网络产品,极大地扩展了Tornado的网络特性,并增强了嵌人式微处理器的网络特性。[1]

3 串口通信基本原理

串口在嵌入式系统当中是一类重要的数据通信接口,其本质功能是作为CPU和串行设备间的编码转换器。当数据从CPU经过串行端口发送出去时,字节数据转换为串行的位;在接收数据时,串行的位被转换为字节数据。应用程序要使用串口进行通信,必须在使用之前向操作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。

串口通信的优点是开发简单,在传输数据量不大、要求速度不高而传输距离较大的通信场合得到广泛应用。

在VxWorks中,将I/O系统设计成为任何类型的设备提供一个简单、统一、独立于设备的接口,任何对于串口的操作都可以视为对一个文件的操作,而不必了解串口设备或程序驱动实现的细节。在串口通信软件的设计中,当串口初始化完成后,在使用之前利用open()打开相应串口,然后进行配置。

VxWorks提供终端和伪终端设备驱动。Tty驱动针对实终端;pty针对仿真终端的程序。Tty设备有两种操作模式:raw模式和line模式。在raw模式下,每个刚从设备输入的字符对读者都是有效的;在line模式下所有输入字符被存储,直到NEWLINE字符输入。设备选项字使用带FIOSETOPTIONS 功能的ioctl()程序来设置。[2]

配置完成后,依据串口打开时的读写标志,调用函数write()、read()对串口进行只读操作、只写操作或同时进行读写操作。

为提高数据接收的实时性,可采用中断方式,利用VxWorks提供的select函数的事件触发机制,将读串口的任务阻塞使其一直等待数据,当有数据来到的时候该任务会立刻自动响应,提高系统的实时性。

4 环境配置

1.create file on floopy disk and write contents:

-> pdev=fdDevCreate(0,0,0,0) /* A:,1.44M,whole disk,offset */

-> dosFsMkfs("/fd0",pdev)

-> fd=creat("/fd0/myfile",2) or -> fp=fopen("/fd0/myfile","w")

-> buf="what you want to write to file"

-> write(fd,buf,strlen(buf)+1) or -> fprintf(fp,buf)

-> close(fd) or -> fclose(fp)

2.open file and read contents from floopy disk:

-> readbuf=malloc(100)

-> fd=open("/fd0/myfile",2) or -> fp=fopen("/fd0/myfile","r")

-> read(fd,readbuf,100) or -> fread(readbuf,1,50,fp)

-> printf readbuf

-> close(fd) or -> close(fp)

3.on simpc shell:

-> fp=fopen("host:d:/temp/myfile","w")

-> fprintf(fp,"kjkkhjk")

-> fclose(fp)