• 正文
  • 相关推荐
申请入驻 产业图谱

STM32MP1x USB OTG Gadget FIFO 设置

20小时前
233
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

STM32MP1x 的 USB‑OTG 工作在 Gadget(外设)模式时,硬件拥有 4KB(1024 个 32bit 字)专用 FIFO‑RAM,供 USB 端点收发数据包使用。默认设备树 FIFO 参数仅适配单 USB 功能;当搭建复合 USB 设备(多 ACM、NCM、RNDIS 等多个功能同时启用),默认 FIFO 分配不足,会出现丢包、USB 枚举失败、大数据传输卡顿、BULK 吞吐量下降等疑难现象。

LAT6041 文档讲解 DWC2 控制器 FIFO 硬件架构、内存计算公式、设备树 DTS 三个关键属性配置方法,并且给出「1 路 NCM+3 路 ACM」复合设备完整调参示例。本文梳理硬件原理、计算规则、DTS 配置、踩坑排错要点。

单位重要提示:DTS 中 FIFO 配置单位是32bit 字,不是字节;1 字 = 4 字节,计算时必须做换算。

资料获取:实战经验 | LAT6041 STM32MP1x USB OTG FIFO设置_v1.0

1. OTG 外设模式 FIFO 硬件架构

STM32MP1 OTG 硬件 FIFO 内存总大小:4096 字节,等价1024个32bit字。 其中 9 个 DMA 通道(1RX+8TX)固定占用每个通道 8 个字,合计占用 72 个字;实际可分配给 USB FIFO 的总资源 = 952 个字,所有 RX、TX FIFO 总和不能超过 952 字。

外设模式 FIFO 关键特性

  1. 所有 OUT 端点共享唯一 Rx‑FIFO 全部 OUT 端点共用接收缓冲区,寄存器OTG_GRXFSIZ控制 Rx‑FIFO 大小;FIFO 填满之后,后续 USB 包会直接返回 NAK 握手,造成丢包。
  2. 每一个 IN 端点拥有独立 Tx‑FIFO EP0 控制端点使用OTG_DIEPTXF0;EP1‑EP7 共 7 个 IN 端点各自拥有独立 TxFIFO 寄存器;
  3. 区分周期性端点、非周期性端点
    • 周期性:中断、同步 (Isochronous) 端点;
    • 非周期性:Bulk 批量、控制传输端点。

硬件寄存器与设备树 DTS 映射

OpenST‑Linux 内核 DWC2 驱动不直接操作寄存器,通过设备树三个属性完成 FIFO 划分:

DTS 属性 含义(单位:32bit 字) 对应硬件
g‑rx‑fifo‑size 全部 OUT 端点共享接收 FIFO 大小 OTG_GRXFSIZ
g‑np‑tx‑fifo‑size 非周期性 TX FIFO,主要用于 EP0 控制端点 OTG_DIEPTXF0
g‑tx‑fifo‑size 数组,共 8 个值,依次分配 EP1~EP7 IN 端点周期性 FIFO OTG_DIEPTXF1‑7

注意:g‑tx‑fifo‑size数组 8 个成员,每个成员最小强制 16 字,即使该端点没有被使用;内核启动时会自动遍历数组,为 Gadget 功能自动匹配大于等于端点 MaxPacket 的 FIFO 资源,不需要人为绑定端点序号。

2. FIFO 最小空间计算公式

2.1 Rx‑FIFO(共享接收缓冲区)

Rx‑FIFO 除数据包之外,还必须预留 SETUP 包、NAK 状态、每个包附带状态描述符空间。
参考最小计算公式: RxFIFO = (5*控制端点数量+8) + ((最大数据包大小/4)+1) + 2*OUT端点数量+1

  • 如果存在多个等时端点,建议放大为 2 倍(最大数据包/4+1),防止连续数据包溢出丢包。

2.2 Tx‑FIFO(IN 端点发送缓冲区)

每个 IN 端点 TxFIFO 最小:TxFIFO = MaxPacketSize / 4; 工程实践建议取 2 倍值,提升高速传输稳定性。
MaxPacketSize 为 USB 端点最大包大小,高速 Bulk 端点典型 512 字节,换算字:512 /4 = 128字;通知中断端点 64 字节换算:64/4=16字,一般工程取 32 字留裕量。

3. 实战案例:NCM + 三路 ACM 复合设备

业务需求:单 OTG 实现 1 个 NCM 网络接口 + 3 个 ACM 虚拟串口复合设备。

  1. NCM:1 个 OUT,2 个 IN;Bulk IN 最大包 512 字节(需要≥128 字);Notify 中断 IN 最大包 64 字节(建议 32 字)。
  2. 每一路 ACM:1 个 OUT,2 个 IN;Bulk IN 最大包 512 字节,需要≥128 字;Notify 通知 IN 64 字节。
  3. 合计:一共4 路 Bulk IN 端点,每一路都至少 128 字,其余通知中断端点使用 32 字。

DTS 配置计算

  • g‑np‑tx‑fifo‑size:EP0 控制端点,MaxPacket=64 字节,设置32字;
  • g‑tx‑fifo‑size数组:4 个 128 字 + 4 个 32 字:<128 128 128 128 32 32 32 32>
  • 总消耗:32 + (128*4)+(32*4)= 672字;剩余资源分配给g‑rx‑fifo‑size,设置 256 字;
  • 总和:256+32+672 = 960,接近硬件上限 952,微调为 256,满足整套复合设备。

修改 dts 片段示例(stm32mp135f‑dk.dts)

&usbotg_hs {
    phy‑names = "usb2‑phy";
    usb‑role‑switch;
    status = "okay";
    g‑rx‑fifo‑size = <256>;
    g‑np‑tx‑fifo‑size = <32>;
    g‑tx‑fifo‑size = <128 128 128 128 32 32 32 32>;
};

该配置已经耗尽硬件绝大多数 FIFO 资源,这也是 STM32MP1 单 OTG 硬件可以支撑的最大复杂度 Gadget 复合设备配置。

4. 工程落地排查清单

  1. 复合 Gadget 枚举失败,dmesg 打印 dwc2 fifo 资源不足
    • 检查全部 FIFO 字总和,必须≤952;
    • 检查g‑tx‑fifo‑size数组 8 个成员,每个数值不能小于 16,未使用端点也要填 16 及以上;
    • Bulk 高速端点 512 字节 MaxPacket,FIFO 至少配置 128 字。
  2. USB 可以枚举,但是大吞吐量传输随机丢包,偶发 NAK
    • Rx‑FIFO 分配过小,增大g‑rx‑fifo‑size;多等时端点场景建议按照 2 倍数据包空间分配;
    • 核对 IN 端点 TxFIFO,只配置理论最小值容易出现传输不稳定,建议放大到 2 倍 MaxPacket/4。
  3. 修改 DTS 之后,参数没有生效
    • 确认编译更新 dtb 设备树二进制;确认 Bootloader 加载的是新 dtb;
    • 内核 dmesg 日志可以打印 dwc2 的 FIFO 分配统计,确认参数是否被内核读取。
  4. 单 Gadget 功能(RNDIS 或者 ACM)工作正常,叠加第二个 Gadget 立刻异常
    • 默认 DTS 的 FIFO 偏向单设备,IN 端点大部分 FIFO 资源分配给第一个端点;复合设备场景需要重新均分g‑tx‑fifo‑size数组。

5. 小结

  1. STM32MP1 OTG‑Gadget 模式,FIFO 总可用资源 952 个 32bit 字,DTS 属性全部以字为单位,不是字节;OUT 端点共享 Rx‑FIFO,每个 IN 端点拥有独立 Tx‑FIFO。
  2. 三个 DTS 属性:g‑rx‑fifo‑size、g‑np‑tx‑fifo‑size、g‑tx‑fifo‑size[8];数组 8 项,每项最小 16 字;内核自动为 Gadget 端点匹配 FIFO,无需硬编码绑定端点编号。
  3. 复合 USB 设备(NCM + 多路 ACM)需要重新做资源预算,不能沿用出厂默认 DTS 配置;文中示例为单 OTG 硬件能力上限的复合配置。
  4. Rx‑FIFO 除数据包之外,还需要预留 SETUP 包、状态描述符;多等时端点建议放大接收缓冲区,避免 NAK 丢包。

6. FAQ

Q:g‑tx‑fifo‑size 数组顺序是否必须和 USB 端点编号一一对应?

A:不需要。内核遍历数组,自动挑选大于等于该端点 MaxPacketSize 的 FIFO 资源分配给 IN 端点,顺序无关,只要数组内存在满足大小的数值即可。

Q:如果 g‑tx‑fifo‑size 里面某个值小于端点 MaxPacket/4 会发生什么?

A:Gadget 功能初始化失败,dmesg 会打印 FIFO 资源不足,USB 复合设备枚举失败。

Q:主机模式下,这套 FIFO 配置是否生效?

A:本文只针对 Gadget 外设 (Device) 模式;Host 主机模式 FIFO 组织架构完全不同,DTS 这几个属性不会生效。免责声明:本文全部基于 ST 官方 LAT6041 文档;实际项目以 OpenST‑Linux 内核 dwc2 绑定文档、硬件手册为准。

相关推荐