4. FlexRay静态段帧收发测试

任务目标

在车联网WAVE协议栈中,WSMP(WAVE Short Message Protocol)位于WAVE协议栈的传输层,负责在WAVE上层应用与下层LLC之间传递短消息。本案例实现WSMP消息的封装与解析核心逻辑,支持将应用层载荷封装为符合IEEE 1609.3标准的WSMP帧,并能从接收到的字节流中正确解析出各字段。

核心实现

#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define WSMP_VERSION 0x03
#define WSMP_HEADER_LEN 8
#define MAX_PAYLOAD 1400

typedef struct {
    uint8_t version;
    uint8_t psid[4];      // Provider Service Identifier
    uint8_t channel;
    uint8_t dataRate;
    uint8_t power;
    uint8_t *payload;
    uint16_t payloadLen;
} WSMP_Msg;

// 封装:生成WSMP帧(含头部+载荷)
uint16_t wsmp_encode(WSMP_Msg *msg, uint8_t *outBuf, uint16_t bufSize) {
    if (!msg || !outBuf || bufSize < WSMP_HEADER_LEN + msg->payloadLen)
        return 0;
    if (msg->payloadLen > MAX_PAYLOAD)
        return 0;

    uint16_t idx = 0;
    outBuf[idx++] = (msg->version << 4) | 0x0C;  // 高4位版本,低4位为头部长度(8字节)
    outBuf[idx++] = msg->psid[0];
    outBuf[idx++] = msg->psid[1];
    outBuf[idx++] = msg->psid[2];
    outBuf[idx++] = msg->psid[3];
    outBuf[idx++] = (msg->channel << 4) | (msg->dataRate & 0x0F);
    outBuf[idx++] = msg->power;
    outBuf[idx++] = (msg->payloadLen >> 8) & 0xFF;
    outBuf[idx++] = msg->payloadLen & 0xFF;

    memcpy(outBuf + idx, msg->payload, msg->payloadLen);
    return WSMP_HEADER_LEN + msg->payloadLen;
}

// 解析:从WSMP帧中提取各字段
int wsmp_decode(const uint8_t *frame, uint16_t frameLen, WSMP_Msg *msg) {
    if (!frame || !msg || frameLen < WSMP_HEADER_LEN)
        return -1;

    msg->version = (frame[0] >> 4) & 0x0F;
    uint8_t hdrLen = (frame[0] & 0x0F) * 4;  // 低4位表示头部长度(单位4字节)
    if (hdrLen != WSMP_HEADER_LEN || frameLen < hdrLen)
        return -2;

    msg->psid[0] = frame[1];
    msg->psid[1] = frame[2];
    msg->psid[2] = frame[3];
    msg->psid[3] = frame[4];
    msg->channel = (frame[5] >> 4) & 0x0F;
    msg->dataRate = frame[5] & 0x0F;
    msg->power = frame[6];
    msg->payloadLen = (frame[7] << 8) | frame[8];

    if (hdrLen + msg->payloadLen > frameLen)
        return -3;

    msg->payload = (uint8_t *)frame + hdrLen;
    return 0;
}

// 测试入口
int main() {
    uint8_t payload[] = {0xDE, 0xAD, 0xBE, 0xEF};
    WSMP_Msg tx = {
        .version = WSMP_VERSION,
        .psid = {0x00, 0x00, 0x00, 0x01},
        .channel = 0x02,
        .dataRate = 0x03,
        .power = 0x10,
        .payload = payload,
        .payloadLen = sizeof(payload)
    };

    uint8_t buf[64];
    uint16_t len = wsmp_encode(&tx, buf, sizeof(buf));
    if (len == 0) {
        printf("encode failed\n");
        return 1;
    }

    WSMP_Msg rx;
    memset(&rx, 0, sizeof(rx));
    if (wsmp_decode(buf, len, &rx) != 0) {
        printf("decode failed\n");
        return 1;
    }

    // 验证字段一致性
    if (rx.version == tx.version &&
        memcmp(rx.psid, tx.psid, 4) == 0 &&
        rx.channel == tx.channel &&
        rx.dataRate == tx.dataRate &&
        rx.power == tx.power &&
        rx.payloadLen == tx.payloadLen &&
        memcmp(rx.payload, tx.payload, tx.payloadLen) == 0) {
        printf("PASS: encode/decode round-trip OK\n");
        return 0;
    } else {
        printf("FAIL: field mismatch\n");
        return 1;
    }
}

编译与运行

gcc -o wsmp_demo wsmp_demo.c
./wsmp_demo

验证方法

程序执行后输出 PASS: encode/decode round-trip OK 即表示封装与解析逻辑正确。该验证通过将同一消息先封装再解析,比对所有字段(版本、PSID、信道、速率、功率、载荷长度与内容)是否完全一致,确保编解码互为逆操作。

关键说明

  • WSMP头部固定为8字节:第1字节高4位为版本号(3),低4位表示头部长度(值为2,表示8字节,单位4字节);第2~5字节为4字节PSID;第6字节高4位为信道号、低4位为数据速率;第7字节为发射功率;第8~9字节为载荷长度(大端序)。
  • 本实现聚焦WSMP核心编解码逻辑,未包含WAVE协议栈中LLC封装、信道竞争等底层处理,实际接入时需将生成的WSMP帧交由下层LLC子层发送。
  • PSID采用4字节表示,符合IEEE 1609.3中PSID的通用格式;若需支持1字节短PSID,可在此框架上扩展。