2. RK平台I2C控制器架构
瑞芯微RK系列SoC内部集成了多个I2C控制器(I2C Controller),用于与Sensor、PMIC、EEPROM等外设通信。理解其硬件框图、寄存器模型、时钟树与速率配置,是解决I2C通信问题的基石。
2.1 RK I2C控制器硬件框图
RK I2C控制器是一个符合I2C总线标准的主机控制器,支持标准模式(100kHz)、快速模式(400kHz)和高速模式(3.4MHz)。其内部主要由以下几个核心模块组成:
- APB接口模块:负责与系统总线(APB)连接,处理寄存器读写与中断信号。
- 时钟分频器:根据输入的模块时钟(I2C_CLK)和配置的分频系数,产生SCL时钟。
- 状态机与控制逻辑:管理I2C总线的启动、停止、数据收发、ACK/NACK检测等时序状态。
- 数据缓冲器(TX/RX FIFO):用于暂存待发送和已接收的数据,深度通常为8或16字节。
- 中断控制器:产生传输完成、接收FIFO非空、仲裁丢失、错误等中断事件。
调试提示: 当I2C通信失败时,首先检查APB接口模块的寄存器是否可正常读写。如果读回全为0或全为F,说明控制器未正确使能或时钟未开启。
2.2 关键寄存器描述
RK I2C控制器的寄存器基地址在芯片数据手册中定义,每个控制器占用约0x1000地址空间。以下是驱动开发中最常操作的几个寄存器:
| 偏移地址 | 寄存器名称 | 位宽 | 功能描述 |
|---|---|---|---|
| 0x0000 | I2C_CON | 32 | 控制寄存器:使能控制器、设置主从模式、软件复位 |
| 0x0004 | I2C_CLKDIV | 32 | 时钟分频寄存器:配置SCL高低电平的分频系数 |
| 0x0008 | I2C_MRXADDR | 32 | 从机地址寄存器:设置目标从设备地址(7位或10位) |
| 0x000C | I2C_MRXCNT | 32 | 接收数据计数寄存器:配置本次主接收的数据字节数 |
| 0x0010 | I2C_MRXBUF | 32 | 接收数据缓冲寄存器:读取接收到的数据 |
| 0x0014 | I2C_MTXBUF | 32 | 发送数据缓冲寄存器:写入待发送的数据 |
| 0x0018 | I2C_MSTART | 32 | 启动传输寄存器:写1触发一次I2C传输 |
| 0x001C | I2C_ISR | 32 | 中断状态寄存器:指示传输完成、错误等中断源 |
寄存器操作注意事项:
- 写
I2C_MSTART寄存器前,必须确保I2C_CON中的使能位已置1。 - 读取
I2C_MRXBUF前,应先检查I2C_ISR中的接收FIFO非空标志。 - 在配置
I2C_CLKDIV时,建议先关闭控制器使能,配置完成后再重新使能。
2.3 时钟树与速率配置
I2C控制器的SCL时钟频率由 模块输入时钟(I2C_CLK) 和 分频寄存器(I2C_CLKDIV) 共同决定。时钟树路径如下:
- PLL输出:通常由系统PLL(如GPLL、CPLL)产生高频时钟。
- 时钟门控与分频:经过CRU(Clock & Reset Unit)模块的时钟门控和预分频,生成
I2C_CLK。 - I2C控制器内部:
I2C_CLK进入控制器,经过I2C_CLKDIV寄存器配置的分频器,最终产生SCL。
2.3.1 速率计算公式
SCL时钟频率的计算公式如下:
SCL频率 = I2C_CLK / ( (CLKDIV_LOW + 1) + (CLKDIV_HIGH + 1) + 3 )
其中:
I2C_CLK:模块输入时钟频率(单位Hz)。CLKDIV_LOW:I2C_CLKDIV寄存器中SCL低电平分频系数(位[15:8])。CLKDIV_HIGH:I2C_CLKDIV寄存器中SCL高电平分频系数(位[7:0])。+3:固定内部延迟周期。
2.3.2 典型配置示例
假设 I2C_CLK = 99 MHz,需要配置SCL为 400 kHz(快速模式):
// 目标SCL频率: 400 kHz
// 99,000,000 / 400,000 = 247.5
// 选择 CLKDIV_LOW = CLKDIV_HIGH = 120
// 实际频率 = 99,000,000 / (121 + 121 + 3) = 99,000,000 / 245 ≈ 404 kHz
I2C_CLKDIV = (120 << 8) | 120; // 0x7878
关键点:
- 为保证SCL占空比接近50%,通常设置
CLKDIV_LOW与CLKDIV_HIGH相等或相近。 - 在设备树中,通过
clock-frequency属性指定目标速率,驱动内部会根据I2C_CLK自动计算并配置I2C_CLKDIV。 - 如果配置后的SCL频率与目标值偏差超过10%,可能导致从设备时序不满足,出现通信错误。
2.4 设备树中I2C控制器节点示例
在RK平台的设备树(.dts)中,I2C控制器节点通常如下所示:
i2c2: i2c@ff130000 {
compatible = "rockchip,rk3399-i2c";
reg = <0x0 0xff130000 0x0 0x1000>;
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;
clock-names = "i2c", "pclk";
clock-frequency = <400000>; // 目标SCL频率: 400kHz
status = "disabled";
};
各字段说明:
| 属性 | 说明 |
|---|---|
compatible |
匹配对应SoC的I2C驱动,如 rockchip,rk3399-i2c |
reg |
控制器寄存器基地址和地址空间大小 |
interrupts |
中断号及触发类型 |
clocks |
模块时钟(SCLK)和APB接口时钟(PCLK) |
clock-frequency |
目标SCL总线频率,驱动据此配置分频寄存器 |
调试技巧: 如果I2C通信不稳定,可以在设备树中临时将
clock-frequency 降低到100000(标准模式),排除速率过高导致的时序问题。同时,使用示波器测量SCL引脚的实际频率,与配置值对比,验证时钟树配置是否正确。