4. MCX以太网驱动与底层初始化

MCX 系列 MCU 的以太网外设(ENET)并不是一个“寄存器一写就能发包”的简单模块,它由 MAC 控制器、DMA 引擎、描述符环、收发缓冲区以及外部 PHY 共同构成一条完整的数据通路。理解这条通路的组织方式,是后续做工业以太网协议栈移植、实时性调优和故障排查的基础。本节围绕 ENET 驱动架构、描述符环、缓冲区管理、MAC 地址配置与 PHY 寄存器读写五个关键点展开,并给出可直接参考的初始化顺序与参数示例。

一、ENET 驱动架构:三层分工

从软件视角看,MCX 的 ENET 驱动通常分为三层。最底层是寄存器访问层,直接操作 ENET 的 MAC 配置寄存器、DMA 工作模式寄存器、描述符基址寄存器以及 MDIO 接口寄存器;中间层是描述符与缓冲区管理层,负责维护发送环和接收环、分配数据缓冲区、处理所有权标志;最上层是面向协议栈的适配层,向上提供标准的收发接口,把描述符状态翻译成“一帧已到达”或“一帧已发出”的事件。

这三层的边界很重要:寄存器层只关心“写哪个地址、写什么值”,描述符层只关心“环指针走到哪、缓冲区归谁”,适配层只关心“帧的边界和长度”。把三者混在一起写,是初学者最常见的结构性问题,会导致中断处理里塞满寄存器操作,难以维护。

MCX ENET 驱动分层与数据通路 协议栈适配层 发送请求 / 接收回调 / 链路状态通知 / 统计计数 描述符与缓冲区管理层 发送描述符环 TDES own / 长度 / 状态 接收描述符环 RDES own / 长度 / 错误位 缓冲区池 对齐 / 大小 / 回收 寄存器访问层 MAC 配置 · DMA 模式 · 描述符基址 · MDIO 控制/数据 · 中断使能 ENET MAC + DMA 引擎 RMII / MII 接口 外部 PHY MDIO 管理 · 差分线收发 MDIO

二、描述符环:ENET 的“传送带”

ENET 的收发不靠 CPU 逐字节搬运,而是靠 DMA 按描述符环自动搬运。每个描述符是一小块固定格式的内存结构,典型包含:缓冲区地址、数据长度、状态与控制字段。其中最关键的是 own 位——它表示这个描述符当前归谁使用。own=1 表示归 DMA(硬件)所有,own=0 表示归 CPU 所有。CPU 和 DMA 通过翻转 own 位来“交接”描述符,这是整个驱动最核心的同步机制。

发送时,CPU 把待发帧放入缓冲区,填写长度,把 own 置 1,然后触发发送;DMA 取走数据、发到 MAC,完成后把 own 清 0 并置“发送完成”状态位。接收时相反:驱动预先准备好一批 own=1 的空描述符,DMA 收到帧后填入数据、写长度、清 own,CPU 在中断或轮询中发现 own=0 即表示有帧可取。

描述符环的长度通常取 2 的幂,例如发送环 8 个、接收环 16 个,便于用掩码做回绕。环的基址必须按 ENET 要求对齐(常见为 16 字节或更高),否则 DMA 可能取到错误描述符。

三、缓冲区管理:大小、对齐与回收

缓冲区大小要兼顾效率和内存占用。工业以太网常见帧长在 64~1518 字节之间,若考虑 VLAN 标签和部分场景的巨帧,可把接收缓冲区设为 1536 或 2048 字节。缓冲区地址建议按 4 字节或更高对齐,避免非对齐访问带来的额外开销。

缓冲区管理最容易出问题的是“回收”。接收路径上,CPU 处理完一帧后必须把描述符重新置 own=1 并挂回环中,否则接收环会逐渐耗尽,表现为“收着收着就不收了”。发送路径上,缓冲区不能在 DMA 完成前被复用或释放,否则会发出错帧。一个稳妥的做法是:为每个描述符维护一个缓冲区指针数组,发送完成中断里按索引回收,接收处理里按索引重新挂载。

判断接收环是否健康,可以观察“当前 own=1 的空描述符数量”。若长期低于环深度的 1/4,说明 CPU 回收不及时,应检查中断延迟或处理耗时。

四、MAC 地址配置

MAC 地址是 6 字节,写入 ENET 的物理地址寄存器组。以常见的寄存器布局为例,通常分为高 16 位和低 32 位两个寄存器:低 32 位存放地址的第 3~6 字节,高 16 位存放第 1~2 字节。假设要配置 MAC 地址 02:00:5E:10:20:30,则低 32 位为 0x5E102030,高 16 位为 0x0200。

/* 示例:MAC 地址写入(具体寄存器名以 MCX 参考手册为准) */
ENET_PALR = 0x5E102030u;   /* 低 32 位:第 3~6 字节 */
ENET_PAUR = 0x00000200u;   /* 高 16 位:第 1~2 字节 */

/* 使能单播地址过滤,并设置混杂模式关闭 */
ENET_RCR |= ENET_RCR_UP;   /* 单播帧接收 */
ENET_RCR &= ~ENET_RCR_PROM; /* 关闭混杂模式 */

除了单播地址,ENET 还支持多播和广播过滤。工业现场常用组播做设备发现或同步报文,此时需要配置多播哈希表或组播地址寄存器。若调试阶段收不到任何帧,可临时打开混杂模式验证物理链路是否正常,但正式产品中应关闭。

五、PHY 寄存器读写:MDIO 时序

MAC 与 PHY 之间通过 MDIO 接口通信,MDIO 是两线制:MDC 时钟线和 MDIO 数据线。读写 PHY 寄存器需要遵循标准的 32 位帧格式:前导码、起始码、操作码、PHY 地址、寄存器地址、 turnaround 和 16 位数据。MCX 的 ENET 通常提供 MDIO 控制寄存器和数据寄存器,由硬件自动生成时序,软件只需填入 PHY 地址、寄存器地址和读写命令。

典型操作流程如下:先写 MDIO 控制寄存器,填入 PHY 地址(例如 0x01)、寄存器地址(例如 0x00 为 BMSR)、操作码(读或写),然后置“开始”位;轮询“完成”位,直到硬件报告操作结束;最后从数据寄存器读出结果或确认写入完成。读 PHY 的 BMSR(地址 0x01)可以判断链路是否建立,读 PHYIDR1/PHYIDR2(地址 0x02/0x03)可以识别 PHY 型号,这是驱动初始化时确认 PHY 是否在线的第一步。

MDIO 读写必须加超时保护。若 PHY 未焊接、供电异常或地址配错,轮询“完成”位会一直不置位,导致初始化卡死。建议设置 1000 次左右的轮询上限,超时后返回错误并记录 PHY 地址。

六、初始化顺序与结果判断

把上述内容串起来,一个可参考的初始化顺序是:使能 ENET 时钟和引脚复用;复位 ENET 模块;配置 MAC 地址和过滤模式;分配并对齐描述符环与缓冲区;写描述符基址寄存器;配置 MDIO 并读取 PHY ID 确认在线;配置 PHY 的速率、双工和自协商;使能 ENET 的收发和中断;最后启动 DMA。

判断初始化是否成功,可以看三个信号:读 PHYIDR 是否得到非 0 且非 0xFFFF 的 ID;读 BMSR 的 Link Status 位是否置 1;发送一帧后发送描述符的 own 位是否被硬件清 0 并置完成位。三者都满足,说明 MAC、DMA、PHY 这条通路已经打通,可以进入协议栈对接阶段。

检查项观察位置正常表现异常提示
PHY 在线PHYIDR1/PHYIDR2非 0、非 0xFFFFMDIO 超时或地址错
链路状态BMSR bit2置 1网线、PHY 供电或自协商
发送完成TDES own 位由 1 变 0DMA 未启动或环基址错
接收可用RDES own 位由 1 变 0 且有帧缓冲区未回收或过滤过严

掌握这五个环节后,ENET 就不再是一个黑盒。后续做协议栈移植时,遇到“发不出去”先查发送描述符 own 位和 DMA 使能,遇到“收不到”先查接收环回收和 PHY 链路,遇到“时通时断”则重点看缓冲区对齐和中断处理时长。把问题定位到具体层次,比盲目改寄存器要高效得多。