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 描述符环与缓冲区映射 CPU / 驱动 填充描述符 Clean/Invalidate D-Cache 读写 OWN 位 描述符环 (16B/项, 16B 对齐) Desc0 Desc1 Desc2 Desc3 OWN | FD | LD | BUF1V | 状态/控制 缓冲区地址 (32-bit) DMA 引擎 TX / RX 通道 自动读写描述符 更新 OWN / 状态位 触发中断 数据缓冲区池 (1536/2048B, Cache Line 对齐) Buf0 Buf1 Buf2 ... 中断汇聚 DMA_ISR / NIS RX / TX / 错误 NVIC 优先级 OWN=1:DMA 拥有描述符;OWN=0:CPU 拥有。RX 归还时重新置 OWN=1,TX 发送完成后由 DMA 清 OWN。 Cache 操作:提交前 Clean,读取前 Invalidate;描述符与缓冲区均需按 cache line 对齐以避免伪共享。

三、中断与轮询模式

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 以太网驱动初始化通常按以下顺序展开:

  1. 时钟与复位:使能 MAC 与 DMA 的 AHB 时钟,释放外设复位,等待 DMA_Mode 的 SWR(Software Reset)位自清。
  2. MDIO 扫描:通过 MAC_MDIO_Address 遍历 PHY 地址 0~31,读取 PHY ID 寄存器(地址 2、3),确认 PHY 存在并记录地址。
  3. PHY 配置:写 PHY 控制寄存器(地址 0)设置自协商、速率与双工;读取 PHY 状态寄存器(地址 1)确认链路已建立。
  4. MAC 配置:设置 MAC_Configuration 的速率、双工、CRC 剥离、巨帧支持;配置 MAC_Frame_Filter 的 MAC 地址过滤。
  5. DMA 描述符初始化:分配 TX/RX Ring,填充缓冲区地址,设置 DMA_Channel_Control 的 PBL(突发长度)与 DSL(描述符跳转长度)。
  6. MTL 队列配置:设置 MTL_RxQ_Operation_Mode 的 RQS(队列大小)与 RTC(接收阈值),为 TSN 多队列预留空间。
  7. 使能收发:置 MAC_Configuration 的 TE 与 RE,置 DMA_Channel_Control 的 ST(Start Transmission)与 SR(Start Reception)。
  8. 中断注册:配置 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 时间戳与诊断抓包才有稳定的底层支撑。