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顺序推进,任一步失败则重试;重试超过MAX_RETRY次进入ERROR状态。同步阶段内部有最多3次尝试,全部失败才触发外层重试。