2. 建立UniPro物理层连接
任务目标
本案例要求通过M-PHY配置与UniPro链路启动序列,在两个UniPro节点(本地节点A与远端节点B)之间建立物理层连接,并验证链路状态达到Active状态。实现范围限定为:M-PHY的PWM-G1速率配置、物理层适配层的启动序列状态机,以及链路状态查询验证。
环境与依赖
- 语言:C(C99兼容)
- 依赖:仅使用标准库
stdint.h、string.h,无第三方库 - 运行方式:单文件编译,模拟两个节点的寄存器交互
核心实现
以下代码实现了M-PHY配置结构体、链路启动状态机(包含HIBERNATE→CFG→Active三态迁移),以及通过共享内存模拟的寄存器读写接口。节点A主动发起启动序列,节点B被动响应。
#include <stdint.h>
#include <string.h>
#include <stdio.h>
/* M-PHY 配置参数 */
typedef struct {
uint8_t gear; /* PWM-G1 = 1 */
uint8_t lane_count; /* 1 lane */
uint16_t hs_series; /* 未使用,保留 */
} MphyConfig;
/* UniPro 链路状态 */
typedef enum {
LINK_HIBERNATE = 0,
LINK_CFG,
LINK_ACTIVE
} LinkState;
/* 节点结构体 */
typedef struct {
MphyConfig mphy;
LinkState state;
uint8_t peer_ready; /* 对端是否已完成配置 */
} UniProNode;
/* 模拟寄存器映射(共享内存) */
static UniProNode node_A, node_B;
static uint8_t link_established;
/* 初始化节点 */
static void node_init(UniProNode *n, uint8_t gear) {
n->mphy.gear = gear;
n->mphy.lane_count = 1;
n->state = LINK_HIBERNATE;
n->peer_ready = 0;
}
/* 写对端寄存器(模拟物理层信号) */
static void write_peer_reg(UniProNode *self, UniProNode *peer,
uint8_t offset, uint32_t value) {
(void)self;
/* 实际硬件中此处通过M-PHY发送写入请求 */
switch (offset) {
case 0x00: peer->mphy.gear = (uint8_t)value; break;
case 0x04: peer->state = (LinkState)value; break;
case 0x08: peer->peer_ready = (uint8_t)value; break;
default: break;
}
}
/* 读对端寄存器 */
static uint32_t read_peer_reg(UniProNode *peer, uint8_t offset) {
switch (offset) {
case 0x00: return peer->mphy.gear;
case 0x04: return (uint32_t)peer->state;
case 0x08: return peer->peer_ready;
default: return 0;
}
}
/* 链路启动序列(节点A主动发起) */
static void link_start_sequence(UniProNode *initiator, UniProNode *target) {
/* Step 1: 配置本地M-PHY为PWM-G1 */
initiator->mphy.gear = 1;
initiator->mphy.lane_count = 1;
/* Step 2: 通知对端进入CFG状态 */
write_peer_reg(initiator, target, 0x04, LINK_CFG);
initiator->state = LINK_CFG;
/* Step 3: 等待对端确认(轮询模拟) */
for (int i = 0; i < 100; i++) {
if (read_peer_reg(target, 0x04) == LINK_CFG) {
break;
}
}
/* Step 4: 对端配置完成,双方进入Active */
write_peer_reg(initiator, target, 0x08, 1);
target->state = LINK_ACTIVE;
initiator->state = LINK_ACTIVE;
link_established = 1;
}
/* 验证链路状态 */
static int verify_link_active(void) {
return (node_A.state == LINK_ACTIVE) &&
(node_B.state == LINK_ACTIVE) &&
(link_established == 1);
}
int main(void) {
/* 初始化两个节点 */
node_init(&node_A, 0);
node_init(&node_B, 0);
link_established = 0;
/* 执行链路启动 */
link_start_sequence(&node_A, &node_B);
/* 验证结果 */
if (verify_link_active()) {
printf("PASS: 链路已建立,双方处于Active状态\n");
printf(" Node A: gear=%u, state=%d\n", node_A.mphy.gear, node_A.state);
printf(" Node B: gear=%u, state=%d\n", node_B.mphy.gear, node_B.state);
return 0;
} else {
printf("FAIL: 链路未建立\n");
return 1;
}
}
编译与运行
gcc -std=c99 -o unipro_link unipro_link.c
./unipro_link
验证方法
程序执行后,观察输出是否包含 PASS: 链路已建立。判定通过条件为:
- 程序退出码为0
- 输出中显示节点A和节点B的state均为2(即
LINK_ACTIVE) - 两个节点的gear值均为1(PWM-G1)
若输出FAIL或退出码非0,说明链路启动序列未正确完成状态迁移。
关键说明
- 本实现使用共享内存模拟寄存器读写,实际硬件中
write_peer_reg和read_peer_reg对应M-PHY的寄存器访问命令(如DME_READ/WRITE) - 链路启动序列遵循UniPro规范中的状态迁移:HIBERNATE→CFG→Active,省略了更细粒度的子状态(如链路启动中的LocalTx/LocalRx配置)以聚焦物理层连接核心流程
- PWM-G1为最低速率档,实际应用中如需更高吞吐可扩展gear值,但需同步修改对端配置