尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

STM32F746与KSZ8863RLL的RMII链路故障排查:时钟、上拉与寄存器实战

STM32F746与KSZ8863RLL的RMII链路故障排查:时钟、上拉与寄存器实战 做嵌入式网络调试最怕的就是这种问题板子跑起来引脚电平看着没问题SMI 也能读到寄存器但 RMII 链路的 Port 3 就是死活起不来。我最近在一个 STM32F746 的项目里就遇到了 KSZ8863RLL 的 RMII 链路故障现象很典型——Port 3 始终 Link 不上CPU 和交换芯片之间像隔了一堵墙两边都“看到”了对方但数据就是过不去。这篇内容是我把整个排查过程完整复盘一遍重点讲时钟、上拉和寄存器设置这三个最容易翻车的环节。这个话题适合正在做嵌入式以太网、工业网关或者带多口交换板子的工程师。你不一定要用完全相同的芯片组合只要碰到 RMII 接口起不来、链路检测不到、或者 RMII 和 MII 模式切换搞不明白的场景这篇都能给你一套可落地的排查思路。1. 问题背景先把这块三端口交换芯片的定位搞明白1.1 KSZ8863RLL 到底是一颗什么样的芯片KSZ8863RLL 是 Microchip 旗下的一款集成度很高的三端口以太网交换芯片。名字里的“8863”系列大家都比较熟悉常用于工业以太网交换机、嵌入式多口路由器和一些需要一进多出的网关设备。它不像常见的纯 PHY 芯片那样只负责物理层收发而是把 MAC、交换引擎、地址表、VLAN 转发逻辑都做进去了外部只需要搭配一颗主控 CPU 来管理它。三个端口的角色并不完全一样。Port 1 和 Port 2 是带内部 PHY 的 10/100M 铜缆口直接接 RJ45 变压器就能用。Port 3 比较特殊它没有内部 PHY对外引出的是数字接口可以配置成 MII 或 RMII用来和外部 MAC、外部 PHY 或者其他交换芯片对接。在这个项目里Port 3 对接的就是 STM32F746 内部以太网 MAC 的 RMII 接口。很多人第一次看到“RMII Link”这个说法会下意识以为它和普通网口的 Link 灯一样其实概念上要区分开。普通网口的 Link 是物理层协商出来的比如 100M 全双工、10M 半双工这些由 PHY 自动协商决定。而这里 Port 3 是数字 RMII 接口它不存在“自动协商”这种物理层交互它的 Link 状态更多取决于两侧 MAC 是否配置一致、时钟是否同步、使能位是否打开。如果只盯着“Link 灯”很容易被表面现象带偏。1.2 “Port 3 没有 RMII Link”到底在说什么我在这个项目里遇到的故障表象是Port 1 接了一台 PCPC 端显示网络已经连接说明 KSZ8863RLL 的 Port 1 PHY 工作正常。但 STM32F746 通过 RMII 访问 Port 3 时以太网驱动一直报 Link Down用 HAL 库接口查询 PHY 状态也始终是 0x0000 或者 0xFFFF 这种“读不到有效状态”的值。如果只是 Link 状态读不到那可能是 SMI 配置有问题如果 Link 状态读到了但不稳定那多半是 REF_CLK 有问题如果 Link 状态稳定但数据不通那就要查 RMII 的信号线和寄存器转发配置。这几种情况我都碰到过它们的排查路径完全不同。所以做调试前第一件事不是急着改代码而是先确认现象到底属于哪一类。我建议第一次遇到这种问题的朋友先把整个链路从 STM32F746 到 KSZ8863RLL 再往外到 Port 1/Port 2 画一张信号流向图把每个信号的角色标清楚。这一步看着简单却能帮你省下大量“东戳一下西戳一下”的时间。2. 动手调试前把 RMII 和 MII 的差异彻底理清2.1 RMII 和 MII 的差异以及为什么接入 CPU 时常用 RMIIMII 是标准媒体独立接口数据线是 4 位 TXD 和 4 位 RXD加上 TX_EN、TX_CLK、RX_CLK、RX_DV、RX_ER、CRS、COL 这些控制信号总共 16 根线左右。RMII 是精简版数据线从 4 位砍到 2 位控制信号也合并了比如 CRS 和 RX_DV 合并成 CRS_DV时钟统一使用 50MHz REF_CLK不再分开 TX_CLK 和 RX_CLK。这样下来信号数量大概只有 9 根对于引脚紧张的 MCU 来说非常友好。STM32F746 这种片子虽然 IO 多但很多引脚被 LCD、SDRAM、USB、SDIO 占掉了给以太网留的空间有限。RMII 的最大优点就是用更少的引脚完成同样的 100M 以太网数据收发代价是接口时钟频率必须提高到 50MHz。因为数据位宽减半只能靠翻倍时钟来维持 100M 速率。这里有一个非常容易混淆的点很多人以为 RMII 和 MII 只是引脚数量不同直接按引脚定义接上去就能跑。实际上RMII 的 50MHz REF_CLK 必须是同源时钟也就是说MAC 侧的 REF_CLK 和 PHY 侧的 REF_CLK 要由同一个时钟源提供或者由一侧输出给另一侧不能两边各用各的晶振。这个“同源”要求是很多 RMII 链路起不来的罪魁祸首。2.2 50MHz REF_CLK一个时钟引发的“连锁反应”RMII 接口所有信号包括 TXD、RXD、TX_EN、CRS_DV全部以 REF_CLK 为基准。如果 REF_CLK 没起来、频率不对、占空比畸形或者抖动太大整个接口就是“瘫痪”的。我遇到过好多次代码看起来没问题寄存器配置也对但就是不通最后拿示波器一量发现 REF_CLK 只有 25MHz等于数据速率直接对不上接口根本没法工作。在 STM32F746 和 KSZ8863RLL 的组合中REF_CLK 通常有几种来源第一种外部 50MHz 有源晶振同时送给 STM32F746 的 ETH_REF_CLK 引脚和 KSZ8863RLL 的 REF_CLK 引脚。这种方案最稳相位一致性最好但成本略高而且 PCB 上要保证两边的 REF_CLK 走线长度尽量接近。第二种STM32F746 的 MCO1 或 MCO2 输出 50MHz一路给 KSZ8863RLL另一路反馈给 STM32 自己的 ETH_REF_CLK。这种方案在某些开发板上能跑但要注意 MCO 输出的驱动能力和抖动信号质量不好时很容易出现偶发丢包。第三种KSZ8863RLL 工作在 RMII 时钟主模式由它内部把 25MHz 晶振倍频到 50MHz然后从 REF_CLK 引脚输出给 STM32F746。这种方式需要正确配置 KSZ8863RLL 的时钟方向寄存器否则同一引脚可能既输出又输入电平互相打架。调试时优先确认一件事REF_CLK 引脚上到底有没有 50MHz 的方波幅度有没有达到对方芯片的高电平阈值。我习惯用示波器直接看 KSZ8863RLL 的 REF_CLK 引脚和 STM32F746 的 PA1 引脚两个点都量一遍确认不是“断线”或“虚焊”。很多情况下代码和寄存器是好的问题就出在 PCB 走线或焊接上。2.3 MDC/MDIO 上拉电阻接线前能多看一眼就多看一眼“RMII 接口 MDC 需要接上拉电阻吗”这个问题我在论坛上见过不止一次。实际答案取决于接口类型RMII 本身的数据信号是推挽或者伪差分逻辑一般不需要上拉但管理接口 MDC/MDIO 是 SMI 总线MDIO 是双向开漏信号必须上拉。MDC 是主控输出的时钟线理论上推挽输出就能工作但很多 PHY 和交换芯片的参考设计里照样会给 MDC 加上拉电阻。KSZ8863RLL 的 MDIO 引脚如果不上拉最典型的故障是SMI 读操作偶尔成功、偶尔失败或者读出来全是 0xFFFF再或者写寄存器没反应。因为 MDIO 是开漏结构没有外部上拉就无法主动拉高而大部分内部上拉的阻值偏大加上 PCB 寄生电容后信号上升沿非常缓慢时序不满足就会导致通信不稳定。MDC 需要不需要上拉我的习惯是如果参考设计里画了就加反正 10kΩ 上拉到 3.3V 不会有什么副作用如果没画可以先不加因为 MDC 是推挽驱动一般也能正常工作。真正要注意的是 MDC 和 MDIO 上拉电压必须和 KSZ8863RLL 的 IO 电源域一致通常是 3.3V。如果上拉到 5V轻则漏电重则烧毁引脚。这里还要提醒一句MDC/MDIO 走线尽量短不要和 RMII 数据线靠太近避免时钟边沿耦合干扰数据。3. STM32F746 侧初始化从 CubeMX 到复用引脚3.1 使能 ETH 外设和选择 RMII 模式STM32F746 内部以太网外设可以工作在 MII 或 RMII 模式CubeMX 里对应 ETH 外设的 Mode 选项。选择 RMII 后CubeMX 会自动分配默认引脚并出现在 GPIO 配置里。这里有个坑CubeMX 默认生成的 GPIO 初始化可能在 ETH 外设使能之前或之后顺序不对可能导致引脚复用冲突。我在项目里习惯手动检查HAL_ETH_Init之后是否有HAL_ETH_Start或HAL_ETH_Start_IT以及底层的HAL_ETH_MspInit是否正确配置了对应 GPIO 的 AF 模式。很多“RMII 起不来”的问题在调试早期就出现是因为用户只初始化了 ETH 外设但忘记把 RMII 引脚切换到 AF 复用模式。GPIO 保持默认输入状态信号根本进不了 MAC。这里给一个快速检查方法用逻辑分析仪或示波器看 STM32F746 的 TX_EN 引脚默认 PG11如果以太网驱动初始化完成后哪怕没有发包该引脚也应当保持一个稳定的低电平如果它是浮空状态或者来回跳说明 GPIO 复用配置可能出了问题。3.2 时钟源MCO1 输出还是外部 50MHz 输入STM32F746 的 RMII 接口需要外部提供 50MHz 参考时钟这是和 MII 一个很大的差别。MII 模式下 MAC 和 PHY 各自提供 TX_CLK/RX_CLK但 RMII 模式下 REF_CLK 必须由外部供给内部 PLL 不能直接作为 RMII 参考时钟。CubeMX 里通常在 RCC 配置的 MCO 部分选择 MCO1 或 MCO2并设置输出频率为 50MHz。MCO 输出 50MHz 时需要注意STM32F746 的 MCO 输出能力有限如果直接驱动 KSZ8863RLL 的 REF_CLK 引脚且走线较长信号质量会下降。更合理的做法是让 MCO 输出 50MHz 给 KSZ8863RLL 的 REF_CLK同时也接到 PA1但这个“接到 PA1”如果是通过 PCB 飞线完成的一定要保证反射尽量小。如果板子上有终端电阻或串联 33Ω 电阻的位置尽量补上避免振铃。如果 KSZ8863RLL 本身能输出 50MHz REF_CLK则可以反着来让 KSZ8863RLL 产生时钟给 STM32F746。这种方式的优势是时钟源靠近交换芯片而且 RMII 时钟抖动控制得比较好。缺点是需要确认 KSZ8863RLL 的寄存器配置把端口 3 的接口时钟方向设为输出否则该引脚可能一直保持高阻STM32 侧读到的是噪声。3.3 GPIO 引脚的连接关系与常见错误STM32F746 的 RMII 接口默认引脚和前面提到的一致但某些封装或板级设计会允许重映射。我建议对照参考手册的 AF 表确认一遍不要只凭记忆。实际项目里最常见的错误是把 CRS_DV 和 RXD0 的顺序弄反或者把 TX_EN 接到了 TXD 上。这类接线错误用万用表一眼就能查出来但如果不画表格就很容易忽略。以下是我在项目里使用的 RMII 接线对照表读者可以参考STM32F746 引脚RMII 信号名KSZ8863RLL Port 3 对应信号方向PA1REF_CLKREF_CLK双向/输入PA2MDIOMDIO双向PC1MDCMDC输出PA7CRS_DVCRS_DV输入PC4RXD0RXD0输入PC5RXD1RXD1输入PG11TX_ENTX_EN输出PG13TXD0TXD0输出PG14TXD1TXD1输出需要特别说明KSZ8863RLL 的信号方向是以交换芯片自身的 MAC 接口为视角的。从 STM32 的角度看TXD0/TXD1/TX_EN 是输出RXD0/RXD1/CRS_DV 是输入所以 STM32F746 的 TX 引脚一定要接到 KSZ8863RLL 的 TX 引脚而不是 RX。这个“方向一致”看起来简单但很多新手第一次接 RMII 时会下意识把 TX 和 RX 交叉导致环路不通。4. KSZ8863RLL 侧寄存器配置和端口角色4.1 Port 3 的控制寄存器与 MII/RMII 选择KSZ8863RLL 的 Port 3 默认工作模式并不一定是 RMII有些型号默认是 MII。如果数据手册里没有明确说明默认值必须先通过寄存器把端口 3 的接口模式改成 RMII。这个配置一般在端口 3 控制寄存器里具体 bit 位会因版本不同有细微差异强烈建议以当前批次芯片的数据手册为准。我遇到过拿着旧版本数据手册配新芯片的情况bit 定义对不上浪费了大半天。如果引脚支持外部上下拉配置也可以通过板级电阻选通 RMII 模式。但大多数情况下KMII 系列的端口 3 模式是通过 SMI 寄存器控制而不是纯引脚配置。也就是说在主控代码里访问 KSZ8863RLL 全局寄存器的能力至关重要。如果 SMI 配置不正确连“切换 RMII 模式”这个动作都做不了。配置完模式后还要检查 Port 3 是否被使能。某些交换芯片上电后默认某些端口处于隔离状态或者只接收不转发。此时虽然 RMII 接口的物理信号是通的但数据包进不了交换引擎表现出来就是“Link 正常但 Ping 不通”。这个坑非常隐蔽因为示波器能看到帧驱动也显示 Link Up但就是无法通信。4.2 SMI 访问 PHY 与交换机全局寄存器MDC/MDIO 接口在 KSZ8863RLL 上既能访问 Port 1 和 Port 2 的 PHY 寄存器也能访问交换机全局寄存器。常见的 PHY 寄存器地址 0 是控制寄存器地址 1 是状态寄存器。调试时我的顺序是先读 Port 1 的 PHY 状态寄存器确认 SMI 链路本身正常。如果 Port 1 的 PHY 能读到有效值说明 MDC/MDIO 的物理层和中控基本没问题。接着再访问交换机全局寄存器把端口 3 的控制值读出来确认当前模式。如果读出来全是 0xFFFF基本可以判断 MDIO 上拉缺失或 MDC 时序异常如果读出来全 0可能是 KSZ8863RLL 没有正常上电或 SMI 片选/使能配置不对。用 STM32 的 HAL 库读写 PHY 寄存器时要注意HAL_ETH_ReadPHYRegister和HAL_ETH_WritePHYRegister的参数含义。PHY 地址并不是永远用 0x00 或 0x01不同交换芯片会定义不同的 PHY 地址映射。我建议在驱动的初始化阶段轮询扫描 0x00 到 0x1F 范围打印每个地址读到的寄存器 0x02 值这样能快速定位有效 PHY 地址。4.3 用环回方式验证数据通路如果 RMII 接口的 Link 状态一直起不来光看寄存器配置往往不够还需要验证“数据是否真的能从这个口进出”。一个非常实用的手段是利用 KSZ8863RLL 的端口转发和环回功能。在调试阶段可以把 Port 1 收到的帧强制转发给 Port 3再从 Port 3 发回 Port 1这样就能用一台 PC 直观地看到数据是否打通。具体做法是把 PC 接到 Port 1给 Port 1 配置一个静态 MAC 表项目标 MAC 指向 Port 3或者干脆配置成广播风暴让 Port 1 的帧全部广播到其它端口。然后在 STM32F746 侧打开抓包或者查看接收中断如果 RMII 接口工作正常应该能收到这些广播帧。收不到就说明问题出在 RMII 信号链路或 Port 3 的转发配置上。这个测试的好处是可以把“PHY 物理层问题”和“交换芯片转发问题”分开。如果 Port 1 的 PC 本身能 Ping 通外部设备但 STM32F746 收不到广播帧问题基本确定在 Port 3 的 RMII 接口。如果 STM32F746 能收到广播帧但 PC 端 Ping 不通 STM32F746那问题就偏向 MAC 地址学习或 RMII 的发送方向而不是单纯 Link 问题。5. 现场调试实录从“没反应”到“Link Up”5.1 第一步复位和时钟波形遇到这种问题我先动手的地方永远是电源、复位、时钟这三大件不确认后面全是白忙。KSZ8863RLL 的复位引脚必须保证足够的低电平时间我一般控制 10ms 以上然后拉高。如果复位时间太短芯片内部寄存器可能处于不确定状态SMI 访问会出现随机失败。确认复位没问题后用示波器量 REF_CLK。我习惯把示波器探头放在 KSZ8863RLL 的 REF_CLK 引脚上同时再量 STM32F746 的 PA1 引脚两个波形对比。如果一个有 50MHz 另一个没有说明中间链路断了或者方向配置错了。如果两边都有 50MHz再检查信号幅度是否达到 2.0V 以上有些板子上 REF_CLK 被分压到 1.8V 或者更低芯片根本识别不了。这里有一个容易被忽略的点有些万用表量 REF_CLK 时会发现平均电压大约是 2.5V会误以为信号正常。实际上方波可能是 3.3V 摆幅对称方波也可能是边缘极差的不规则波形。必须用示波器看占空比和上升沿。我遇到过占空比 30% 的 REF_CLKPHY 侧的时钟恢复电路勉强能工作但 RMII 接口就是吞包严重直到换了一颗有源晶振后才彻底解决。5.2 第二步MDC/MDIO 是否能访问到 PHY确认时钟没问题后我开始做 SMI 访问测试。先把 STM32F746 的 MDIO 引脚接一个 4.7kΩ 上拉到 3.3VMDC 引脚加一个 10kΩ 上拉到 3.3V然后写一个最简单的读寄存器函数读 Port 1 的 PHY 寄存器和交换机全局寄存器。如果读回的值有意义就说明 SMI 通信底层正常。很多人问 MDC 到底需不需要上拉我实测下来大多数情况下不加也能读但加了之后稳定性明显更好。尤其在 MDC 频率比较高、PCB 走线较长的时候MDC 边沿会产生振铃上拉电阻能够改善信号质量。我现在的工程习惯是MDC 和 MDIO 各放一个 10kΩ 上拉到 3.3V除非参考设计明确说不需要。如果 SMI 读不到有效值先检查 MDIO 是否有波形。正常工作时MDIO 在 MDC 上升沿附近会有一段高电平或低电平的数据。如果 MDIO 一直是高电平可能是上拉电阻把信号拉死了或者 KSZ8863RLL 的 SMI 功能没有使能。如果 MDIO 一直是低电平可能是 KSZ8863RLL 没有应答需要检查 PHY 地址对不对。5.3 第三步RX_DV 与 TX_EN 的时序观察当 Link 状态始终起不来时我还会把目光放到 RMII 的数据和控制信号上。给 KSZ8863RLL 的 Port 1 接一个活跃的网络设备比如插到一台正常上网的交换机上然后用示波器看 KSZ8863RLL 发给 STM32F746 的 CRS_DV 信号。正常情况下当 Port 1 收到网络数据时CRS_DV 会呈现高电平脉冲RXD0/RXD1 也会随之变化。如果 CRS_DV 一直为低说明 KSZ8863RLL 根本没把 Port 1 收到的数据转到 Port 3要么是端口转发配置不对要么是 Port 3 的 RMII 发送路径有问题。如果 CRS_DV 有脉冲但时常很短而且 RXD0/RXD1 没有对应数据那问题可能在时钟同步上——REF_CLK 和 RX 数据相位不对导致 MAC 采样失败。反过来从 STM32F746 向外发包时用示波器看 TX_EN 引脚。TX_EN 拉高期间TXD0/TXD1 应该有对应的数据变化。如果 TX_EN 正常但 KSZ8863RLL 不把数据从 Port 1 发出去那就需要查交换机的转发学习表或者检查 Port 3 是否被错误地配置成隔离模式。5.4 第四步寄存器回读和链路状态判断最后一步我会在调试串口上打印几个关键寄存器的值。打印的内容包括PHY 状态寄存器、端口 3 控制寄存器、端口 1 控制寄存器、全局中断状态寄存器等。通过这些寄存器能判断芯片是否真的识别到了外部链路以及端口 3 是否处于允许收发的状态。这里要特别注意有些交换芯片的“链路状态”是针对物理层 PHY 口的而 Port 3 作为数字接口可能没有传统意义的 Link 寄存器。如果你在 Port 3 上读不到类似 PHY 状态的寄存器不要慌这不是芯片坏了而是它本来就没有这种寄存器。要判断 Port 3 是否“通”主要看端口使能、速度双工配置和转发标志。我在调试中经常用一个小技巧写一个直接把 Port 3 的 RX 和 Port 1 的 TX 短接的测试模式也就是在交换机内部做一个二端口转发测试。这样做即使不依赖 STM32F746 的协议栈也能判断交换芯片本身的数据通路是否正常。如果测试模式下 Port 1 的 PC 依然 Ping 不通那说明 KSZ8863RLL 自身的转发逻辑或端口配置肯定有问题再往 RMII 信号上使劲就是浪费时间。6. 常见问题与排查技巧实录6.1 快速速查表现象、原因和对策这里我整理了一个速查表基本涵盖了我遇到和听到的常见情况能少走不少弯路。故障现象可能原因快速对策REF_CLK 无波形MCO 配置错误/晶振没起振先测 KSZ8863RLL 和 STM32 两个 REF_CLK 引脚REF_CLK 频率只有 25MHz倍频寄存器没配置查 KSZ8863RLL 时钟方向/倍频设置MDIO 读回全 0xFFFFMDIO 上拉缺失或 PHY 地址错误加 4.7kΩ 上拉扫描 0x00~0x1F 地址MDIO 读回全 0x0000KSZ8863RLL 未上电或复位异常检查复位时序和电源电压寄存器能读但 RMII Link 不起来Port 3 模式配置为 MII 而非 RMII读端口 3 控制寄存器确认模式位Port1 Link 正常但 CPU 收不到包VLAN/端口隔离配置问题配置端口 VLAN 或强制广播测试偶尔能收到包但极不稳定REF_CLK 抖动大/走线过长改用有源晶振优化 PCB 走线TX_EN 有波形但外部设备不通KSZ8863RLL 转发学习表问题清空 MAC 表配置静态转发6.2 几个容易忽略的细节和我的排查习惯最后分享几个我在实操中总结出来的经验。第一个是上电顺序。KSZ8863RLL 的 IO 电源和核心电源如果分组控制先给核心电源还是先给 IO 电源会影响芯片内部逻辑的初始化状态。我遇到过先给 IO 后给核心时SMI 访问奇偶校验总出错反过来就正常。这个细节在数据手册的电源要求章节里有建议但很多人做硬件时没注意。第二个是 RMII 接口的 RX 路径时序。RMII 不像 MII 有独立的 RX_CLK它只有 REF_CLK 一个时钟数据在 REF_CLK 的上升沿被采样。如果 KSZ8863RLL 输出的 RXD 数据和 STM32F746 的采样时钟沿对齐不好就会偶发采样错误。很多板子最终是通过加长或缩短 RXD 走线来调整时序但这个调整不能靠肉眼猜最好用示波器同时看 REF_CLK 和 RXD 的建立时间。第三个是关于“RMII 和 MII 之间切换”的坑。我发现很多工程师把 RMII 当成 MII 的简单减线版实际上两者的寄存器配置、时钟频率、甚至信号极性都可能不同。如果你的板子同时兼容 MII 和 RMII一定要在硬件设计阶段把接口模式的选择引脚或寄存器默认值确认清楚否则等软件跑起来再改往往牵一发动全身。第四个经验是在调试前期千万不要一次性初始化太多功能。我只开 ETH 外设、串口打印和定时器先把 RMII 最基本的数据通路打通然后再加协议栈、任务调度、操作系统。很多“完全没反应”的问题其实是任务调度把以太网中断饿死了或者是驱动初始化时访问了未使能的外设导致死循环。简化到最小系统问题会清晰很多。我在实际调试中最深的一点体会是RMII 链路问题百分之八十出在“时钟”和“配置一致性”上。时钟没问题、SMI 能通、模式一致剩下的往往只是接线或者寄存器掩码的小错误。如果你能从头到尾按照“复位时钟、SMI 访问、信号波形、寄存器回读”的顺序查一遍绝大多数问题都能在几小时内定位而不是靠一遍遍编译刷机去碰运气。
返回列表