4. I3C 命令码与 CCC:通用命令码、设备角色、组地址
4.1 CCC 命令码——I3C 的"通用语言"
CCC(Common Command Code)是 I3C 总线里最核心的控制机制。说白了,它就是主控器用来给所有设备或某个设备下指令的一套标准"口令"。你想想看,I2C 里要配置一个从机,往往得写一堆寄存器地址和数据,而 I3C 直接用一条 CCC 命令就能完成,效率高得多。
我刚开始接触 I3C 时,总觉得 CCC 就是一堆命令码表格,背下来就行了。后来才发现,真正重要的是理解它的两种传递方式:广播命令和定向命令。广播命令是所有设备都会响应,定向命令只发给某个特定的目标设备。这个区别在地址分配场景里特别关键——ENTDAA 就是广播命令,而 SETNEWDA 是定向命令。
4.2 通用命令码分类与速查
标准 CCC 命令码分为三类:必选命令、可选命令和厂商自定义命令。我习惯把跟地址分配相关的几条命令单独拎出来记,因为它们在 DMA 场景下出现频率最高。
| 命令码 | 缩写 | 类型 | 功能简述 |
|---|---|---|---|
| 0x07 | ENTDAA | 广播 | 进入动态地址分配流程 |
| 0x08 | SETNEWDA | 定向 | 为指定设备设置新动态地址 |
| 0x09 | SETGRP | 定向 | 为设备分配组地址 |
| 0x0A | GETGRP | 定向 | 读取设备的组地址配置 |
| 0x0B | RSTDAA | 广播 | 重置所有设备的动态地址 |
| 0x0C | SETDASA | 定向 | 设置设备的静态地址作为动态地址 |
为什么我特别强调这几条?因为 DMA 做批量地址分配时,依赖的就是 ENTDAA 启动流程、SETNEWDA 逐个写入地址、RSTDAA 做异常恢复。有一次我在项目里发现 DMA 传输老是中断,查了半天,最后发现是 SETNEWDA 的响应超时处理没做好——嗯,从那以后我给每条命令都加了超时计数器。
4.3 设备角色:谁在发号施令?
I3C 总线上有三种角色:Primary Controller、Secondary Controller 和 Target。它们的关系有点像团队里的"主负责人、副手和成员"。
- Primary Controller:总线的"老大",负责发起 CCC 命令、分配地址、管理时钟。DMA 场景下,它通常是 SoC 的主控核。
- Secondary Controller:可以理解为"备份老大"。当 Primary 让出总线时,它能接管控制权。我遇到过主控器宕机、Secondary 接管后地址表不同步的坑——解决方法是在切换后重新发起 ENTDAA。
- Target:就是普通的从设备,接收命令、响应地址分配。DMA 的目标设备基本都是 Target 角色。
你可能会问:角色之间怎么切换?靠的就是 CCC 命令。比如 SETDASA 能把一个 Target 提升为 Secondary Controller,但需要先验证它的能力。我在项目中就见过一个传感器说自己支持 Secondary 模式,结果发过去命令根本没响应……
4.4 组地址:一对多通信的钥匙
组地址(Group Address)是 I3C 里一个很巧妙的设计。它允许 Primary Controller 把多个 Target 设备编成一个"组",然后通过一个地址同时给组内所有设备发命令。你想想看,如果不用组地址,要对 8 个设备做同样的操作就得发 8 次定向命令——有了组地址,一次搞定。
在 DMA 地址分配场景里,组地址的价值体现在"批量同步"上。比如你要同时给一组传感器分配动态地址,传统做法是逐个发 SETNEWDA,耗时随设备数量线性增长。而先通过 SETGRP 把设备编组,再用一次广播命令触发组内地址分配,效率直接翻倍。
我曾经在组地址分配上踩过一个坑:SETGRP 命令的参数里包含了组地址值和成员列表,我当时把成员列表的起始地址算错了,结果组里少了两个设备。调试了整整两天,最后用 GETGRP 回读才发现——嗯,从那以后我每次发完 SETGRP 都会立即读回来校验。
4.5 设备角色与组地址的配合
不同角色在使用组地址时的权限不一样:
- Primary Controller 可以发起 SETGRP 和 GETGRP,管理所有组的配置。
- Secondary Controller 只能读取组地址配置(GETGRP),不能修改。如果需要修改,必须先切换为 Primary 角色。
- Target 只能被动接受组地址分配,并在收到组广播命令时响应。
这个权限分级在 DMA 场景下很重要。我记得有个项目,Secondary Controller 试图在接管总线后直接发 SETGRP,结果所有 Target 都不响应——因为角色还没切换完成。正确的做法是先发 SETDASA 完成角色切换,再执行组地址操作。
4.6 实战:结合 DMA 的组地址分配流程
总结一下,在 DMA 地址分配场景中,命令码、角色和组地址是这样协同的:
- Primary Controller 通过广播 RSTDAA 重置所有设备的动态地址。
- Primary 向目标设备逐个发送 SETGRP,将它们编入同一个组。
- Primary 发送广播 ENTDAA,组内所有设备同时进入动态地址分配流程。
- DMA 控制器接管总线,批量写入每个设备的动态地址(通过 SETNEWDA)。
- Primary 发送 GETGRP 校验组地址配置是否完整。
这个流程我测试过多次,在 8 个设备以下时,DMA 的地址分配耗时比逐条发送 CCC 命令减少了 60% 以上。核心就在于利用了组地址的"一次广播、全员响应"特性。