3. 动态地址分配原理:I3C 动态地址分配协议详解

说到 I3C 的核心玩法,动态地址分配是绕不开的关键一环。

我个人习惯把动态地址分配比作一场“设备点名大会”。

主设备挨个叫名字(或者说,让从设备自己报名字),然后分配一个临时的、唯一的 7 位地址。省去了传统 I2C 里那些硬件的地址引脚,也避免了地址冲突的烦恼。

但坑也不少。我当年第一次调通 ENTDAA 流程时,就因为没注意时序细节,导致一个从设备死活不响应。查了好几天的波形,最后发现是 TCAS 时间设置不够。

咱们今天就聊聊这个分配环节的细节。

3.1 三个核心命令:ENTDAA、SETDASA、SETNEWDA

I3C 的地址分配,说白了就是靠几个专用命令完成的。咱们先看一个对比表,心里有个底。

命令(缩写) 全称 核心用途 适用场景
ENTDAA Enter Dynamic Address Assignment 启动动态地址分配流程,从设备主动提交自己的地址 系统启动、总线枚举
SETDASA Set Dynamic Address from Static Address 给有固定 I2C 地址的从设备直接设置一个动态地址 兼容 I2C 设备、快速配置
SETNEWDA Set New Dynamic Address 为已分配地址的设备更换一个新的动态地址 热插拔、地址冲突处理

你可能会问:这三条命令到底怎么选?嗯,这取决于你的从设备是什么“出身”。

关键区分点:

  • 如果从设备是纯 I3C 设备(没有固定 I2C 地址),只能用 ENTDAA。
  • 如果从设备有出厂时的固定 I2C 地址(比如 0x50),用 SETDASA 更直接。
  • 如果运行时需要改地址(比如地址冲突或热插拔),那就用 SETNEWDA。

3.2 ENTDAA 流程深度解析

这个命令是 I3C 的招牌操作。我习惯把它比作“全自动点名”。主设备只发出一个命令,剩下的工作由从设备自己“抢答”。

步骤拆解:

  1. 主设备发起。 主设备在总线上发送 ENTDAA(0x07 编码)的 CCC(Common Command Code)。
  2. 从设备响应。 所有未分配地址的 I3C 从设备,收到命令后会进入“侦察模式”。它们把自己的 48-bit Provisional ID 放在 SDA 线上。
  3. 总线仲裁(关键!)。 多个从设备同时上拉数据,利用 I3C 的开漏模式做位仲裁。谁的 Provisional ID 更小(按位比较,低电平胜出),谁就继续响应。
  4. 唯一胜出者产生。 仲裁失败的从设备会释放总线,等待下一轮。胜出者会收到主设备分配的 新的 7 位动态地址。
  5. 循环。 重复上述过程,直到所有从设备都分配完地址。

我曾经踩过的坑:

我做一个小批量产品时,用了三颗不同厂家的 I3C 传感器。它们的 Provisional ID 结构不同,其中一颗在 EntDAA 流程中因为 ID 的某一位处理不当,导致它在仲裁阶段误判。结果是,这颗传感器“假装”自己获胜,但后面又响应了错误的地址。后来我用逻辑分析仪抓了总线,才发现问题出在 ID 的 BIT47 上——有一家的芯片把那一位留空了(当作 Reserved),而另一家把它用作厂商版本号。版本号高,仲裁时先输出 1,导致它“输”给了正确的从设备,最后乱套。所以,千万别相信所有芯片的 Provisional ID 都按同一套标准来。

你想想看,这个过程是不是很像“抢答器”?而且 I3C 的仲裁停得很快,几乎不浪费总线时间。

3.3 SETDASA:给“老设备”一个“新身份”

如果你的从设备是 I2C 转 I3C 的混合设备,或者有固定的静态地址(比如老式的 EEPROM),那用 SETDASA 更合适。

操作方式:

  • 主设备直接发送 SETDASA CCC,后面带上目标设备的静态 I2C 地址。
  • 拥有该静态地址的从设备,会被主设备分配一个新的动态地址。
  • 整个过程不需要仲裁,因为静态地址是唯一的。

这里有讲究:

SETDASA 适合那种“我明确知道谁在总线上”的场景。比如,你在 BOM 里只有一颗温度芯片和一颗光感芯片,且它们的静态地址分别是 0x48 和 0x50。那么,直接调用两次 SETDASA,比跑一遍完整的 ENTDAA 要快得多。

小技巧:

我在做复杂系统时,通常先尝试 SETDASA,如果失败(比如从设备没响应),再回退到 ENTDAA。这样能兼顾速度和兼容性。

3.4 SETNEWDA:运行时“换马甲”

这个命令的使用频率相对低一些,但关键时刻很有用。

典型场景:

  • 热插拔:一个从设备被拔出又插回,它之前分配的动态地址可能冲突,需要换成新的。
  • 地址冲突:两个从设备因为某些奇怪原因(比如硬件 Bug)分配了相同的动态地址,需要用 SETNEWDA 把其中一个踢出去。

操作方式:

主设备先知道从设备的“旧动态地址”,然后发送 SETNEWDA,后面跟上新的地址。

说白了,就是给设备换一个数字标签。

3.5 核心流程图

说了这么多,不如画个图直观。下面是我这章的核心逻辑:I3C 动态地址分配的完整决策路径。

I3C 动态地址分配决策与流程 主设备发起地址分配 选择命令 ENTDAA (ID 仲裁) SETDASA (静态地址) SETNEWDA (更换) 多轮仲裁、地址分配 直到所有设备被分配 直接分配 静态地址已知 更换动态地址 解决冲突或热插拔 动态地址分配完成 根据从设备类型,选择对应路径

流程图解读:

  • 左侧(紫色、蓝色):ENTDAA 流程,适用于纯 I3C 设备,依靠 ID 仲裁逐步分配。
  • 中间(绿色):SETDASA 流程,适用于有固定 I2C 地址的设备,快速分配。
  • 右侧(青色):SETNEWDA 流程,适用于运行时的地址变更操作。
  • 最终所有路径汇聚到红色终点:分配完成。

3.6 代码示例:ENTDAA 流程的时序描述

光看概念还不够,咱们看看实际在总线上跑的时候长什么样。下面这段“伪代码”更像是一段波形描述,方便你理解主从交互的节奏。

// I3C 动态地址分配 (ENTDAA) 流程示例
// 假设总线上有 3 个从设备,Provisional ID 分别为:
// DevA: 0x12_34_56_78_9A_BC
// DevB: 0x0A_00_00_00_00_01
// DevC: 0x12_34_56_78_9A_BB

// Step 1: 主设备发送 ENTDAA (0x07)
START -> SCL 时钟 -> 发送 7'b000_0111 + W (0x0E) -> 从设备 ACK
// 此时,所有未分配地址的从设备开始准备

// Step 2: 从设备发送 Provisional ID (逐位仲裁)
// 总线上出现 48-bit 数据流,所有从设备同时驱动
// 仲裁结果:最低的 ID 胜出 (DevB: 0x0A_00_00_00_00_01 胜出)
SDA: 0x0A_00_00_00_00_01  (从设备 B 赢得仲裁)
// 其他从设备释放总线,进入待命状态

// Step 3: 主设备分配动态地址 (例如 0x01)
主设备发送:0x01 (7-bit 地址) + R/W bit (0)
从设备 B ACK

// Step 4: 主设备发送 ENTDAA (0x07) 重复流程
// 剩下 DevA 与 DevC 继续仲裁
// DevC (0x12_34_56_78_9A_BB) < DevA (0x12_34_56_78_9A_BC)
// DevC 赢得第二轮仲裁
主设备分配地址:0x02

// Step 5: 第三次 ENTDAA
// 只剩下 DevA,无仲裁直接分配
主设备分配地址:0x03

// 主设备发送 ENTDAA,无人响应 (NACK) -> 分配完成

实战建议:

我一般在代码里给 ENTDAA 循环加一个“超时”机制。如果连续三次尝试都没有任何从设备响应(主设备收到 NACK),就认为总线枚举结束。否则,可能会陷入死循环。

3.7 避坑指南

说了这么多优点,也该提提我踩过的雷了。

  • Provisional ID 的完整性:不是所有厂商的 ID 格式都一致。有的厂商会留空某些位,有的会用作厂家版本号。如果你家总线上混用不同品牌的芯片,务必查清每颗芯片的 ID 定义。不然仲裁会出幺蛾子。
  • TCAS 时间:ENTDAA 过程中,从设备从“命令解码”切换到“数据发送”的过渡时间很短。如果主设备的 SCL 频率太高,从设备可能来不及准备数据。我建议刚开始做开发时,先用 400kHz 跑通,再试着调高。
  • 地址 0x7E 是保留地址:动态地址不能分配成 0x7E,这个地址是作为广播或特殊操作用的。不少新手在调试时手动配了个 0x7E,结果通讯全乱套了。
  • SETDASA 不支持 I2C 从设备:这一点很容易搞混。SETDASA 虽然用到 I2C 的静态地址,但操作的必须是 I3C 从设备(支持 I3C 协议)。纯 I2C 设备是无法响应 SETDASA 命令的。

特别警告:

我曾经为客户排查一个棘手的 EMI 问题。现象是:I3C 总线在运行 ENTDAA 时,会突然产生巨大的辐射干扰。我抓了波形,发现主设备在发送 ENTDAA 后的那个“总线空闲”窗口,SCL 和 SDA 上有明显的振铃。原因?主设备的驱动电流太强,信号边沿太陡。我调高了驱动能力的配置寄存器,把上升沿从 3ns 拉到 8ns,辐射噪声瞬间下降了 6dB。所以,ENTDAA 流程中的信号边沿控制,是 EMI 整改的重点之一。

好了,关于动态地址分配的核心机制,咱们聊到这儿。理解这三条命令(ENTDAA、SETDASA、SETNEWDA),就算是抓住 I3C 地址管理的命脉了。