3. 实现分区间的消息传递
任务目标
在VxWorks ARINC653环境中,通过消息传递机制实现两个分区之间的数据交换。本案例将创建两个分区:发送分区(Sender)周期性地向接收分区(Receiver)发送递增计数消息,接收分区读取并校验消息内容。
环境依赖
本案例基于VxWorks 7 + ARINC653模块构建,需要以下组件:
- VxWorks 7(含ARINC653内核模块)
- Wind River Workbench(用于编译和部署)
- 目标机配置文件(.cdf)中启用ARINC653支持
核心实现
ARINC653消息传递通过采样端口(Sampling Port)或队列端口(Queuing Port)实现。本案例采用队列端口,支持消息的异步缓冲传递。发送分区创建队列端口并周期写入,接收分区读取并校验。
/* 消息传递实现 - 发送分区 */
#include <vxWorks.h>
#include <arinc653.h>
#define MSG_SIZE 16
#define QUEUE_DEPTH 8
#define SEND_INTERVAL 1000 /* 1秒发送周期 */
/* 发送分区主函数 */
void SenderPartition(void)
{
STATUS status;
QUEUE_PORT_ID portId;
char msg[MSG_SIZE];
int counter = 0;
SYSTEM_TIME_TYPE currentTime;
/* 创建队列端口(发送方向) */
status = CREATE_QUEUING_PORT("MSG_QUEUE", MSG_SIZE, QUEUE_DEPTH,
DESTINATION, &portId);
if (status != NO_ERROR) {
printf("Sender: 端口创建失败, status=%d\n", status);
return;
}
while (1) {
/* 构造消息 */
snprintf(msg, MSG_SIZE, "MSG-%d", counter++);
GET_TIME(currentTime);
/* 发送消息(无限等待直到成功) */
status = SEND_QUEUING_MESSAGE(portId, msg, MSG_SIZE,
INFINITE_TIME_VALUE);
if (status != NO_ERROR) {
printf("Sender: 发送失败, status=%d\n", status);
} else {
printf("Sender: 已发送 [%s] at %d ms\n", msg, currentTime);
}
/* 等待下一个周期 */
PERIODIC_WAIT(SEND_INTERVAL);
}
}
/* 消息传递实现 - 接收分区 */
#include <vxWorks.h>
#include <arinc653.h>
#define MSG_SIZE 16
#define RECEIVE_TIMEOUT 2000 /* 2秒超时 */
/* 接收分区主函数 */
void ReceiverPartition(void)
{
STATUS status;
QUEUE_PORT_ID portId;
char msg[MSG_SIZE];
int msgSize;
int expected = 0;
SYSTEM_TIME_TYPE currentTime;
/* 创建队列端口(接收方向) */
status = CREATE_QUEUING_PORT("MSG_QUEUE", MSG_SIZE, QUEUE_DEPTH,
SOURCE, &portId);
if (status != NO_ERROR) {
printf("Receiver: 端口创建失败, status=%d\n", status);
return;
}
while (1) {
msgSize = MSG_SIZE;
status = RECEIVE_QUEUING_MESSAGE(portId, msg, &msgSize,
RECEIVE_TIMEOUT);
if (status == NO_ERROR) {
GET_TIME(currentTime);
printf("Receiver: 收到 [%s] at %d ms\n", msg, currentTime);
/* 校验消息内容 */
char expectedMsg[MSG_SIZE];
snprintf(expectedMsg, MSG_SIZE, "MSG-%d", expected);
if (strcmp(msg, expectedMsg) == 0) {
printf("Receiver: 校验通过 (期望 %s)\n", expectedMsg);
} else {
printf("Receiver: 校验失败! 收到 %s, 期望 %s\n",
msg, expectedMsg);
}
expected++;
} else if (status == NOT_AVAILABLE) {
printf("Receiver: 接收超时,无新消息\n");
} else {
printf("Receiver: 接收错误, status=%d\n", status);
}
}
}
分区配置与集成
在ARINC653系统配置中,需要将上述两个函数分别绑定到两个独立分区,并分配时间窗口。以下为关键配置片段(集成到系统.cdf文件中):
/* 分区调度配置(时间窗口分配) */
PARTITION Sender {
ENTRY_POINT = SenderPartition;
TIME_WINDOW = 1000; /* 每周期1ms */
}
PARTITION Receiver {
ENTRY_POINT = ReceiverPartition;
TIME_WINDOW = 1000; /* 每周期1ms */
}
/* 系统主时间框架:交替调度两个分区 */
SCHEDULE {
PARTITION Sender DURATION 1000;
PARTITION Receiver DURATION 1000;
PERIOD = 2000; /* 主时间框架2ms */
}
运行与验证
- 在Workbench中编译两个分区模块,生成可加载的ARINC653模块
- 将系统镜像部署到目标机并启动
- 观察串口输出,预期看到以下交替日志:
Sender: 已发送 [MSG-0] at 1000 ms
Receiver: 收到 [MSG-0] at 1000 ms
Receiver: 校验通过 (期望 MSG-0)
Sender: 已发送 [MSG-1] at 2000 ms
Receiver: 收到 [MSG-1] at 2000 ms
Receiver: 校验通过 (期望 MSG-1)
...
通过条件:接收分区连续收到10条以上消息且每条校验均通过,无发送/接收错误状态码,即可判定消息传递机制工作正常。
常见问题
- 端口创建失败(INVALID_CONFIG):检查两个分区是否使用完全相同的端口名称"MSG_QUEUE",且一个为SOURCE、另一个为DESTINATION
- 接收超时(NOT_AVAILABLE):确认发送分区的调度周期与接收分区的时间窗口重叠,且发送间隔小于接收超时时间
- 消息内容错乱:检查消息大小MSG_SIZE是否一致,队列深度是否足够容纳发送间隔内的消息积压