4. 实现UniPro链路启动序列

任务说明

本案例实现UniPro协议栈中PHY适配层到数据链路层的链路启动序列,覆盖唤醒(Wakeup)、同步(Sync)和参数协商(Parameter Negotiation)三个阶段,最终使链路进入Active状态。实现采用C语言,模拟M-PHY Gear1配置,不依赖具体硬件寄存器。

核心数据结构

typedef enum {
    LS_WAKEUP,
    LS_SYNC,
    LS_NEGOTIATE,
    LS_ACTIVE,
    LS_ERROR
} LinkState;

typedef struct {
    uint8_t gear;        /* M-PHY Gear: 1~4 */
    uint8_t lane;        /* Lane count: 1~4 */
    uint16_t hs_rate;    /* High-speed rate (Mbps) */
    uint8_t pwm_rate;    /* PWM rate code */
} UniProParams;

typedef struct {
    LinkState state;
    UniProParams local;
    UniProParams peer;
    uint8_t retry_count;
    uint8_t sync_attempts;
} UniProLink;

关键完整代码

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

#define MAX_SYNC_ATTEMPTS 3
#define MAX_RETRY 2

/* 发送唤醒序列:拉高线缆电平并保持特定时间 */
static int phy_send_wakeup(void) {
    /* 实际硬件中此处操作PHY寄存器使能唤醒信号 */
    return 0; /* 0表示成功 */
}

/* 发送同步序列:连续发送SYNC字符 */
static int phy_send_sync_pattern(void) {
    /* 向对端发送0x55模式,持续至少10个字符时间 */
    return 0;
}

/* 接收对端同步响应 */
static int phy_wait_sync_ack(uint32_t timeout_ms) {
    (void)timeout_ms;
    /* 检查是否收到对端SYNC响应 */
    return 0;
}

/* 发送参数协商请求 */
static int dme_send_params(UniProParams *params) {
    /* 构造并发送DME_SET请求,包含gear/lane/rate */
    printf("  [DME] Send params: gear=%u lane=%u hs_rate=%u\n",
           params->gear, params->lane, params->hs_rate);
    return 0;
}

/* 接收并处理对端参数响应 */
static int dme_recv_params(UniProParams *peer) {
    /* 解析对端返回的DME_GET响应 */
    peer->gear = 1;
    peer->lane = 1;
    peer->hs_rate = 1248;
    return 0;
}

/* 参数协商:比较双方能力,取最小公共配置 */
static int negotiate_params(UniProLink *link) {
    if (dme_send_params(&link->local) != 0) return -1;
    if (dme_recv_params(&link->peer) != 0) return -1;

    /* 取双方支持的最小值作为最终配置 */
    if (link->peer.gear < link->local.gear)
        link->local.gear = link->peer.gear;
    if (link->peer.lane < link->local.lane)
        link->local.lane = link->peer.lane;
    if (link->peer.hs_rate < link->local.hs_rate)
        link->local.hs_rate = link->peer.hs_rate;

    printf("  [DME] Negotiated: gear=%u lane=%u rate=%u Mbps\n",
           link->local.gear, link->local.lane, link->local.hs_rate);
    return 0;
}

/* 链路启动主流程 */
int unipro_link_start(UniProLink *link) {
    link->state = LS_WAKEUP;
    link->retry_count = 0;

    while (link->retry_count <= MAX_RETRY) {
        /* 阶段1: 唤醒 */
        if (phy_send_wakeup() != 0) goto error;
        link->state = LS_SYNC;

        /* 阶段2: 同步 */
        link->sync_attempts = 0;
        while (link->sync_attempts < MAX_SYNC_ATTEMPTS) {
            if (phy_send_sync_pattern() == 0 &&
                phy_wait_sync_ack(100) == 0) {
                break;
            }
            link->sync_attempts++;
        }
        if (link->sync_attempts >= MAX_SYNC_ATTEMPTS) {
            link->retry_count++;
            continue;
        }

        /* 阶段3: 参数协商 */
        link->state = LS_NEGOTIATE;
        if (negotiate_params(link) != 0) {
            link->retry_count++;
            continue;
        }

        /* 进入Active状态 */
        link->state = LS_ACTIVE;
        printf("  [LINK] Link is ACTIVE (gear=%u, lane=%u)\n",
               link->local.gear, link->local.lane);
        return 0;

error:
        link->retry_count++;
    }

    link->state = LS_ERROR;
    printf("  [LINK] Link start FAILED after %u retries\n", link->retry_count);
    return -1;
}

/* 最小调用入口 */
int main(void) {
    UniProLink link;
    memset(&link, 0, sizeof(link));

    link.local.gear = 1;
    link.local.lane = 1;
    link.local.hs_rate = 1248;

    printf("Starting UniPro link...\n");
    int ret = unipro_link_start(&link);

    if (ret == 0) {
        printf("Link startup sequence PASSED\n");
        return 0;
    } else {
        printf("Link startup sequence FAILED\n");
        return 1;
    }
}

编译与运行

gcc -std=c99 -Wall -o unipro_link unipro_link.c
./unipro_link

验证方法

程序执行后观察输出:

  • 若依次打印[DME] Send params、[DME] Negotiated和[LINK] Link is ACTIVE,且最终返回Link startup sequence PASSED,说明链路启动序列完整执行并进入Active状态。
  • 若出现FAILED或ERROR,说明某阶段未通过,可检查各PHY/DME函数的返回值。

判定通过条件:main返回0,且状态机最终停留在LS_ACTIVE。本代码为纯逻辑模拟,PHY层函数返回0表示硬件操作成功;接入真实硬件时,需将phy_*和dme_*函数替换为实际寄存器读写实现。

WAKEUP SYNC NEGOTIATE ACTIVE ERROR 唤醒成功 同步完成 协商成功 同步失败重试 协商失败 重试耗尽 正常流程 失败重试

状态机图中,链路启动按WAKEUP→SYNC→NEGOTIATE顺序推进,任一步失败则重试;重试超过MAX_RETRY次进入ERROR状态。同步阶段内部有最多3次尝试,全部失败才触发外层重试。