简介:KSZ8863MLLI 数据手册(PDF)面向嵌入式硬件与网络开发工程师,尤其是使用 STM32 等 MCU 扩展以太网接口、需要为三端口交换机做原理图设计与驱动调试的读者。文档完整覆盖该芯片的三口 10/100 以太网交换能力:三 MAC 两 PHY、1k MAC 地址查找表与非阻塞存储转发结构,IEEE 802.1q VLAN(最多 16 组)、802.1p/q 标签插入与删除、入方向与出方向可编程限速、广播风暴抑制以及 802.1d 快速生成树等交换特性;同时说明 SMI、MIIM、SPI 与 I2C 等寄存器访问方式,以及 QoS/CoS 优先级重映射、IGMP Snooping、MAC 过滤、端口镜像与 MIB 统计、LinkMD 电缆诊断和低功耗设计等内容。压缩包仅含 1 个 PDF 文件,约 1.32MB,便于检索,可作为寄存器配置与硬件设计的案头参考。该手册已有 1204 人学习下载,适合在选型评估、PCB 设计和底层驱动开发阶段查阅。
1. KSZ8863MLL 数据手册值不值得啃:三口交换芯片的选型边界
某开发者拿着一块 STM32 板子要接两个网口,评审时被问了一句「你的 MAC 够吗」,才发现单 MAC 的 MCU 撑不起双网口转发。翻到的就是 KSZ8863MLL 数据手册——48 脚 LQFP 封装的集成三口 10/100 管理型交换机,内部三个 MAC、两个 PHY,第三个端口以 MII 或 RMII 形式挂到 MCU。它解决的正是「MCU 只有一个以太网外设却要接两条网线」这类问题,同时把 VLAN、QoS、风暴抑制、端口镜像这些通常要外挂芯片才有的能力塞进 7mm×7mm 的封装里。适合工业控制、楼宇网关、视频前端这类端口不多但对管理性有要求的场景;只想做傻瓜 Hub 的,用不上它一半功能。
2. 端口与引脚:48 脚 LQFP 上每一根线都得先定死
这块板子最容易翻车的地方不在软件,在原理图。KSZ8863 的引脚复用密度很高,好几根脚既要当 PHY 的 RX 数据线用,又要在复位期间被采样成配置位,画图时随手加个上拉,可能就把端口 2 的自协商给关了。这一章按「端口分工 → 时钟复位 → 变压器走线」的顺序把硬件侧的边界讲清楚,后面调软件才知道该怀疑谁。
2.1 三个端口的分工,以及 MLL/RLL/FLL 三个型号怎么挑
先纠正一个常见误解:标题写「3-port switch」,很多人第一反应是三个 RJ45 网口。实际上端口 1 和端口 2 才是带 PHY 的 10/100BASE-T/TX 收发器,各自带 HP Auto MDI-X,能自动识别直通线和交叉线,也能通过寄存器关掉这个功能;端口 3 是纯 MAC,没有 PHY,必须外接到 CPU 的 MAC 上。所以整颗芯片对外是「两个网口 + 一条到处理器的内部总线」,做产品时真正对外的网口数是 2。
三个 MAC 挂在同一个非阻塞交换结构上,配 1K 容量的 MAC 地址查找表,存储转发架构。非阻塞的意思是三个端口同时全速收发时内部不会互相堵,这对「两个网口满速对打、同时 CPU 还要抓包」的场景很关键。流控方面,全双工走 IEEE 802.3x PAUSE 帧,还能强制打开;半双工走背压。端口 1 和端口 2 各有独立的 MAC 地址,支持自地址过滤,CPU 侧做单播/多播区分时不用全靠软件过滤。
三个型号的差别就在端口 3 和端口 2 的形态上,选型时先看 CPU 侧有什么接口:
| 型号 | 端口 1 | 端口 2 | 端口 3 | 典型搭配 |
|---|---|---|---|---|
| KSZ8863MLL | 10/100BASE-T/TX PHY | 10/100BASE-T/TX PHY | MII(可配 MAC 模式或 PHY 模式) | MCU 带标准 MII |
| KSZ8863RLL | 10/100BASE-T/TX PHY | 10/100BASE-T/TX PHY | RMII | MCU 只有 RMII,省引脚 |
| KSZ8863FLL | 100BASE-FX | 10/100BASE-T/TX PHY | MII | 一路光纤上联 + 一路铜缆 |
MII 和 RMII 的取舍不只是引脚数。MII 的收发各 4 位数据加各自的时钟和有效信号,走线多但时序宽松;RMII 把数据位砍到 2 位,时钟统一到 50MHz,引脚省一半,代价是对参考时钟的抖动和走线等长更敏感。RLL 这颗能把 50MHz 参考时钟从 REFCLKO_3 引脚输出给 CPU,省掉板上第二个晶振,这是它相对 MLL 最实际的卖点。标题里的 KSZ8863MLLI 对应的是工业温度等级那一档,-40°C 到 +85°C,寄存器行为与商业级一致,软件不用改。
还有一层容易忽略:端口 3 的 MII 可以工作在 MAC 模式,也可以工作在 PHY 模式。交换机当 PHY 用时,SMTXC3 是输出,时钟由交换机给 CPU;交换机当 MAC 用时,SMTXC3 变成输入,时钟由 CPU 给交换机。这个方向搞反了,链路状态可能看起来正常,但一个包都过不去,而且不会有任何报错。我一般会在原理图评审时把这一根线的方向用红笔标出来,让硬件同事确认一遍。
2.2 时钟、复位与 strapping:上电前必须锁死的几根脚
数据手册里有一句很容易被跳过的注释:时钟必须在复位电压拉高之前施加到 X1 引脚。这句话是血泪经验换来的——如果晶振起振慢于复位释放,芯片内部状态机会锁在一个未定义的状态,表现是 SPI 能读到 Chip ID,但两个 PHY 完全不工作,插网线灯都不闪。排查时盯着示波器看 RSTN 上升沿和 X1 第一个完整周期谁先到,基本一眼就能定位。
时钟源方面,X1/X2 接 25MHz 或 50MHz 的晶振或振荡器,精度要求 ±50ppm。用晶振时 X1、X2 都接;用有源振荡器时 X1 接时钟输出、X2 悬空,而且这个振荡器要能耐受 3.3V。RLL 型号在 RMII 模式下对 X1 的频率有要求,靠 SMTXD32 这根脚在上电时被采样来决定:上拉表示 X1 接 25MHz(默认),下拉表示 X1 接 50MHz。这个选择必须和板上实际贴的晶振一致,贴了 25MHz 却把脚拉低,RMII 侧就永远起不来。
复位是 RSTN,低有效。数据手册第 8 章专门讲了复位电路,核心要求是复位低电平要维持足够长,让内部 LDO 和带隙基准稳定下来。我一般用一颗复位监控芯片而不是简单的 RC,RC 在低温下电容容量漂移,容易出现「实验室好的、冬天现场批量重启」的情况。
strapping 是这块芯片最容易踩雷的部分。一批引脚在 RSTN 上升沿被采样,决定端口 1/2 的默认双工、速率、自协商开关和流控策略,采样完这些脚立刻切回正常功能。问题在于它们同时是 PHY 的 RX 数据线,外部上下拉电阻会挂在高速信号上:
| 引脚 | 复用功能 | 上拉(PU) | 下拉(PD) |
|---|---|---|---|
| 25 SMRXDV3 | P1DPX | 自协商失败时默认全双工 | 默认半双工 |
| 26 SMRXD33 | P2ANEN | 使能端口 2 自协商 | 禁止自协商 |
| 27 SMRXD32 | P2SPD | 强制 100BASE-T | 强制 10BASE-T |
| 28 SMRXD31 | P2DPX | 全双工 | 半双工 |
| 29 SMRXD30 | P2FFC | 强制开启流控 | 按自协商结果 |
| 17 SMTXD33 | EN_REFCLKO_3(RLL) | 输出 50MHz 参考时钟 | 不输出 |
| 24 SMTXER3 | MII_LINK_3 | — | 置 1 表示端口 3 无链路并启用 bypass |
阻值选择上有讲究。太小会拖累 RX 信号眼图,太大在潮湿环境下漏电流会影响采样电平,常用做法是 4.7k 到 10k,并且把上下拉放在靠近芯片引脚的位置,不要放在变压器那一侧。更稳妥的做法是在 strap 脚和 PHY 差分线之间串一颗小电阻做隔离,采样期间电阻不影响电平,正常工作时又不至于把信号压死。
还有两个模拟脚不能忘。ISET 用一颗 11.8kΩ、1% 精度的电阻下拉到地,设定 PHY 的发送电流。这颗电阻贴成 10k 或者用 5% 精度,短距离、常温下大概率看不出问题,一旦线缆拉长到 80 米以上或者低温启动,就会出现链路能 up 但丢包率异常的情况。VDDCO 是内部 1.8V LDO 的输出,VDDA_1.8 和 VDDC 都从它取电,这个脚必须外接足够容量的去耦电容,绝对不能从外部往里灌 1.8V。
2.3 PHY 侧走线、变压器选型与 LinkMD 电缆诊断
隔离变压器的选型在数据手册第 9 章有单独一节,核心参数是 1:1 匝比、支持 10/100BASE-TX、隔离耐压满足产品安规等级、带共模扼流圈。这里有个常被抄错的细节:中心抽头的接法跟 PHY 的驱动类型强相关,不同厂商、不同系列的 PHY 接法不一样,照抄隔壁项目的参考电路是典型的翻车来源。稳妥做法是直接翻到第 9 节的推荐电路,按上面的偏置和去耦网络一比一还原。
差分对走线方面,RX/TX 各自按 100Ω 差分阻抗控制,对内等长建议控制在 5mil 以内,对间不要长距离平行走,避免串扰。变压器到连接器之间要留出足够的隔离间距,ESD 器件放在连接器侧而不是芯片侧。整块板上 25MHz 时钟、SPI 时钟、RMII 的 50MHz 参考时钟都是潜在的干扰源,布局时让它们离差分对远一点,尤其是 50MHz 那根,它是方波,谐波能铺得很宽。
LinkMD 是基于 TDR 的电缆诊断功能,能测线缆长度和故障位置。用法是在 PHY 的扩展寄存器里触发一次诊断,等它跑完再读回结果,按手册给的换算系数折成米。这个功能在产线测试和现场排障时特别省事:客户报「网线插上不通」,你可以先跑一次 LinkMD,读回来的距离如果是 3 米,说明是连接器附近的问题;如果是 0 米或者溢出,说明是开路或短路;如果读回来的值在正常范围内但链路还是起不来,那问题大概率在自协商或者对端设备上,不用再折腾线。
3. 寄存器访问:SPI、I2C、MIIM、SMI 四条路怎么选
软件侧的第一件事是把「能读能写」这条路打通,否则后面配 VLAN、调 QoS 全是空中楼阁。KSZ8863 提供了四条访问路径,覆盖的场景完全不同,选错了不是不能跑,是会在某个深夜让你怀疑人生。这一章把四条路的边界讲清楚,然后给两段能直接抄的代码。
3.1 四种管理接口的适用场景对比
串行管理接口 SMI 和 MII 管理接口 MIIM 是两套东西,命名上容易混。SMI 是两线制的串行接口,能访问芯片内部全部寄存器;MIIM 是标准的 MDC/MDIO 两线接口,主要面向 PHY 寄存器,帧格式固定 32 位。高速 SPI 和 I2C 则是访问全部内部寄存器的主通道,适合 CPU 侧已经有现成控制器、不想再占两根专用脚的情况。
| 接口 | 引脚 | 访问范围 | 速度 | 适用场景 |
|---|---|---|---|---|
| SPI | SCL_MDC、SDA_MDIO、SPIQ、SPIS | 全部内部寄存器 | 最高,适合批量初始化 | CPU 有 SPI 且速率要求高 |
| I2C | SCL_MDC、SDA_MDIO | 全部内部寄存器 | 中等,受总线电容限制 | CPU 引脚紧张,板上有现成 I2C |
| MIIM | MDC、MDIO | PHY 标准寄存器 0~31 | 慢,每帧 32 位 | 只想读链路状态、自协商结果 |
| SMI | 复用 MIIM 引脚 | 全部内部寄存器 | 慢 | 无 SPI/I2C 时的兜底 |
实际项目里最常见的是「SPI 做初始化 + MIIM 做运行时状态读取」的组合。启动时用 SPI 把几十个寄存器一口气刷完,运行期间只需要周期性读 PHY 的状态寄存器看链路有没有掉,这时候用 MIIM 更省事,很多 MCU 的以太网外设自带 MIIM 控制器,连驱动都不用写。
如果板上还要接 EEPROM 做无管理模式的配置,那是另一条路径:上电时芯片从 EEPROM 自动加载一部分寄存器初值,适合完全不需要 CPU 参与的纯硬件交换机产品。这条路我只在成本极度敏感的方案里见过,调试体验很差,因为配置藏在 EEPROM 里,改一次要重新烧一次。
I2C 模式下的从机地址是固定的 7 位地址,写帧和读帧的末位不同。第一版调试时务必先回读 Chip ID 确认通信正常,不要直接往下写配置寄存器——地址错了但总线上有应答的情况是存在的,因为可能撞上了板上另一颗器件。SPI 模式则要注意片选 SPIS 的时序,片选拉低到第一个时钟沿之间要有足够的建立时间,很多 MCU 的硬件 SPI 在这个参数上卡得很紧,初期建议先降到 1MHz 调通再往上提。
3.2 用 SPI 批量配置:时序与代码骨架
SPI 从机模式的帧结构是「命令字节 + 数据」。命令字节的最高位区分读写,次高位区分单字节还是四字节突发,低 6 位是寄存器地址。四字节突发模式在刷连续的寄存器块时特别有用,一次片选能写四个字节,初始化时间能砍掉一大半。
/* KSZ8863 SPI 单字节访问 * 命令字节: bit7 = 1 读 / 0 写 * bit6 = 1 四字节突发 / 0 单字节 * bit5:0 = 寄存器地址 * SPI 参数: 模式 0 (CPOL=0, CPHA=0), MSB first */ #define KSZ_CMD_WR(addr) ((uint8_t)((addr) & 0x3F)) #define KSZ_CMD_RD(addr) ((uint8_t)(0x80 | ((addr) & 0x3F))) static void ksz_cs_low(void) { HAL_GPIO_WritePin(KSZ_CS_PORT, KSZ_CS_PIN, GPIO_PIN_RESET); } static void ksz_cs_high(void) { HAL_GPIO_WritePin(KSZ_CS_PORT, KSZ_CS_PIN, GPIO_PIN_SET); } uint8_t ksz_reg_write(uint8_t addr, uint8_t val) { uint8_t tx[2] = { KSZ_CMD_WR(addr), val }; ksz_cs_low(); if (HAL_SPI_Transmit(&hspi1, tx, 2, 10) != HAL_OK) { ksz_cs_high(); return 1; /* 超时返回非 0,调用方决定是否重试 */ } ksz_cs_high(); return 0; } uint8_t ksz_reg_read(uint8_t addr, uint8_t *out) { uint8_t cmd = KSZ_CMD_RD(addr); uint8_t dummy = 0; ksz_cs_low(); if (HAL_SPI_Transmit(&hspi1, &cmd, 1, 10) != HAL_OK) { ksz_cs_high(); return 1; } /* 读操作需要一个 dummy 周期,数据在第二个字节回来 */ if (HAL_SPI_Receive(&hspi1, &dummy, 1, 10) != HAL_OK) { ksz_cs_high(); return 1; } if (HAL_SPI_Receive(&hspi1, out, 1, 10) != HAL_OK) { ksz_cs_high(); return 1; } ksz_cs_high(); return 0; }这段代码的关键点在三个地方。片选的手动控制必须包住整帧,不能靠 SPI 外设的硬件片选,因为读操作中间有一个 dummy 周期,硬件片选可能会在字节之间抬起来。超时时间给了 10ms,看起来很长,但调试阶段宁可慢也别卡死,等跑通之后再压到 1ms 量级。读操作的 dummy 周期是最容易漏的,漏了的表现是读回来的值永远比预期晚一个字节,看起来像地址错位,实际上是时序少了一拍。
四字节突发模式在初始化阶段值得单独写一个函数。把要刷的寄存器按地址排序,连续的一段用突发写一次性发出去,能显著缩短上电到链路 up 的时间。但要注意突发写不能跨芯片内部的分页边界,跨页时硬件行为可能不符合预期,稳妥做法是在地址不连续的地方断开,重新拉一次片选。
调试阶段我一般会先做一次全寄存器回读校验:写一批已知值,再逐个读回来比对。这一步能同时验证地址线、数据线和片选时序,比单点读一个 Chip ID 靠谱得多。如果某个地址读回来总是错一位,基本可以确定是 SPI 模式配错了,检查 CPOL/CPHA。
3.3 MIIM 读 PHY 寄存器的时序坑
MIIM 的帧格式是标准的 32 位:前导码、起始位、操作码、5 位 PHY 地址、5 位寄存器地址、2 位转向、16 位数据。这套格式是从 IEEE 802.3 继承下来的,几乎所有带以太网外设的 MCU 都直接支持,用起来比自己拼 SPI 帧省事。
/* 用 STM32 的 ETH 外设读 PHY 寄存器 * 注意 HAL 库的参数顺序是 (reg, phyaddr),和直觉相反 */ uint8_t phy_reg_read(uint16_t phyaddr, uint16_t reg, uint16_t *val) { uint32_t tmp = 0; uint32_t tick = HAL_GetTick(); while (HAL_ETH_ReadPHYRegister(&heth, reg, phyaddr, &tmp) != HAL_OK) { /* MDC 分频太慢或者 PHY 未上电时会一直失败,必须加超时 */ if (HAL_GetTick() - tick > 5) { return 1; } } *val = (uint16_t)(tmp & 0xFFFF); return 0; }第一个坑是参数顺序。HAL 库的函数原型里寄存器地址在前、PHY 地址在后,跟大部分人的阅读习惯相反,写反了不会报错,只会一直返回全 1 或者全 0。第二个坑是 MDC 频率,标准规定上限 2.5MHz,但实际能跑多快取决于板上 MDIO 的上拉阻值和总线电容,1.5k 到 2k 的上拉配 100pF 以内的负载比较稳。第三个坑是超时,PHY 还没出复位或者供电没稳的时候,MIIM 读会一直失败,没有超时保护的代码会卡在 while 里,现象是「上电后程序不跑了」,很容易误判成时钟问题。
PHY 地址不是固定的,取决于芯片的 strapping 配置。不知道地址的情况下,最省事的办法是从 0 到 31 扫一遍,读寄存器 2(PHY ID1),能读到一个非 0xFFFF 且非 0x0000 的值就说明找对了。扫的时候别只看第一个非全 1 的地址,因为总线上可能挂着别的器件。
读回来的值全是 0xFFFF,按这个顺序排查:先量 MDIO 上拉电阻有没有贴,再量 MDC 有没有波形,最后确认 PHY 是否已经上电——端口 1 和端口 2 的模拟电源 VDDA_3.3 是独立供电的,有人只给 VDDIO 供电就急着读 PHY,当然读不到。
4. VLAN、QoS、风暴抑制与镜像:把管理特性真正配上
能读写寄存器只是起点,真正让这颗芯片值钱的是它的管理特性。这一章按「VLAN → 优先级 → 风暴抑制与限速 → 端口镜像」的顺序,把每一块的配置逻辑和寄存器操作对应起来。前提是你已经翻到数据手册第 4 章的寄存器映射表,把每块功能的基址和位定义抄到自己的头文件里——直接把地址硬编码在业务代码里,后面换型号或者改配置会非常痛苦。
4.1 802.1q VLAN:16 组表项与端口 tag/untag
VLAN 支持最多 16 个组,VLAN ID 覆盖完整范围。表结构是每个表项包含一个 VID 和一个端口成员位图,成员位图决定哪几个端口属于这个 VLAN。端口 1、2、3 各占一位,三位的组合一共 8 种,但实际用到的就那么几种。
tag/untag 是按端口配的,这个粒度的意义在于:接终端的端口一般配成 untag,用户插上网线不需要懂 VLAN;接交换机或者 CPU 的端口配成 tag,保留 VID 信息给上层处理。IEEE 802.1p/q 的标签插入和剥离是在出口侧做的,也就是说帧从端口出去的那一瞬间才决定加不加标签,进来的时候不受影响。
配置顺序上我习惯先停转发再改表。寄存器里有一个全局的 START_SWITCH 位,清零之后交换结构停止转发但寄存器访问不受影响,改完 VLAN 表再置回去。这样做的好处是避免「改了前 8 项、后 8 项还是旧的」这种半张表生效的中间状态,在有多播和广播的环境里,半张表生效可能瞬间打出一波泛洪。
一个实际的配置例子:端口 1 接内网 PC,端口 2 接外网,端口 3 接 CPU。要做的隔离是 PC 和外网二层不通,但都能和 CPU 通信。做法是建两个 VLAN,VLAN 10 的成员是端口 1 和端口 3,VLAN 20 的成员是端口 2 和端口 3,端口 1 和端口 2 配 untag 并设 PVID 分别为 10 和 20,端口 3 配 tag。这样 CPU 侧收到的帧带 VLAN 标签,能区分来源;两个终端侧看不到标签,即插即用。
自地址过滤在这套配置下要注意。端口 1 和端口 2 各有独立 MAC 地址,开启自地址过滤后,目的 MAC 是端口 1 地址的帧不会被转发到端口 2。做上面那个隔离方案时,如果 CPU 侧发的帧目的地址写成端口 2 的地址,帧会被直接丢掉,看起来像 VLAN 没配对。排障时先确认 MAC 地址表,再看 VLAN 表。
4.2 802.1p 优先级重映射与四队列调度
QoS 这块支持三种分类依据:按端口、按 802.1p 的 3 位优先级字段、按 DiffServ(IPv4 的 ToS 或者 IPv6 的 Traffic Class)。三种可以叠加,最终映射到每个端口的 4 个优先级队列上。
802.1p 的重映射是按端口独立配的,这一点很实用。标准的 8 个优先级值(0 到 7)在工业场景里往往用不满,常见的做法是把 0/1 映射到队列 0(尽力而为),2/3 映射到队列 1,4/5 映射到队列 2,6/7 映射到队列 3。但如果某个端口接的是语音设备,可能希望把 PCP=5 单独提到最高队列,这时候就可以只改这个端口的映射表。
/* 802.1p 优先级(0~7)重映射到内部 4 级队列(0~3) * 每个 PCP 值占 2 bit,4 个 PCP 塞满一个字节 * REG_PCP_MAP_BASE 和每端口的偏移量按手册第 4 章寄存器映射表填 */ static const uint8_t pcp_to_queue[8] = { 0, 0, 1, 1, 2, 2, 3, 3 }; uint8_t ksz_set_pcp_map(uint8_t port) { uint8_t i, val = 0; if (port > 2) return 1; /* 只有 3 个端口 */ for (i = 0; i < 8; i++) { val |= (uint8_t)((pcp_to_queue[i] & 0x03) << ((i % 4) * 2)); if ((i % 4) == 3) { /* 每 4 个 PCP 写一个字节,第 0 个字节管 PCP0~3,第 1 个管 PCP4~7 */ uint8_t reg = REG_PCP_MAP_BASE + port * 2 + (i / 4); if (ksz_reg_write(reg, val) != 0) return 2; val = 0; } } return 0; }这段代码的逻辑很直白:把 8 个 PCP 值按每 4 个一组打包成两个字节,逐个写进对应端口的映射寄存器。参数 port 的取值范围是 0 到 2,对应端口 1 到端口 3。注意重映射表和队列调度算法是两回事,映射决定帧进哪个队列,调度决定队列之间怎么出队。队列调度有严格优先级和加权轮询两种模式,语音和视频混跑的场景建议用加权轮询,纯实时控制用严格优先级。
DiffServ 的配置比 802.1p 复杂一层,因为它要看 IP 头里的字段。IPv4 看 ToS 字节的高 6 位,IPv6 看 Traffic Class。这颗芯片支持 IPv4/IPv6 双栈的优先级分类,配置时需要同时打开对应的使能位,否则只认 802.1p 不认 IP 层。做三网融合类产品时这一点很关键,运营商下发的策略往往只标 DSCP 不打 802.1p 标签。
4.3 风暴抑制、速率限制与端口镜像
广播风暴保护支持全局和每端口两个层级,控制方式是按百分比。寄存器里填的是一个 8 位数值,含义是「该端口带宽的百分之几」,超过这个阈值的广播帧会被丢弃。典型配置是全局设一个兜底值(比如 5%),然后对上行端口单独放宽到 10%,因为上行端口本来就承载更多广播流量。
这里的百分比是按端口当前协商速率算的,不是按芯片总带宽。有一点要注意:10M 端口配 5% 和 100M 端口配 5%,绝对带宽差了十倍,做限速策略时要按端口的实际速率分别算。未知单播和组播的风暴抑制是分开配的,很多方案只开广播抑制,结果多播流量一上来照样把 CPU 打挂。
速率限制分 ingress 和 egress 两个方向,按端口独立配置。ingress 限速是在帧进入交换结构之前做,egress 是在出口队列做。两者的行为不一样:ingress 超限直接丢,egress 超限会在队列里堆积然后按调度策略丢。做流量整形类的需求时要用 egress,做防护类的需求用 ingress。粒度通常在几十 kbps 量级,具体换算关系在寄存器定义里有说明,配置时按目标带宽除以粒度得到寄存器值。
端口镜像可以把任意端口的 ingress 和/或 egress 流量复制到指定端口或 MII 接口。调试时非常好用,CPU 侧的端口 3 本身就能当镜像目的口,不需要额外占用一个物理网口。配置上的坑在于镜像目的端口不能同时参与正常转发,否则镜像流量会和业务流量混在一起,抓包时看到的是两份。另一个坑是带宽,镜像口如果只有 100M,而被镜像的端口是双工 100M 满速跑,镜像口一定会丢包,看到的现象是「抓包抓不全」,很容易误判成芯片丢包。
5. 避坑与排查:上电不亮、RMII 不通、tail tag 丢包
前面几章讲的是「应该怎么做」,这一章讲「做错了会看到什么」。下面五条都是我在不同项目里真实撞过的,按「现象 → 原因 → 解决」的结构写,方便对号入座。排查顺序建议从上往下,因为后面几条的现象可能被前面几条的问题掩盖。
5.1 上电与链路类问题
现象一:SPI 能读到 Chip ID,但两个网口的 link 灯全灭,插网线毫无反应。
这是最典型的上电时序问题。原因通常有三种:晶振起振时间慢于 RSTN 释放、RSTN 的低电平持续时间不够长导致内部 LDO 没稳、ISET 电阻贴错或者精度不够。数据手册明确要求时钟在复位电压拉高之前就施加到 X1,很多板子的复位电路是一颗简单的 RC,电容取值偏小的时候复位释放太快,晶振还在起振阶段。
解决办法是用示波器双通道同时看 X1 和 RSTN,把触发设在 RSTN 的上升沿,看 X1 的第一个完整周期是不是在触发点之前。如果 X1 滞后,把复位电容加大或者换成带延时的复位监控芯片。ISET 用万用表量对地电阻,必须在 11.8kΩ 附近,偏差超过 1% 就换掉。还有一种情况是 VDDA_3.3 和 VDDIO 的上电顺序有问题,VDDIO 先上、模拟电源后上,会导致 PHY 内部状态机锁死,表现和上面完全一样。
现象二:RMII 模式下 PHY 侧 link up、自协商 100M 全双工,但 CPU 侧一个包都收不到。
先怀疑参考时钟。RLL 型号的 REFCLKO_3 输出需要 SMTXD33 这根脚在上电时被上拉才使能,如果板上给的是下拉或者悬空,50MHz 参考时钟根本没有输出,CPU 侧的 RMII 接口拿不到时钟,自然收不到任何东西。用示波器量 17 脚,应该有干净的 50MHz 方波,幅度接近 VDDIO。
第二个怀疑对象是 SMTXC3/REFCLKI_3 这根线的方向。RLL 在 RMII 模式下这根脚是参考时钟输入,如果板上把它当输出接了(照着 MLL 的参考电路抄的),时钟冲突会导致两边都不工作。第三个怀疑对象是 X1 的频率选择,18 脚在下拉状态下要求 X1 输入 50MHz,如果板上贴的是 25MHz 晶振又没改 strap,PLL 锁不住,输出时钟频率会跑偏。
排查顺序建议是:先量 50MHz 输出有没有,再量 X1 起振频率对不对,最后确认 SMTXC3 的方向。三步走完基本能定位,不用反复改代码。
5.2 数据
本文还有配套的精品资源,点击获取