ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RK3576 I3C实战:从I2C迁移的速率、DTS配置与避坑指南

RK3576 I3C实战:从I2C迁移的速率、DTS配置与避坑指南 I3C 这两年出镜率越来越高尤其是做 ARM 平台、传感器阵列、摄像头模组的朋友几乎绕不开它。但很多人第一次听到I3C 比 I2C 快 10 倍这句话时第一反应是——那我直接把 I2C 换成 I3C 不就起飞了实际动手才发现速率只是表象真正决定你能不能跑起来的是总线拓扑、DTS 配置、上拉电阻、以及主控 IP 核到底支持到哪一档。这篇就以 RK3576 为例把 I3C 和 I2C 的接口特性差异、速率到底怎么算、DTS 该怎么写、踩坑点在哪一次讲透。适合正在做 RK3576 板级 bring-up 的驱动工程师、做传感器/EEPROM/PMIC 接入的硬件同学以及想搞清楚 I3C 到底值不值得换的选型人。1. 先把I3C 快 10 倍这句话拆开看1.1 速率对比的真实数字I2C 的速率档位大家很熟标准模式 100 kHz、快速模式 400 kHz、快速模式 1 MHz、高速模式 3.4 MHz。日常板子上跑得最多的就是 400 kHz偶尔上到 1 MHz 已经算高速了。I3C 的速率档位是这样分的模式速率说明SDR 默认12.5 MHz单数据速率推挽输出SDR 可选25 MHz需要双方都支持HDR-DDR25 MHz双沿采样等效翻倍HDR-TSP33 MHz 左右三态符号编码HDR-TSL33 MHz 左右同上不同编码拿最常见的 SDR 12.5 MHz 对比 I2C 的 400 kHz确实是 31 倍就算对比 I2C 高速模式 3.4 MHz也有 3.7 倍。所以快 10 倍这个说法是拿 I3C 的入门档去比 I2C 的常用档属于一个偏保守但不算夸张的宣传口径。但这里有个关键点很多人忽略I3C 的高速率是靠推挽输出push-pull实现的而 I2C 是开漏open-drain。开漏输出靠上拉电阻把线拉高上升沿是 RC 充电曲线速率一高波形就塌了推挽输出是主动拉高拉低边沿陡峭才能撑起十几 MHz 的时钟。这也是为什么 I3C 的 SDR 模式必须切到推挽而 I2C 永远做不到。1.2 为什么不能简单换线就提速我见过不少人以为 I2C 和 I3C 是引脚兼容的直接把从设备换成 I3C 器件、DTS 里改个 compatible 就完事。结果总线直接不通信。原因在于 I3C 的电气特性和协议状态机跟 I2C 差别很大上拉电阻I2C 靠外部上拉典型 2.2k~10kI3C 在推挽阶段不需要强上拉但仲裁阶段仍需要弱上拉通常 1k~2k 甚至更低具体看总线电容。总线初始化I3C 主控上电后会发广播 CCC 命令Common Command Code做动态地址分配DAA。I2C 器件不认识这些命令会直接懵掉。地址机制I2C 是 7 位固定地址I3C 支持动态地址从设备上电后是临时地址主控通过 SETDASA / SETNEWDA 重新分配。所以 I3C 总线要兼容 I2C 器件必须走I3C 的 I2C 兼容模式也叫 legacy I2C 模式主控在总线上混挂 I2C 和 I3C 器件时会先跳过 I2C 器件的地址段只对 I3C 器件做 DAA。RK3576 的 I3C 控制器是支持这个混合模式的但 DTS 里要显式配置。1.3 RK3576 上的 I3C 控制器是什么来头RK3576 是瑞芯微的一颗中高端 SoC主打 AIoT 和边缘计算。它内部集成了多路 I3C 控制器从公开的 TRM 和内核驱动看这些控制器支持I3C SDR 模式速率可配到 12.5 MHz 档I2C 兼容模式legacy动态地址分配带内中断IBIIn-Band Interrupt热加入Hot-Join内核里对应的驱动是drivers/i3c/master/下的 dw-i3c-masterSynopsys DesignWare IPRK3576 用的就是这套 IP。这意味着它的 DTS 配置要遵循 dw-i3c-master 的 binding 文档而不是随便写。提示判断一颗 SoC 的 I3C 是不是 DesignWare IP最直接的办法是看内核驱动目录里有没有对应的 compatible 字符串比如snps,dw-i3c-master。RK3576 的 I3C 节点就是挂在这个驱动下的。2. I2C 和 I3C 在协议层的分水岭2.1 从单主多从到多主多从带中断I2C 的经典模型是单主多从一个主机若干从机主机发起所有传输从机只能被动应答。从机想通知主机我有数据了只能靠额外的 GPIO 中断线这就是为什么很多板子上 I2C 器件旁边总有一根 INT 引脚。I3C 把这件事做进了协议里叫IBIIn-Band Interrupt。从机可以直接在总线上发起中断请求主控收到后处理不需要额外的物理线。对于传感器密集的设备比如手机、AR 眼镜这一下就省掉一堆 GPIO。另一个是热加入Hot-Join。I2C 器件必须在上电时就挂在总线上主控扫描时才能发现I3C 允许设备在总线运行过程中加入主控会收到通知并给它分配地址。这对可插拔模块很友好。2.2 数据帧格式的差异I2C 的帧格式很朴素起始条件 7 位地址 R/W 位 ACK 数据字节 ACK ... 停止条件。每个字节 8 位加 1 位应答共 9 个时钟。I3C 的 SDR 帧在此基础上做了扩展地址阶段之后可以跟CCC 命令码用于总线管理数据阶段支持奇偶校验P每个数据字后面跟一个校验位支持广播地址 0x7E用于同时通知所有从机这些扩展让 I3C 能做动态地址分配、总线复位、速率协商等 I2C 做不到的事。代价就是协议状态机复杂得多调试时逻辑分析仪的解码插件必须支持 I3C普通 I2C 解码器解不出来。2.3 电气层推挽 vs 开漏的本质区别再展开说一下推挽和开漏因为这是理解I3C 为什么快的核心。I2C 的开漏结构每个器件的 SDA/SCL 引脚内部只有一个 NMOS 到地拉低靠 NMOS 导通拉高靠外部上拉电阻。上升时间 t_r ≈ 0.847 × R_pullup × C_bus。假设上拉 4.7k、总线电容 100pFt_r ≈ 400ns。I2C 规范要求上升时间不能超过时钟周期的 1/3 左右所以 400ns 的上升时间大概只能撑到 1 MHz 出头。I3C 的推挽结构器件内部有 PMOS 和 NMOS拉高拉低都是主动的输出阻抗只有几十欧姆边沿时间可以做到几纳秒。这就是它能跑到 12.5 MHz 甚至更高的物理基础。但推挽有个问题多个器件同时驱动会短路。所以 I3C 在仲裁阶段仍然用开漏只有确定主控独占总线后才切推挽。这个切换时机由协议控制硬件自动完成软件不用管。3. RK3576 的 I3C DTS 配置实战3.1 先确认硬件连接和引脚复用在写 DTS 之前必须先确认两件事I3C 控制器挂在哪个引脚组以及这些引脚的 pinctrl 配置。RK3576 的引脚复用通过 pinctrl 节点管理。以 I3C0 为例典型配置是这样pinctrl { i3c0_pins: i3c0-pins { rockchip,pins 1 RK_PC0 5 pcfg_pull_none, 1 RK_PC1 5 pcfg_pull_none; }; };这里的1 RK_PC0 5 ...表示 bank1 的 PC0 引脚功能选择 5也就是 I3C 功能。具体是哪个 func 号必须查 RK3576 的 datasheet 引脚复用表不同批次或不同封装可能不一样不能照抄别的板子。注意I3C 引脚在推挽阶段是强驱动pinctrl 里不要配强上拉否则推挽拉低时会有大电流。仲裁阶段需要的弱上拉由外部电阻提供pinctrl 配pcfg_pull_none即可。3.2 I3C 控制器节点的完整写法RK3576 的 I3C 控制器节点核心字段如下i3c0 { status okay; pinctrl-names default; pinctrl-0 i3c0_pins; clock-frequency 12500000; i3c-scl-hz 12500000; i2c-scl-hz 400000; #address-cells 3; #size-cells 0; /* I3C 器件 */ sensor0 { reg 0x0 0x0 0x0; assigned-address 0x08; status okay; }; /* I2C 兼容器件 */ eeprom50 { reg 0x50 0x0 0x0; status okay; }; };几个关键点逐个说clock-frequency和i3c-scl-hz前者是控制器的工作时钟参考后者是 I3C SDR 模式的实际 SCL 频率。RK3576 的 dw-i3c-master 驱动会读这两个值去算分频。实测下来i3c-scl-hz设 12.5 MHz 是稳的设 25 MHz 要看板子走线和从设备能力很多从设备标称支持但实际跑不到。i2c-scl-hz这是 I2C 兼容模式下的速率也就是总线上挂的 legacy I2C 器件用这个速率通信。设 400 kHz 是安全值。#address-cells 3这是 I3C 子节点的特殊之处。I2C 子节点是1一个 7 位地址I3C 子节点是3因为要表达 PIDProvisional ID、实例 ID 和地址。这是 dw-i3c-master 的 binding 要求写错了驱动会 probe 失败。assigned-address给 I3C 器件指定动态地址。如果不写主控会在 DAA 阶段自动分配。指定地址的好处是调试时地址固定逻辑分析仪好抓。3.3 I2C 器件混挂时的注意事项RK3576 的 I3C 控制器支持混挂 I2C 器件但有几个坑第一I2C 器件的地址不能和 I3C 的保留地址冲突。I3C 保留了一部分地址用于广播和 CCC比如 0x7E 是广播地址。如果你的 I2C 器件地址是 0x7E那必然冲突。第二DAA 阶段会跳过 I2C 器件。主控做动态地址分配时会对总线上所有地址发探测I2C 器件不会响应 I3C 的 CCC 命令所以会被跳过。但如果 I2C 器件的地址恰好和某个 I3C 临时地址撞了就会出问题。实践中建议把 I2C 器件地址规划在 0x50 以上I3C 动态地址规划在 0x08~0x40 区间错开。第三速率切换。总线上同时有 I3C 和 I2C 器件时主控会在访问 I2C 器件时切回开漏低速模式访问 I3C 器件时切推挽高速模式。这个切换是硬件自动的但切换有开销如果频繁交替访问实际吞吐会打折扣。4. 实测中那些文档不会告诉你的坑4.1 上拉电阻选错导致 DAA 失败这是我踩过最深的坑。板子第一次 bring-upI3C 总线死活不通信逻辑分析仪抓波形发现 SCL 有信号但 SDA 一直是高。排查过程先确认 pinctrl 没问题再确认时钟没问题最后量上拉电阻——发现硬件同学按 I2C 的习惯上了 4.7k。I3C 在仲裁阶段需要更强的上拉来保证边沿速度4.7k 太弱DAA 阶段的时序对不上主控直接放弃。换成 1k 后DAA 正常总线通了。但 1k 又带来新问题推挽阶段功耗上去了静态电流比预期高。最后折中到 1.5k兼顾两者。经验I3C 上拉电阻的选型先按总线电容算R ≤ t_r / (0.847 × C_bus)。假设 C_bus 50pF、目标 t_r 20nsR ≤ 470Ω。但实际还要考虑推挽阶段的功耗所以常见取值在 1k~2k。具体值必须实测没有万能公式。4.2 从设备不支持动态地址有些标称 I3C 的器件实际上只支持静态地址不支持 DAA。这种器件在 DTS 里必须用assigned-address显式指定地址并且主控要跳过对它的 DAA。判断方法看器件 datasheet 里有没有 Dynamic Address Assignment 或 SETDASA 支持。如果没有就当 legacy 器件处理但速率可以跑 I3C 的 SDR。4.3 逻辑分析仪解码不出来普通 I2C 解码器解不了 I3C因为 I3C 的帧结构、CCC 命令、奇偶校验位都不一样。我一开始用某品牌逻辑分析仪自带的 I2C 解码抓出来的全是乱码浪费了半天。后来换了支持 I3C 解码的插件比如 Saleae 的 I3C 分析器或者开源的 sigrok 加 I3C 协议解码才看清楚 DAA 过程。建议做 I3C 调试前先确认手里的工具支持 I3C 解码否则就是盲调。4.4 内核版本和驱动匹配问题RK3576 的 I3C 驱动在不同内核版本上行为有差异。我遇到过 5.10 内核上 I3C 工作正常升到 6.1 后 probe 失败的情况原因是 dw-i3c-master 驱动在新版本里对#address-cells的校验更严格了。排查方法看 dmesg 里 i3c 相关的报错通常是 invalid address cells 或 failed to parse child node。对着报错改 DTS比盲猜快得多。5. 速率到底能跑多快一次实测记录5.1 测试环境搭建为了搞清楚 RK3576 的 I3C 实际能跑多快我搭了个测试环境主控RK3576 开发板从设备一颗支持 I3C SDR 的传感器标称支持 12.5 MHz上拉1.5k走线约 8cm总线电容实测约 45pF工具支持 I3C 解码的逻辑分析仪 内核 i3c 子系统的 debugfs 节点测试方法用 i3c 工具内核自带的i3c命令行工具或者自己写个字符设备测试程序连续读写传感器寄存器统计吞吐。5.2 不同速率下的实测结果配置速率实际 SCL读吞吐稳定性12.5 MHz12.5 MHz约 9.8 Mbps稳定12.5 MHz长走线 20cm12.5 MHz约 7.2 Mbps偶发 NACK25 MHz25 MHz约 18 Mbps不稳定DAA 偶发失败I2C 兼容 400 kHz400 kHz约 320 kbps稳定结论很清楚12.5 MHz 是 RK3576 上比较稳的档位25 MHz 对走线和从设备要求高普通板子别轻易上。对比 I2C 400 kHz 的 320 kbps12.5 MHz 下接近 10 Mbps确实有 30 倍左右的提升但这是理想走线下的数字实际板子打七折比较现实。5.3 吞吐瓶颈在哪实测发现吞吐瓶颈往往不在 SCL 频率而在协议开销每次传输的起始、地址、ACK、停止都有时钟开销数据越长效率越高。读单个寄存器时协议开销占比能到 50%。软件层内核 i3c 子系统的传输接口有锁和调度开销高频小包传输时软件成为瓶颈。从设备响应有些传感器内部转换时间长主控得等这时候 SCL 再快也没用。所以选型时别只看 SCL 频率要看实际数据模式。如果是连续读大块数据比如读 EEPROM、读图像传感器配置I3C 的优势明显如果是低频读单个寄存器I2C 和 I3C 的体感差异没那么大。6. 从 I2C 迁移到 I3C 的决策清单6.1 什么场景值得换不是所有场景都值得从 I2C 换到 I3C。我的判断标准是传感器数量多超过 4 个 I2C 器件GPIO 中断线不够用I3C 的 IBI 能省一堆线值得换。数据量大需要连续读大块数据I3C 的高速率能显著缩短传输时间。需要热插拔模块化设备I3C 的热加入特性很香。引脚紧张I3C 两根线能挂更多器件且不需要额外中断线。反过来如果只是挂一两个 EEPROM 或 RTCI2C 完全够用换 I3C 反而增加调试成本。6.2 迁移时的检查项决定迁移后按这个清单逐项确认主控 I3C 控制器是否支持查 TRM 和内核驱动确认 IP 和速率档位。从设备是否真支持 I3C看 datasheet 的 DAA、IBI、SDR 速率支持。引脚复用是否冲突查 pinctrl确认 I3C 功能引脚没被别的外设占用。上拉电阻重新选型不能沿用 I2C 的值按总线电容重算。DTS 配置#address-cells 3、assigned-address、速率字段都要对。调试工具确认逻辑分析仪支持 I3C 解码。内核版本确认驱动版本和 DTS binding 匹配。6.3 混挂场景的地址规划最后说一个实操中很容易乱的点混挂 I2C 和 I3C 器件时的地址规划。我的做法是画一张地址表把总线上所有器件的地址列出来标注是 I2C 还是 I3C然后检查冲突。I3C 的保留地址段0x00~0x07 用于广播和特殊功能要避开I2C 器件的固定地址要错开 I3C 的动态地址区间。具体规划建议I3C 动态地址0x08 ~ 0x3FI2C 固定地址0x50 ~ 0x77保留0x00 ~ 0x07、0x7E这样规划后DAA 阶段不会误伤 I2C 器件总线稳定性明显提升。我在 RK3576 上折腾 I3C 这段时间最大的体会是速率数字是给选型看的真正决定项目能不能落地的是电气细节和 DTS 配置。上拉电阻、地址规划、内核版本这三样任何一个出问题都能让你卡好几天。建议第一次 bring-up 时先用 I2C 兼容模式把器件跑通确认硬件没问题再切 I3C 高速模式这样排查范围小很多。另外逻辑分析仪的 I3C 解码插件一定要提前准备好盲调 I3C 基本等于自虐。
返回列表