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 */
}

运行与验证

  1. 在Workbench中编译两个分区模块,生成可加载的ARINC653模块
  2. 将系统镜像部署到目标机并启动
  3. 观察串口输出,预期看到以下交替日志:
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是否一致,队列深度是否足够容纳发送间隔内的消息积压