4. 使用采样端口通信

任务目标

在VxWorks ARINC653环境中,通过采样端口(Sampling Port)实现两个分区间的周期性数据通信。本案例将配置一个采样端口对:发送分区周期性地写入消息,接收分区周期性地读取消息,验证数据在分区间的正确传递。

环境依赖

本案例基于VxWorks 7 + ARINC653板级支持包(BSP),需要以下组件:

  • VxWorks 7 集成开发环境(Workbench)
  • ARINC653内核模块(已启用分区调度)
  • 支持ARINC653的BSP(如x86或PowerPC架构)

核心实现

以下代码展示了采样端口通信的完整实现,包含发送分区和接收分区两个独立模块。采样端口采用单生产者单消费者模式,端口方向在创建时确定。

/* 采样端口通信实现 - 发送分区 (Partition1) */
#include <vxWorks.h>
#include <arinc653.h>

/* 采样端口配置参数 */
#define SAMP_PORT_NAME        "SAMPLE_PORT_1"
#define SAMP_PORT_MESSAGE_SIZE  32
#define SAMP_PORT_PERIOD_MS     100   /* 发送周期 */

/* 发送分区主函数 */
void Partition1Main(void)
{
    STATUS        status;
    SAMPLING_PORT_ID portId;
    SAMPLE_PORT_STATUS portStatus;
    char          sendBuffer[SAMP_PORT_MESSAGE_SIZE];
    int           msgCount = 0;
    
    /* 创建采样端口(发送方向) */
    status = CREATE_SAMPLING_PORT(
        SAMP_PORT_NAME,
        SAMP_PORT_MESSAGE_SIZE,
        DESTINATION,
        SAMP_PORT_PERIOD_MS,
        &portId);
    
    if (status != OK) {
        printf("P1: 采样端口创建失败, status=%d\n", status);
        return;
    }
    printf("P1: 采样端口创建成功, ID=%d\n", portId);
    
    /* 周期性发送数据 */
    while (1) {
        /* 构造消息内容 */
        snprintf(sendBuffer, sizeof(sendBuffer), 
                 "P1-Msg-%d", msgCount++);
        
        /* 写入采样端口 */
        status = WRITE_SAMPLING_MESSAGE(portId, 
                                        sendBuffer, 
                                        strlen(sendBuffer) + 1);
        if (status != OK) {
            printf("P1: 写入失败, status=%d\n", status);
        } else {
            printf("P1: 已发送: %s\n", sendBuffer);
        }
        
        /* 周期延时 */
        PERIODIC_WAIT(1);  /* 等待下一个周期 */
    }
}

/* 接收分区主函数 (Partition2) */
void Partition2Main(void)
{
    STATUS        status;
    SAMPLING_PORT_ID portId;
    SAMPLE_PORT_STATUS portStatus;
    char          recvBuffer[SAMP_PORT_MESSAGE_SIZE];
    int           msgCount = 0;
    
    /* 创建采样端口(接收方向) */
    status = CREATE_SAMPLING_PORT(
        SAMP_PORT_NAME,
        SAMP_PORT_MESSAGE_SIZE,
        SOURCE,
        SAMP_PORT_PERIOD_MS,
        &portId);
    
    if (status != OK) {
        printf("P2: 采样端口创建失败, status=%d\n", status);
        return;
    }
    printf("P2: 采样端口创建成功, ID=%d\n", portId);
    
    /* 周期性接收数据 */
    while (1) {
        /* 读取采样端口消息 */
        status = READ_SAMPLING_MESSAGE(portId, 
                                       recvBuffer, 
                                       sizeof(recvBuffer));
        if (status == OK) {
            printf("P2: 收到消息: %s\n", recvBuffer);
            msgCount++;
        } else {
            printf("P2: 读取超时或无新数据\n");
        }
        
        /* 周期延时 */
        PERIODIC_WAIT(1);
    }
}

配置说明

在VxWorks的ARINC653分区配置文件中(通常为XML格式),需要为两个分区分配采样端口资源:

<!-- 分区配置文件片段 (arinc653_config.xml) -->
<!-- 采样端口定义 -->
<Sampling_Port>
    <Port_Name>SAMPLE_PORT_1</Port_Name>
    <Port_Direction>DESTINATION</Port_Direction>
    <Max_Message_Size>32</Max_Message_Size>
    <Port_Period>100</Port_Period>
</Sampling_Port>

<!-- 分区1 (发送) -->
<Partition>
    <Name>Partition1</Name>
    <Sampling_Port_Ref>SAMPLE_PORT_1</Sampling_Port_Ref>
</Partition>

<!-- 分区2 (接收) -->
<Partition>
    <Name>Partition2</Name>
    <Sampling_Port_Ref>SAMPLE_PORT_1</Sampling_Port_Ref>
</Partition>

运行与验证

编译与部署:

  1. 在Workbench中创建两个分区工程,分别包含Partition1Main和Partition2Main代码
  2. 编译生成分区可执行文件(.out)
  3. 配置ARINC653模块系统镜像,加载分区配置文件和两个分区可执行文件
  4. 启动VxWorks目标机系统

验证方法:

  1. 观察串口或控制台输出,应看到P1和P2的启动日志
  2. 确认P1周期性打印"已发送: P1-Msg-N"(N递增)
  3. 确认P2周期性打印"收到消息: P1-Msg-N",且消息内容与P1发送的序号一致
  4. 通过条件:P2接收到的消息序号连续递增,无乱序或丢失(在采样端口语义下,允许覆盖旧数据,但不应出现错误内容)

预期输出示例:

P1: 采样端口创建成功, ID=0
P2: 采样端口创建成功, ID=0
P1: 已发送: P1-Msg-0
P2: 收到消息: P1-Msg-0
P1: 已发送: P1-Msg-1
P2: 收到消息: P1-Msg-1
P1: 已发送: P1-Msg-2
P2: 收到消息: P1-Msg-2
...

关键要点

  • 采样端口创建时需指定方向:SOURCE(接收)或DESTINATION(发送),同一端口名在两个分区中方向必须匹配
  • PERIODIC_WAIT(1)依赖ARINC653分区周期调度,需在分区配置中设置正确的周期值
  • 采样端口消息大小固定,写入超过端口容量的数据会返回错误
  • 接收方使用READ_SAMPLING_MESSAGE时,若端口无新数据且超时时间到,返回错误码,需根据实际需求处理