3. ST Stellar以太网外设与驱动架构
ST Stellar 系列 MCU 面向车载中央网关、域控制器与区域控制器,其以太网子系统并非单一 MAC,而是由多个以太网外设实例、DMA 引擎、TSN 硬件调度单元与中断汇聚逻辑共同构成的片上通信子系统。理解这一层的寄存器模型、描述符结构与驱动初始化顺序,是后续做 TSN 流量调度、gPTP 时间同步和诊断调试的基础。本节从硬件对象出发,逐层落到驱动实现与调试手段。
一、MAC 控制器寄存器模型
Stellar 的以太网 MAC 遵循 Synopsys DesignWare GMAC(DWMAC)风格的分页寄存器布局,每个 MAC 实例在系统地址空间中占据一段连续区域,典型划分为以下几个功能区:
- MAC 配置区(0x0000 起):MAC_Configuration、MAC_Frame_Filter、MAC_Packet_Filter 等,控制收发使能、速率(10/100/1000 Mbps)、双工模式、CRC 剥离、VLAN 过滤与混杂模式。
- 流控与时间戳区:Flow_Control、Timestamp_Control,配合 TSN 的 gPTP 硬件打戳,时间戳精度由 PTP_Timestamp_Status 中的 ns 字段与亚纳秒字段共同给出。
- MDIO 区:MAC_MDIO_Address、MAC_MDIO_Data,用于访问外部 PHY 的 32 个寄存器,是链路建立与自协商的入口。
- DMA 控制区(0x1000 起):DMA_Mode、DMA_Status、DMA_Interrupt_Enable、DMA_Channel_Control,每个收发通道独立一套寄存器。
- MTL 队列区:MTL_Operation_Mode、MTL_RxQ_Operation_Mode,配置队列深度、阈值与仲裁方式,是 TSN 多队列调度的落点。
驱动访问这些寄存器时,通常先通过 readl()/writel() 完成 32 位读写,再配合位域宏(如 GMAC_CONFIG_TE、GMAC_CONFIG_RE)做原子置位。需要特别注意的是,MAC 配置寄存器中的 TE(Transmitter Enable)与 RE(Receiver Enable)必须在 DMA 通道初始化完成后再置位,否则会出现描述符未就绪而丢帧。
二、DMA 描述符与缓冲区管理
Stellar 以太网采用环形描述符队列,每个通道由 TX Ring 与 RX Ring 组成。描述符本身是 16 字节结构,包含 32 位缓冲区地址、32 位状态与控制字段、以及可选的扩展时间戳字段。驱动在初始化阶段需要完成三件事:分配描述符内存(必须 16 字节对齐,且位于 DMA 可访问的 SRAM 区域)、分配数据缓冲区(通常 1536 或 2048 字节,按 cache line 对齐)、建立描述符与缓冲区的映射关系。
RX 路径上,驱动预先填充若干描述符并置 OWN 位为 1,表示所有权交给 DMA;当帧到达,DMA 写入数据并清 OWN 位,同时置 FD(首描述符)与 LD(末描述符)标志。驱动在中断或轮询中扫描 RX Ring,遇到 OWN=0 即取出帧,处理完后重新置 OWN=1 归还给 DMA。TX 路径相反:驱动填充缓冲区、置 OWN=1 并触发 DMA_Tx_Poll_Demand,DMA 发送完成后清 OWN 并置 TBU(Transmit Buffer Unavailable)或 TJT(Transmit Jabber Timeout)等状态位。
缓冲区管理的关键是 cache 一致性。Stellar 的 Cortex-M7 带 D-Cache,驱动在把描述符交给 DMA 前必须执行 SCB_CleanDCache_by_Addr(),在 DMA 写回后读取前执行 SCB_InvalidateDCache_by_Addr()。若忽略这一步,会出现“描述符已更新但 CPU 读到旧值”的典型故障。
三、中断与轮询模式
Stellar 以太网提供两种收包处理模式。中断模式下,DMA 在收到帧后置 RI(Receive Interrupt)位,若 DMA_Interrupt_Enable 中对应位使能,则向 NVIC 发出中断请求。驱动在 ISR 中读取 DMA_Status 判断中断源,调用 NAPI 风格的 poll() 批量处理 RX Ring,避免每帧一次中断带来的开销。TX 完成中断则用于回收已发送缓冲区。
轮询模式适用于低延迟或中断负载敏感的场景:驱动关闭 RI 使能,在任务循环中周期性读取 DMA_Status 的 RS(Receive Status)位,或直接扫描 RX Ring 的 OWN 位。轮询间隔需要权衡:过密会占用 CPU,过疏会增加延迟。在 Stellar 上,若以太网用于 TSN 时间敏感流,通常建议中断与轮询混合——高优先级队列用中断,低优先级队列用轮询。
DMA_Interrupt_Enable 是否使能了 RIE,以及 DMA_Status 中的 RI 是否被正确清除。Stellar 的 DMA 状态位是写 1 清除(W1C),误用读改写会导致中断反复触发。四、驱动初始化流程
一个可工作的 Stellar 以太网驱动初始化通常按以下顺序展开:
- 时钟与复位:使能 MAC 与 DMA 的 AHB 时钟,释放外设复位,等待
DMA_Mode的SWR(Software Reset)位自清。 - MDIO 扫描:通过
MAC_MDIO_Address遍历 PHY 地址 0~31,读取 PHY ID 寄存器(地址 2、3),确认 PHY 存在并记录地址。 - PHY 配置:写 PHY 控制寄存器(地址 0)设置自协商、速率与双工;读取 PHY 状态寄存器(地址 1)确认链路已建立。
- MAC 配置:设置
MAC_Configuration的速率、双工、CRC 剥离、巨帧支持;配置MAC_Frame_Filter的 MAC 地址过滤。 - DMA 描述符初始化:分配 TX/RX Ring,填充缓冲区地址,设置
DMA_Channel_Control的PBL(突发长度)与DSL(描述符跳转长度)。 - MTL 队列配置:设置
MTL_RxQ_Operation_Mode的RQS(队列大小)与RTC(接收阈值),为 TSN 多队列预留空间。 - 使能收发:置
MAC_Configuration的TE与RE,置DMA_Channel_Control的ST(Start Transmission)与SR(Start Reception)。 - 中断注册:配置 NVIC 优先级,使能
DMA_Interrupt_Enable中的NIE、RIE、TIE。
初始化完成后,驱动应能通过 DMA_Status 的 RBU(Receive Buffer Unavailable)与 TBU 位判断缓冲区是否耗尽,并据此触发补充描述符的逻辑。
五、调试方法
Stellar 以太网调试可从三个层面入手。寄存器层面,用调试器直接读取 MAC_Configuration、DMA_Status、MTL_RxQ_Debug,确认收发使能、队列水位与错误计数。描述符层面,在内存窗口中查看 RX Ring 的 OWN 位分布,若大量描述符长期 OWN=1,说明 DMA 未收到帧或 PHY 链路未通。统计层面,读取 MMC 计数器(如 MMC_RxPacketCount、MMC_TxPacketCount、MMC_RxCRCError),可快速区分“链路不通”与“帧被过滤”。
MMC_RxPacketCount 增长但应用层收不到数据,优先检查 RX Ring 的 OWN 位是否被驱动正确归还,以及 cache invalidate 是否在读取前执行。这是 Stellar 平台上最常见的“计数正常但丢帧”原因。综合来看,Stellar 以太网驱动的核心在于把寄存器模型、描述符环与 cache 一致性三者对齐。寄存器决定 MAC 行为,描述符决定数据搬运,cache 操作决定 CPU 与 DMA 看到的是否是同一份数据。把这三层关系理清,后续的 TSN 队列调度、gPTP 时间戳与诊断抓包才有稳定的底层支撑。