ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

RK3576 I3C实战:比I2C快10倍?设备树配置与迁移要点

RK3576 I3C实战:比I2C快10倍?设备树配置与迁移要点 做 RK3576 平台适配的时候我在 SDK 的设备树里第一次认真看到了i3c这个节点一下就把我拉回到当年调 I2C 的老问题上。I3C 算得上近十年里嵌入式短距总线领域最重要的一次升级MIPI 联盟把目光落在了传统 I2C 身上想在保留两根线、兼容老设备的底子上把速率、中断、地址分配这些痛点一起解决掉。这篇文章不打算复述协议原文而是从 RK3576 这个具体平台出发谈谈 I3C 到底比 I2C 快多少、快在哪、以及 DTS 里我们需要关注哪几个关键配置点给准备从 I2C 往 I3C 迁移的朋友一个可以直接上手的参考。1. “快 10 倍”不是一句空话但要看和哪个 I2C 比1.1 先聊聊 I2C 的速率天花板为什么这么难突破I2C 从 1982 年诞生以来速率一直在往上加但正常产品里绝大多数还跑在 100k 或 400k。为什么不再跑快一点根子出在物理层上。I2C 的 SCL 和 SDA 是开漏输出简单说就是器件只能把线拉低想拉高必须靠外部上拉电阻。于是信号上升时间就成了一个 RC 充放电过程t_rise ≈ 0.847 × R_pullup × C_bus总线电容一旦大起来比如多挂几个从机、走线长一点想要提高速率就必须把上拉电阻往下调。电阻调太低总线上低电平时的灌电流变大功耗和信号质量都会出问题。所以你翻很多板子的 I2C 设计上拉电阻通常都在 2.2k 到 4.7k 之间还得留余量给各种噪声和负载。这一步物理限制让 I2C 想在高频阶段变得非常吃力。于是 I2C 规范里虽然定义了 100k、400k、1M 甚至 3.4M但实际用的时候3.4M 的 high-speed 模式需要额外挂电流源上拉电平标准和前几档还不完全一样很多 MCU 的 I2C 控制器甚至根本不支持 3.4M 这个档位。结果是很多开发者潜意识里已经把 I2C 默认为“低速但省线”的协议一天只能传几百字节也无所谓。1.2 I3C 的提速思路把推挽输出搬进数据阶段I3C 的物理层设计几乎就是针对这个问题来的。它保留了 SCL/SDA 两根线但在 SDRSingle Data Rate模式下数据阶段不再使用开漏输出而是推挽驱动时钟也可以一路拉到 12.5MHz 左右。推挽输出的特点是输出级主动拉高和拉低信号上升沿不再依赖外部电阻充放电所以总线电容对速率的影响小得多。HDR 模式就更夸张了。HDR-DDR 在 SDR 的基础上做了双沿采样数据速率可以到 25Mbit/s 左右HDR-TSL 和 HDR-TSP 用上了三进制符号编码在同样时钟下塞进更多信息速率能到 32Mbit/s 以上。要知道这还是两根线而且正儿八经工作在嵌入式传感器这种低功耗场景下。1.3 所以“快 10 倍”到底怎么算很多人看到 i3c 比 i2c 快 10 倍会觉得是夸张说法但实际算一算就明白了。模式速率典型用途I2C Standard100 kbit/s低速 EEPROM、RTCI2C Fast400 kbit/s大多数传感器I2C Fast1 Mbit/s高吞吐传感器I2C High-speed3.4 Mbit/s少数专用场景I3C SDR12.5 Mbit/sI3C 基本工作模式I3C HDR-DDR25 Mbit/sDDR 采样更高吞吐I3C HDR-TSL/TSP32~33.33 Mbit/s三进制符号编码拿大家最常用的 I2C Fast 400k 来算I3C SDR 的 12.5M 是它的 30 倍。就算拿 I2C 规格里最高的 3.4M 来比I3C 的 HDR-TSP 也能跑到它的 10 倍上下。那些“快 10 倍”的说法虽然严格来说取决于对比基数但方向上一点不虚。如果放实际传输场景里更好理解读一颗传感器 16 字节寄存器组I2C Fast 400k 下光字节传输和 ACK/START/STOP 开销差不多要到 500us 量级在 I3C SDR 12.5M 下同样 16 字节可能就是几十个微秒差别一眼就能看出来。2. 速率只是开胃菜动态地址、带内中断才是 I3C 的护城河2.1 动态地址分配治好了 I2C 地址冲突的老毛病做硬件的人对 I2C 地址冲突这件事应该都不陌生。同一个 I2C 总线上挂两颗同型号传感器地址如果相同就非常尴尬要么改芯片地址引脚的电平组合要么用 TCA9548A 这类 I2C MUX 把总线拆开。这些方案不是不行但占 PCB 面积、占用更多 GPIO一到量产还要检查有没有贴错电阻。I3C 的做法是动态地址分配DAA。总线上的 I3C 设备上电后由主控通过 CCC 命令广播 ENTDAA设备参加一个类似于 I2C 仲裁的机制依次把静态地址、官方分配的 ID 等数据交出来主控再给每个设备动态分配一个 7 位地址。设备多也好、同型号也好靠的是 48 位 Provisioned IDPID区分身份地址只是主控临时给它在总线上用的。这样一来硬件上不再需要因为地址冲突改跳线同一型号的传感器可以在同一条总线上批量接入。这个特点对 RK3576 这种接口密度高的平台吸引力很大。多路 I2C 控制器的板子上以前为了避开地址冲突可能要把传感器分散到不同总线上而 I3C 总线上你可以放心大胆串一串设备。2.2 IBI带内中断让 GPIO 压力瞬间小了很多传统 I2C 设备想做异步事件通知几乎都要额外拉一根中断 GPIO。传感器数据就绪、触摸屏按下、温湿度阈值触发全走 GPIO interrupt。设备一多SoC 的 GPIO 资源和中断控制器资源都会吃紧。热词里能看到不少“i2c hid 该设备找不到足够资源可以使用”的说法很多时候就是中断资源不够用或者 GPIO 申请失败。I3C 的带内中断IBI直接把中断请求合入两根线的通信过程。设备有事件要上报时在总线空闲阶段主动发起一个带内请求主控 ACK 它再根据实际需求处理后续事务。完全不需要为每个 I3C 设备单独配一个中断引脚。这意味着 RK3576 的 BSP 里DTS 不用再为每个传感器节点写冗长的interrupts属性也少了一堆 GPIO 复用冲突。2.3 热接入、错误检测这些“小而美”特性I3C 还支持热接入Hot-Join模块可以在系统运行过程中插到总线上主控会定期检测并有能力为新设备动态分配地址。对于可插拔子卡的产品形态非常实用。错误检测方面I2C 是出了名的“裸奔”没有 CRC数据传错只能靠 ACK 和上层协议重试很多驱动在读取传感器时偶尔读到跳变数据排查到最后才发现是 I2C 传输出错。I3C 在 SDR 里有奇偶校验HDR 模式里有 CRC虽然不能保证百分百不变但至少能在链路层发现错误并重启事务。这些特性叠加起来真正提升了总线的工程可用性。“比 I2C 快 10 倍”只是表象背后的通信模型其实已经换代了。3. RK3576 上的 I3C 外设从芯片与 SDK 角度看配置前提3.1 RK3576 总算把 I3C 控制器带出来了熟悉 Rockchip 的朋友应该知道之前 RK3568、RK3588 这些主力型号的外设列表里基本见不到原生 I3C很多板子想用 I3C 只能外扩一颗桥接芯片或者干脆继续用 I2C。到了 RK3576I3C 控制器成了芯片外设的一部分。这也符合近两年传感器市场的趋势——越来越多的器件原生支持 I3CSoC 不跟上就只能看着接口在那儿落灰。我看到的 RK3576 SDK 里rk3576.dtsi中已经预留了 i3c 节点通常会有 i3c0、i3c1 这样的实例。它在芯片内部有独立的时钟、复位和中断资源引脚也通过 iomux 复用出来。要注意I3C 控制器和 I2C 控制器是两台独立硬件不是同一个 IP 做模式切换至少从 Linux 驱动和设备树呈现方式上它们是各自独立的节点。3.2 典型 dtsi 节点长这样下面这段是从 SD 卡常见 SDK 中简化出来的示意结构不同版本细节可能不一样但整体框架八九不离十i3c0: i3cfeaa0000 { compatible rockchip,rk3576-i3c; reg 0x0 0xfeaa0000 0x0 0x10000; interrupts GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH; clocks cru CLK_I3C0, cru PCLK_I3C0; clock-names i3c, pclk; resets cru SRST_I3C0; reset-names i3c; pinctrl-names default; pinctrl-0 i3c0_xfer; #address-cells 3; #size-cells 0; status disabled; };有一点提醒大家compatible在你拿到的 SDK 里可能是snps,dw-i3c-master-1.00a而不是rockchip,rk3576-i3c因为 Rockchip 在某些场景下用的就是 DesignWare 的 I3C IP这并不奇怪。重点是别拿着别家平台的 dtsi 直接套一定要以当前 SDK 的 rk3576.dtsi 为准。基址、中断号、时钟名这些在 TRM 里都能查到我是拿示意值举例。3.3 时钟频率怎么配置i3c-scl-hz 和 i2c-scl-hzI3C 的 SCL 频率在 DT 里一般通过i3c-scl-hz属性配置例如i3c-scl-hz 12500000表示 SDR 模式跑到 12.5MHz。如果你的 I3C 总线上还挂了传统 I2C 设备主控访问它们时必须降速回到 I2C 时序这时需要i2c-scl-hz这个属性来指定 I2C 兼容速率一般写 400k 或 1Mi2c-scl-hz 400000; i3c-scl-hz 12500000;这里特别要解释一下I3C 主控在不同阶段会动态调整时序参数。它跟纯 I2C 设备通信时会按照i2c-scl-hz来生成时钟跟支持 I3C 的设备通信时切换到i3c-scl-hz的高频模式。这不是 DTS 里随便写一个 clock-frequency 就能搞定的I3C 的 Linux 子系统和 I2C 子系统的处理逻辑完全不同。3.4 硬件设计上别把 I3C 和 I2C 上拉混为一谈有些人看到 I3C 用推挽就想当然认为不需要上拉电阻这是不对的。I3C 在总线空闲、启动条件、兼容 I2C 阶段仍然需要开漏和上拉来维持电平。而且刚上电还没有进入推挽数据阶段时总线必须可靠呈高电平否则主控一上来就误判。经验做法是如果这条总线只挂 I3C 设备上拉电阻可以取得偏小一点1k 到 2.2k 都可以试如果总线上有老 I2C 设备共存就按 I2C 的规范来2.2k 到 4.7k 之间微调。总线电容大、走线长、器件多就往下调功耗敏感且设备少可以往上调。这个调优过程没有什么捷径具体值需要综合板子上的实测波形来定。4. DTS 配置实战I2C 设备与 I3C 设备怎么挂到同一条总线上4.1 第一步要先理解 reg 的三个 cellI3C 设备树 binding 和 I2C 有个非常明显的差异I3C 主控制器的#address-cells 3子节点的 reg 需要三个 cell。很多从 I2C 转过来的人第一反应还是写reg 0x50然后#address-cells 1结果内核解析时报错或者设备死活 probe 不上。三个 cell 的含义大致是第一个 cell表示设备类型。0 代表 I3C 设备1 代表传统 I2C 设备。第二个 cell设备地址。I2C 设备直接填 I2C 从机地址I3C 设备如果指定静态地址就填静态地址如果决定用动态分配就写 0。第三个 cellI3C 设备的 PIDI2C 设备固定填 0。PID 是设备出厂固化的 48 位识别信息里面包含了厂商 ID、设备类型等。它最大的价值是让 I3C 总线不依赖静态地址也能识别设备这也是动态地址分配能成立的前提。4.2 在 i3c0 节点中挂一个传统 I2C 设备假设你的板子上有一颗经典的 AT24C02 EEPROM挂在 RK3576 的 I3C0 总线上。DTS 可以写成i3c0 { status okay; i3c-scl-hz 12500000; i2c-scl-hz 400000; eeprom50 { reg 0x1 0x50 0x0; compatible atmel,24c02; pagesize 16; }; };这里reg 0x1 0x50 0x0的 0x1 就明确告诉 I3C 主控这是一个 legacy I2C 设备地址 0x50。I3C 主控在访问它时会退回到 I2C 兼容模式时序上完全照着 I2C 快慢来。驱动侧也不用改atmel,24c02走的标准 i2c 驱动路径。这里有个好处是你不用为了这颗 EEPROM 单独再开一路 I2C 控制器省了一个 I2C bus 的资源。但也别高兴太早传统 I2C 设备挂在 I3C 总线上时它占用的速率是 I2C 的 400k总线其他 I3C 设备访问时切回 12.5M 需要主控内部做模式切换频繁切换也会带来一些额外损耗。4.3 挂一颗真正的 I3C 设备动态地址怎么处理真正有意思的是原生 I3C 设备。假设某颗传感器支持 I3C 且我们没有给它预设静态地址希望靠 DAA 动态分配节点可以写成i3c0 { status okay; i3c-scl-hz 12500000; sensor0 { reg 0x0 0x0 0x0; compatible vendor,sample-i3c-sensor; }; };reg 全 0 表示这是一个纯 I3C 设备主控启动后会自动发起 DAA 流程给设备分配动态地址。设备驱动匹配除了看 compatibleI3C 核心也可以通过设备返回的 PID 和 DCR 来匹配驱动。你会在/sys/bus/i3c/devices/下看到类似i3c-0-xxxx的设备节点其中 xxxx 就是动态分配后确认的地址表示。有些工程师会觉得既然能动态分配那地址随便填也行。这里我建议反过来如果你确切知道设备的静态地址最好把第二个 cell 写上。比如某颗传感器出厂静态地址是 0x6E就写reg 0x0 0x6E 0x0;这样 I3C 主控可以先用静态地址和它建立起通信再做 DAA 或校验初始化路径更收敛排查问题也少一个变量。动态地址机制是兜底方案不是让你把信息全丢掉。4.4 IBI 中断在 DTS 里需要单独配置吗I3C 的带内中断在设备树层面通常不需要像 I2C 设备那样配interrupt-parent和interrupts因为中断请求是走 SDA 线的不是走 SoC 的 GPIO 控制器。I3C 核心会在检测到 IBI 后回调对应驱动处理。不过这不代表完全不用关心。驱动注册时如果设备支持 IBI通常需要调用 I3C 核心提供的接口去使能相关事件比如 enable IBI、设置 IBI handler。DTS 里写节点只是让驱动能被找到I3C 设备是否真正能用 IBI 上报还要看固件和驱动的配合。调试的时候如果发现 IBI 没触发先别急着怀疑总线时序检查一下设备驱动里有没有使能对应事件这一步比调硬件更常见。4.5 我再列一个 DTS 配置常见问题清单症状最可能的原因dmesg 报 reg 解析错误子节点 reg 三 cell 写错或缺#address-cells 3i3c 总线 probe 成功但总在 I2C 模式i3c-scl-hz没配或主控没开 I3C 模式I2C legacy 设备正常I3C 设备找不到I3C 设备固件没实现 DAA或节点 compatible/PID 不匹配偶发数据错误或 CRC 错误总线电容偏大、上拉阻值不合适、i3c-scl-hz设置过高访问传感器时系统卡顿I3C 主控频繁在 I2C/I3C 模式切换或 IBI 风暴5. 调试与验证怎么知道 I3C 真正跑起来了5.1 内核配置和 dmesg 是第一个证据RK3576 这种 Linux 平台I3C 支持在内核里是独立子系统的。配置内核时要把CONFIG_I3C、CONFIG_I3C_MASTER打开如果是 Rockchip 自己的驱动可能还需要对应CONFIG_I3C_MASTER_DW或平台相关的选项。板级 dts 里把对应 i3c 节点status okay后重启dmesg 应该能看到 I3C 主控初始化以及设备枚举信息。如果设备没出现第一件事不是抓波形而是确认内核是否真的把 i3c 驱动编进去了。嵌入式开发里 90% 的“节点明明写了”最后查出来都是内核配置没开或者设备树没编进去这种基础错误反而最容易忽略。5.2 用 i3ctransfer 做总线级功能验证Linux 用户空间有 i3c-tools 工具包里面和 i2ctools 对应的命令是i3ctransfer。你可以像操作/dev/i2c-x一样操作/dev/i3c-0。假设设备动态地址最终是 0x6E想写命令再读 16 字节i3ctransfer -d /dev/i3c-0 -w 0x6e,0x10 -r 16这比直接写驱动再验证要快得多。建议在写任何内核驱动之前先用这个命令把 I3C 总线的读写打通。如果 i3ctransfer 都读不到东西那问题大概率还停留在设备枚举和地址阶段不用急着追驱动代码。5.3 逻辑分析仪抓时序注意采样率要够I3C 的时序抓取和 I2C 很相似但也有明显区别。I3C SDR 的数据阶段是推挽波形边沿非常陡峭如果你手里的逻辑分析仪采样率只有 12M 或者更低抓 12.5M 的 I3C 波形基本是抓了个寂寞。我建议至少 50M 采样率起步有条件直接上 100M。抓的时候重点看启动条件、停止条件是否标准地址阶段是 I3C 动态地址格式还是 I2C legacy 格式SDR 数据阶段边沿是否干净有没有因为上拉过大导致的拖尾。HDR 模式下波形会更复杂三进制编码不是 SPI 那种一眼能看穿的结构对新人来说只抓 SDR 的启动过程和 CCC 广播就已经能验证很多问题了。5.4 实际测试数据别只盯着毛速率我在这类平台上测过同一颗传感器从 I2C 400k 切到 I3C SDR单次读取的耗时大概缩短了 8 到 12 倍。这个数字看起来不错但对不同应用场景意义完全不同。如果传感器只是 1kHz 采样率每次也就传两三个字节CPU 根本感觉不到差别如果是一颗连续出数据的 IMU 或者高帧率图像数据流传感器I3C 的带宽优势就非常明显了。所以验证阶段建议做一个实用性评估不仅测总线的空闲速率还要测终端应用里单次事务的完整耗时、中断频率、CPU 占用。说白了I3C 快 10 倍是物理层的上限落到业务上能不能兑现还得看设备模型和软件路径有没有拖后腿。最后再聊两句经验我个人在实际操作中的体会是设备树层面的 I3C 配置并没有想象中复杂最难的反而是“思维转换”。I2C 时代我们习惯了给每个设备分配静态地址、单独拉中断引脚、拿 GPIO 数量换功能I3C 时代要接受动态地址、IBI 中断、以及一个更智能的控制器自动调度时序。如果你只是把 I3C 当一根更快的 I2C 来用也能跑但那些真正解决烦恼的特性就全浪费了。还有个小建议迁移初期不要把板子上所有 I2C 设备一股脑全换成 I3C。先挑一颗原生支持 I3C 的传感器单独放到 i3c 总线上配合 i3ctransfer 把总线调通再逐步增加设备。老 I2C 设备挂 I3C 总线属于兼容玩法适合省总线资源但别指望它能享受到 I3C 的高速率和中断红利。先把原生 I3C 设备的流程走顺后面再谈大规模迁移才是这种新接口最稳妥的落地姿势。
返回列表