# 第四章:标准寄存器(0-15)——基本控制、状态与厂商ID

本章核心要点

  • 掌握寄存器0-15的固定含义与访问规则
  • 学会通过控制寄存器完成自协商、复位、环回等操作
  • 理解状态寄存器如何反馈链路状态与故障
  • 学会读取厂商ID与型号,识别芯片身份
## 4.1 标准寄存器概述——为什么是0-15? 你打开任何一款PHY的数据手册,都会发现寄存器0到15的定义几乎是固定的。这不是巧合。 IEEE 802.3规范里,这16个寄存器被称为“基本寄存器集”。说白了,这是所有PHY芯片必须实现的公共接口。不管你是Broadcom、Marvell还是Realtek的片子,寄存器0永远是控制寄存器,寄存器1永远是状态寄存器。 **我个人习惯**,调试一个新板子时,第一件事不是看信号质量,而是先读寄存器0和1。为什么?如果这两个寄存器都读不到正确值,说明MDIO/MDC通路有问题,后面的分析全是白费。 ## 4.2 寄存器0——基本控制寄存器 这是最常用的寄存器,没有之一。它控制着PHY的核心行为。 ### 4.2.1 寄存器0位定义 | 位域 | 名称 | 功能简述 | |------|------|----------| | 15 | 软件复位 | 1=复位PHY,复位后自动清0 | | 14 | 环回模式 | 1=使能环回,用于板级测试 | | 13 | 速率选择(高位) | 与位6组合选择速率 | | 12 | 自协商使能 | 1=使能自协商,0=强制模式 | | 11 | 省电模式 | 1=进入省电状态 | | 10 | 隔离模式 | 1=隔离MII接口 | | 9 | 重启自协商 | 1=重新开始自协商 | | 8 | 双工模式 | 1=全双工,0=半双工 | | 7 | 碰撞测试 | 1=使能碰撞测试(很少用) | | 6 | 速率选择(低位) | 与位13组合 | | 5 | 解除自动降速 | 1=关闭自动降速 | | 4:0 | 预留 | 通常为0 | ### 4.2.2 软件复位操作 **我曾经**在一个量产项目中吃过亏——复位后没有等待足够时间就直接读写其他寄存器。结果读到的一直是复位前的脏数据。 正确做法是这样的:
// 步骤1: 写入复位命令
write_phy_reg(phy_addr, 0, 0x8000);

// 步骤2: 等待复位完成(关键!)
int timeout = 1000;
while (timeout--) {
    uint16_t val = read_phy_reg(phy_addr, 0);
    if ((val & 0x8000) == 0) {
        printf("Reset complete!\n");
        break;
    }
    delay_us(10);  // 至少等10微秒
}
if (timeout == 0) {
    printf("ERROR: Reset timeout!\n");
}
经验之谈:复位后,寄存器会回到默认值。但有些PHY在复位期间不响应MDIO读请求,读回来的数据可能是0xFFFF。我一般会在复位后额外延时2ms,确保PHY内部状态机稳定。
## 4.3 寄存器1——基本状态寄存器 这个寄存器告诉你PHY当前的状态。很多调试问题能从这里找到线索。 ### 4.3.1 关键位解读 | 位域 | 名称 | 含义 | |------|------|------| | 15 | 100BASE-T4支持 | 基本没用,T4早就淘汰了 | | 14 | 100BASE-TX全双工支持 | 1=支持 | | 13 | 100BASE-TX半双工支持 | 1=支持 | | 12 | 10BASE-T全双工支持 | 1=支持 | | 11 | 10BASE-T半双工支持 | 1=支持 | | 10:7 | 预留 | 读为0 | | 6 | MF预充支持 | 一般不用关心 | | 5 | 自协商完成 | 1=自协商完成(重要!) | | 4 | 远端错误 | 1=对端报告了错误 | | 3 | 自协商能力 | 1=支持自协商 | | 2 | 链路状态 | 1=链路已建立(核心指标) | | 1 | 页接收能力 | 支持页交换 | | 0 | 扩展寄存器能力 | 支持寄存器16+ | **我遇到过一个诡异问题**:板子上电后链路指示灯不亮,但寄存器1的位2(链路状态)却是1。这说明什么?说明MAC侧检测到了信号,但物理层协商出了问题。真相是——对端PHY工作在100M,我这端强制配成了10M。频率不匹配,信号还能被检测到,但数据根本传不了。 ### 4.3.2 链路检测实战术
// 检查链路是否建立
uint16_t status = read_phy_reg(phy_addr, 1);

if (status & 0x0004) {
    printf("Link is UP\n");
    
    // 检查自协商是否完成
    if (status & 0x0020) {
        printf("Auto-negotiation complete\n");
        
        // 读伙伴的能力(需要读寄存器5)
        uint16_t partner = read_phy_reg(phy_addr, 5);
        // ... 进一步分析
    }
} else {
    printf("Link is DOWN! Check cable/connector\n");
}
## 4.4 寄存器2和3——厂商ID 这两个寄存器构成一个32位的厂商识别码。寄存器2是高16位,寄存器3是低16位。 我记得有一次在实验室里,拿来一块新板子。标签被磨掉了,软件团队不知道里面是什么PHY。我让他们读寄存器2和3,得到0x0141和0x0CC2。查一下标准分配——0x0141是Broadcom的代码。再查0x0CC2对应的具体型号——BCM5461。问题解决了。 ### 常见厂商ID简表 | 厂商 | 寄存器2值 | 寄存器3典型值 | |------|-----------|--------------| | Broadcom | 0x0141 | 0x0Cx0系列 | | Marvell | 0x0141 | 0x0Ex0系列 | | Realtek | 0x001C | 0x81x0系列 | | Microchip | 0x0050 | 0x6Cx0系列 | | TI | 0x0800 | 0x28x0系列 |
注意:有些PHY的寄存器2和3在复位后可能是0x0000,需要先执行一次读取或软件复位才能拿到正确ID。别问我怎么知道的——板子刚上电就急着读ID,结果全是0,怀疑人生。
## 4.5 寄存器4和5——自协商伙伴能力 这两个寄存器是调试自协商问题的关键。 寄存器4:广告能力。告诉对端“我能跑哪些模式”。 寄存器5:伙伴能力。告诉本端“对端能跑哪些模式”。 我调试一个1000M项目时,发现链接只能协商到100M。读寄存器5一看,伙伴能力的1000M位根本没置1。换了一台千兆交换机,问题立刻解决。 ## 4.6 寄存器6——自协商扩展状态 这个寄存器有4个位特别重要: | 位域 | 名称 | 含义 | |------|------|------| | 15 | 1000BASE-X全双工 | 千兆全双工支持 | | 14 | 1000BASE-X半双工 | 千兆半双工支持 | | 13 | 1000BASE-T全双工 | 1000BASE-T全双工 | | 12 | 1000BASE-T半双工 | 1000BASE-T半双工 | | 11:0 | 其他 | 一般用不到 | ## 4.7 寄存器0-15知识体系结构图 标准寄存器0-15知识体系结构图 标准寄存器集(0-15) 控制类寄存器 状态类寄存器 标识/能力类 Reg 0 控制 Reg 16+ 扩展 Reg 1 状态 Reg 6 扩展状态 Reg 2/3 厂商ID Reg 4/5 能力 复位/环回 速率/双工 自协商控制 链路状态检测 自协商完成标志 远端错误标志 OUI/型号识别 协商能力匹配 双工模式匹配 提示:寄存器0-15是所有PHY芯片的公共基础,调试时优先检查寄存器1的链路状态和寄存器0的复位状态 ## 4.8 实战调试方法论 ### 4.8.1 上电调试第一步 我每调试一个新板子,都会按这个顺序检查: 1. **读寄存器2和3**:确认PHY型号 2. **读寄存器0**:确认当前配置(复位状态、自协商开关) 3. **读寄存器1**:确认链路是否建立 4. **如果链路down**:检查寄存器4和5,看自协商是否在跑 5. **如果链路up但不通**:检查寄存器0的速率和双工设置 ### 4.8.2 常见问题排查 | 现象 | 检查寄存器 | 可能原因 | |------|-----------|----------| | 读寄存器全是0xFFFF | 任意 | MDIO不通,检查时钟和数据线 | | 读寄存器全是0x0000 | 任意 | PHY未上电或复位引脚被拉低 | | 链路不稳定,频繁up/down | 寄存器1位2 | 线缆质量差或连接器接触不良 | | 只能协商到最低速率 | 寄存器5 | 对端设备能力不足 | | 能ping通但丢包 | 寄存器0位14 | 可能误开了环回模式 |
我的一个小技巧:在调试脚本里,我会定期打印寄存器1的值(比如每500ms一次)。连续打印几轮,链路状态、自协商标志的变化模式就能一目了然。很多时候,问题藏在“偶尔闪一下”的异常里。
## 4.9 本章小结 寄存器0-15是PHY调试的起点和基石。掌握了它们,你就能: - 快速判断硬件通路是否正常 - 读懂链路协商的过程和结果 - 精准定位大部分物理层问题 **我个人经验是**:很多复杂的PHY问题,最后都能追溯到这几个寄存器的某个位上。有时候一个bit就能解释为什么设备不能互通、为什么性能达不到标称值。所以,花时间吃透这16个寄存器,是PHY调试中最值得的投入。