在 PCIe 系统中,为了解决 死锁(Deadlock) 问题,PCIe 协议和实现层面采取了一整套设计与工程手段,从协议机制、硬件架构到软件策略都有防护。


✅ 一句话总结:

PCIe 通过 信用流控、事务类型隔离、调度优先级、以及 软件限制策略,系统性防止多个 TLP 相互等待、资源占满而无法继续的死锁情况。


🧠 死锁产生的本质原因

原因描述
双向互等设备 A 等待设备 B 释放资源,B 又在等 A ⇒ 环路等待
信用耗尽Buffer 被填满,Flow Control Update 不能发送
事务阻塞某一类事务独占通道,其他事务无法进行
软件轮询等待软件等硬件响应,硬件等软件操作 ⇒ 逻辑死锁

✅ PCIe 协议层解决死锁的机制

1. 信用流控(Credit-Based Flow Control)

  • 核心:发送方必须有足够的 Credit 才能发送 TLP
  • 防止 RX buffer 被打满
  • 保证数据不会丢,也不会死等

📌 补充机制:

  • Flow Control Update 帧会定期发送,归还已消费的 credit,打破等待环

2. 事务类型独立通道 + 调度机制

TLP 类型描述
Posted不需要应答(如 Memory Write)
Non-Posted需要应答(如 Memory Read)
Completion是应答返回(如 Read 的响应)

PCIe 要求:

  • 三类 TLP 的 credit 和 buffer 是逻辑隔离的
  • 如果一类事务 buffer 满,不影响另一类事务流通
  • 特别强调:Completion TLP 必须保证优先发送,不允许被 Posted 或 Read 请求阻塞

🧠 这样可以打破:

“设备发了 Read 等 Completion → Completion 被写请求堵住 → 写也等信用 → 全卡住” 的死锁链条。


3. Switch 和 Root Complex 中的调度优先级

  • 所有 PCIe 交换结构(如 Switch 芯片、RC)都应实现:

    • Round-Robin 调度:防止某一类事务饿死
    • Completion 优先级高于 Posted
    • 强制发送 Flow Control Update

📌 有些厂商实现了动态调度,检测 starvation 情况自动“抢占”发送通路。


✅ 软件层如何防死锁(尤其是 DMA 和 Read 请求)

1. 控制 outstanding Read 请求数(重要)

  • 如果 PCIe 设备发太多 Memory Read 请求,而不限制 Outstanding Count,可能把对方 Completion buffer 撑爆

  • 最佳实践:

    • 限制最大 Read Pending(如最多 16 个)
    • 每发一个 Read,要么收到 Completion,要么等待超时

2. 合理使用 FIFO 和状态机

  • 不要用阻塞逻辑轮询等待 Completion,改为异步回调机制
  • 用 FIFO 分离各类事务,防止写请求阻塞 Read 返回路径

✅ 工程实践中的死锁防御策略

技术手段描述
Buffer Deep Enough设计足够 RX/TX FIFO,防止突发阻塞
分离通道设计读写使用不同 AXI/AVALON 通道
TLP 类型打标签/区分处理不同通道优先级、隔离处理
测试工具注入高压情况用 PCIe Stress Test 工具测试环路死锁
软件 Watchdog 检测无响应超时重启 DMA / PCIe 控制器

✅ 总结

层级防止死锁的机制
协议信用流控、事务类型分离、Completion优先
硬件架构Buffer 隔离、调度策略、环路检测
驱动软件控制 TLP 深度、异步设计、超时保护
系统测试死锁注入、timeout机制、debug分析辅助

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐