4. ARM平台I2C控制器概述:常见SoC特性对比
在嵌入式ARM Linux系统中,I2C控制器作为芯片内部的一个I2C总线主机(Master)外设,负责在硬件层面实现I2C协议的时序、仲裁、中断和DMA传输。不同厂商的ARM SoC(如STM32MP1、i.MX6、RK3399)在I2C控制器的寄存器模型、时钟管理、中断机制和DMA支持上存在显著差异,这些差异直接影响设备树绑定和驱动适配策略。
核心认知: 设备树中的I2C节点本质上是描述控制器硬件特性的“寄存器地图”和“资源清单”。理解控制器差异,是正确编写和调试设备树的前提。
4.1 三大主流SoC I2C控制器特性总览
下表从IP核来源、位宽、时钟、中断、DMA、地址模式、传输速率等关键维度,对比STM32MP1、i.MX6和RK3399的I2C控制器。
| 特性维度 | STM32MP1 (I2C) | i.MX6 (I2C) | RK3399 (I2C) |
|---|---|---|---|
| IP核来源 | ST 自研 (I2Cv2) | NXP (飞思卡尔) VF610 | Rockchip 自研 (APB) |
| 寄存器位宽 | 32-bit | 8-bit (部分32-bit对齐) | 32-bit |
| 时钟源 | PCLK (APB总线时钟) | IPG_CLK (外设时钟) | PCLK (APB总线时钟) |
| 中断类型 | 单中断线 (事件+错误合并) | 单中断线 | 单中断线 |
| DMA支持 | 支持 (TX/RX独立DMA请求) | 支持 (需外置DMA引擎) | 支持 (内置DMA控制器) |
| 地址模式 | 7-bit / 10-bit | 7-bit / 10-bit | 7-bit / 10-bit |
| 最大传输速率 | Fast-mode Plus (1 Mbps) | Fast-mode (400 Kbps) | Fast-mode (400 Kbps) |
| 从机模式 | 支持 (多主模式) | 支持 (从机模式) | 支持 (从机模式) |
| 总线仲裁 | 硬件自动仲裁 | 硬件自动仲裁 | 硬件自动仲裁 |
| 电源管理 | 支持时钟门控 | 支持时钟门控 | 支持时钟门控 + 唤醒 |
关键差异点: STM32MP1的I2C控制器支持Fast-mode Plus(1Mbps),适合高速传感器;i.MX6的寄存器为8位宽,在设备树中需要特别注意地址对齐;RK3399的I2C控制器内置了DMA请求逻辑,在设备树中需要额外配置dmas属性。
4.2 控制器内部架构对比
下图展示了三种SoC I2C控制器的内部模块架构差异,重点突出时钟域、数据路径和中断/DMA请求路径。
架构差异解读: STM32MP1和RK3399都具备硬件FIFO,能有效减少中断频率,适合高吞吐量场景;i.MX6的VF610 I2C没有FIFO,每次传输都需要CPU逐字节干预,在设备树中需要配置更小的传输超时。RK3399的DMA请求直接连接到内部DMA控制器,延迟更低。
4.3 时钟树与速率计算差异
I2C控制器的时钟源和分频逻辑直接影响总线速率。三种SoC的时钟树结构不同,设备树中clock-frequency属性的实际效果也不同。
4.3.1 时钟路径对比
| SoC | 时钟源 | 分频方式 | 设备树时钟属性 |
|---|---|---|---|
| STM32MP1 | PCLK (APB) → 预分频器 → 时序寄存器 | 通过 TIMINGR 寄存器配置 SCL 高低电平时间 | clock-frequency + st,i2c-timing |
| i.MX6 | IPG_CLK → IFDR 分频寄存器 | 6位分频因子 (0x00~0x3F) | clock-frequency (驱动自动计算 IFDR) |
| RK3399 | PCLK → CLKDIV 寄存器 | 8位分频因子 (0x00~0xFF) | clock-frequency + rockchip,clk-div |
常见陷阱: 在STM32MP1上,仅设置
clock-frequency而不配置st,i2c-timing可能导致时序违规,因为驱动需要精确的时序参数来计算SCL高低电平。i.MX6的IFDR分频值不是线性映射,驱动中有一个查找表,设备树中不要手动设置IFDR值。
4.3.2 速率计算示例
以100Kbps标准模式为例,三种SoC的时钟配置差异:
// STM32MP1: 需要计算 TIMINGR 寄存器值
// PCLK = 54 MHz, 目标 100Kbps
// 驱动通过 st,i2c-timing 属性传入预计算值
i2c2: i2c@40012000 {
compatible = "st,stm32mp15-i2c";
clock-frequency = <100000>;
st,i2c-timing = <0x00303D5B>; // 预计算时序
};
// i.MX6: 驱动自动选择 IFDR 分频因子
i2c1: i2c@21a0000 {
compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";
clock-frequency = <100000>; // 驱动自动匹配 IFDR
};
// RK3399: 需要配置 CLKDIV
i2c0: i2c@ff3c0000 {
compatible = "rockchip,rk3399-i2c";
clock-frequency = <100000>;
rockchip,clk-div = <0x42>; // 手动或自动计算
};
4.4 中断与DMA机制差异
中断和DMA是I2C控制器实现非阻塞传输的关键。下表对比三种SoC的中断事件和DMA请求线。
| SoC | 中断事件 | DMA请求线数 | 设备树中断属性 |
|---|---|---|---|
| STM32MP1 | TXIS, RXNE, TC, NACKF, STOPF, ARLO, BERR, OVR | 2 (TX + RX) | interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH> |
| i.MX6 | IIC_IF (传输完成/错误) | 1 (共享) | interrupts = <0 54 IRQ_TYPE_LEVEL_HIGH> |
| RK3399 | MSTX_FIFO_EMPTY, MSRX_FIFO_FULL, ARBITRATION_LOST, NAK | 2 (TX + RX) | interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH> |
调试建议: 在STM32MP1上,如果遇到NACK中断,需要检查
st,i2c-timing是否匹配实际PCLK频率。i.MX6的IIC_IF中断是边沿触发还是电平触发取决于芯片版本,设备树中建议使用IRQ_TYPE_LEVEL_HIGH以保证兼容性。
4.5 设备树绑定差异总结
下表汇总了三种SoC在设备树中描述I2C控制器时的关键属性差异,是编写和移植设备树时的快速参考。
| 设备树属性 | STM32MP1 | i.MX6 | RK3399 |
|---|---|---|---|
compatible |
st,stm32mp15-i2c |
fsl,imx6q-i2c |
rockchip,rk3399-i2c |
reg |
寄存器基址 + 大小 (0x400) | 寄存器基址 + 大小 (0x4000) | 寄存器基址 + 大小 (0x1000) |
clocks |
1个 (PCLK) | 1个 (IPG_CLK) | 1个 (PCLK) |
dmas |
2个 (tx, rx) | 可选 (需外部DMA) | 2个 (tx, rx) |
pinctrl |
必须配置 | 必须配置 | 必须配置 |
wakeup-source |
支持 | 不支持 | 支持 |
移植要点: 当从i.MX6向RK3399移植I2C设备时,需要特别注意
dmas属性的添加,因为RK3399的I2C控制器默认使用DMA传输,而i.MX6的I2C控制器在设备树中通常不配置DMA。同时,pinctrl的引脚配置需要根据SoC的GPIO复用表重新定义。
4.6 本章小结
- STM32MP1:I2Cv2控制器,32位寄存器,支持Fast-mode+,需要精确的时序配置(
st,i2c-timing),适合高速传感器场景。 - i.MX6:VF610 I2C控制器,8位寄存器,无硬件FIFO,时钟分频通过IFDR查找表实现,设备树配置相对简单。
- RK3399:Rockchip自研I2C控制器,32位寄存器,16字节FIFO,内置DMA控制器,设备树需要配置
dmas和rockchip,clk-div。 - 共性:三者都支持7/10位地址、多主模式、硬件仲裁,设备树中都需要配置
compatible、reg、interrupts、clocks和pinctrl。