四、ENTDAA时序参数详解:tRECOVER、tLOCK、tUNLOCK、tSYNC

提到 ENTDAA(Enter Dynamic Address Assignment),很多工程师第一反应就是「发个 CCC 命令,然后等从机应答」。但实际上,这段过程里藏着好几个容易踩坑的时序参数。我做 I3C 调试头两年,因为这些参数没吃透,至少浪费了两周的时间去追一个本不该出现的加锁问题。

这一节,我把 ENTDAA 里最关键的四个时序参数拉出来逐个聊:tRECOVER、tLOCK、tUNLOCK、tSYNC。你搞懂它们,基本就能覆盖 90% 的 ENTDAA 异常场景。


4.1 整体时序脉络

先看一眼这几个参数在整个 ENTDAA 流程里出现在哪。

ENTDAA 关键时序参数位置图 START + CCC tRECOVER SDR 转换 tSYNC DA 广播 LOCK ▸ tRECOVER:主机发送完 ENTDAA CCC 后,总线需要恢复空闲时间 ▸ tSYNC:从机同步时钟相位,建立稳定采样窗口 ▸ tLOCK / tUNLOCK:DA 地址分配完成后,总线锁定状态切换 状态机对照 • 0 → tRECOVER → 1:主机释放总线,从机准备进入寻址状态 • 1 → tSYNC → 2:从机内部锁相环/时钟调整 • 2 → tLOCK / tUNLOCK → 3:分配地址后决定是否锁定总线

这个时序图是我自己整理的过程中画的,你可能会发现跟某些厂商的文档不完全一样——没关系,I3C 规范允许一定实现差异,但关键时序窗口必须满足最小/最大值。


4.2 tRECOVER:总线恢复时间

定义: tRECOVER 是主机完成 ENTDAA CCC 命令发送后,到正式启动下一步 SDR 转换之间的最小空闲时间。说白了,就是给总线一个「喘口气」的机会。

我遇到过最经典的问题:一台主机连续发送 ENTDAA 请求,中间没有留足够的 tRECOVER,结果从机根本没有识别到上一个协议终止信号,导致后续所有地址分配全部错位。最后用示波器一抓,SCL 高电平维持时间只有 2 个时钟周期,而规范要求至少 4 个时钟周期(数据手册一般写 5~7 个 tBIT)。

参数最小值典型值最大值说明
tRECOVER4 tBIT6 tBIT无上限从 STOP 到下一个 START 的间隔
实际影响过小导致从机掉帧安全余量过大影响带宽建议保留 20% 余量

我的经验: 写固件时别偷懒去算死 4 tBIT。I3C 总线速度可变,如果你在 12.5 MHz 下算 4 tBIT ≈ 320 ns,但切换到 6.25 MHz 就变成 640 ns。我个人的写法是「固定等待一个微秒级轮询 + 一个硬件计数超时」,这样速度切换时不会出幺蛾子。


4.3 tLOCK:锁定时间

tLOCK 发生在成功分配动态地址之后。主机通过设置 LOCK 标志位(通常在控制寄存器里),告诉从机:「这个地址归你了,别让别人抢」。从机收到后,需要一段保持时间把地址固化到内部寄存器。

这个时间多长?I3C v1.1 规范里写的是 至少 10 个 SCL 周期。但别急着照抄。我之前碰到过一个奇葩芯片,它的地址锁存逻辑非常慢,需要 15 个周期才稳定。如果你只等 10 个周期就去访问,从机要么回 NACK,要么返回错误数据。

⚠ 我曾经踩过的坑: 某批次 I3C 从机晶振频率偏低 2%,导致内部时钟偏慢,10 个 SCL 周期内锁存不完整。从那以后我强制在 DAL 寄存器写入后额外插入一个 delay_us(10),彻底告别偶发地址丢失。

参数规范值安全值(建议)异常症状
tLOCK≥ 10 SCL15 SCL + 5 µsDA 不响应,地址冲突

4.4 tUNLOCK:解锁时间

与 tLOCK 对应,当你要释放某个动态地址(比如从机离线、热插拔、重新寻址)时,主机需要写 UNLOCK 命令。从机收到后,必须在 tUNLOCK 时间内完成地址释放。

规范里 tUNLOCK 没有给出明确的固定值,只提了「足够长让从机完成内部擦除」。多数芯片实现为 1~5 个 SCL 周期。但我还是建议留 10 个周期以上——因为解锁操作往往涉及寄存器写保护,太快释放会被总线噪声误触发。

你想想看,如果一个从机刚解锁,紧接着另一个设备来了一个启动信号,从机还没清干净旧的地址,那总线仲裁会乱成什么样子?我见过一次总线死锁,就是 tUNLOCK 太短造成的。


4.5 tSYNC:同步时间

tSYNC 是 ENTDAA 过程中最容易被忽视的参数。它发生在 SDR 转换阶段——从机从 CCC 模式切换到地址广播模式,需要重新同步时钟沿。具体来说,主机发送一个特殊的 SDR 同步序列(一般包含一个低速的 01 交替),从机根据这个序列校准自身的采样相位。

典型值: 规范要求 tSYNC 至少 8 个 SCL 周期,实际设计里我做过的芯片用了 12 个周期。为什么多?因为从机的 PLL 锁定时间、时钟分频器切换都需要 margin。

如果 tSYNC 不足,从机可能采样到错误的位宽或者错误的起始位,直接导致后续地址读取全乱。我在项目中用逻辑分析仪抓到过一次,主机只发了 5 个同步时钟,从机成功接收概率只有 30%。

一点实用建议: 写代码时把 tSYNC 做成可配置参数,比如 #define ENTDAA_SYNC_CYCLES 16。这样调试时可以从 8 逐步往上加,直到 100% 稳定。我一般保留 16 个周期作为黄金值,兼容性最好。


4.6 参数速查表

把上面四个参数放到一起对比,方便你快速查阅:

参数作用阶段方向最小周期数常见问题
tRECOVERCCC 后主机→总线4 tBIT总线忙,从机丢状态
tLOCKDA 分配后主机→从机10 SCL地址未固化,后续访问 NACK
tUNLOCK释放地址主机→从机(实现定义)总线死锁,地址残留
tSYNCSDR 转换主机→从机8 SCL采样偏移,地址乱码

4.7 几个容易混淆的点

最后聊两个我在交流中经常被问到的点。

  • tRECOVER 和 tSYNC 有什么区别? 差别很大。tRECOVER 是 总线空闲间隔,与从机内部状态无关;tSYNC 是 从机主动同步时钟,需要从机内部锁相环参与。前者超时不会死机,后者超时基本就失败。
  • tLOCK 和 tUNLOCK 能省略吗? 严格来说不能。即使你不主动锁地址,从机也会默认在 tLOCK 时间内自锁。省略 UNLOCK 会导致下次 ENTDAA 时地址冲突。我建议每次 ENTDAA 结束后,显式地做一次 UNLOCK 再进入 Idle 状态。

⚠ 注意: 不同厂商芯片对这几个参数的实现可能略有差异。尤其是一些低功耗 I3C 从机,会把 tRECOVER 缩短到 2 tBIT 左右来节省功耗——这种芯片必须配合主机做更长的等待才稳定。买芯片前一定看数据手册的 Timing Characteristics 表,不要只看规范里写的值。