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非空、仲裁丢失、错误等中断事件。
RK I2C控制器硬件框图 APB接口模块 时钟分频器 状态机与控制逻辑 TX FIFO (8x8) RX FIFO (8x8) 中断控制器 I2C Bus (SCL / SDA)
调试提示: 当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) 共同决定。时钟树路径如下:

  1. PLL输出:通常由系统PLL(如GPLL、CPLL)产生高频时钟。
  2. 时钟门控与分频:经过CRU(Clock & Reset Unit)模块的时钟门控和预分频,生成 I2C_CLK。
  3. I2C控制器内部:I2C_CLK 进入控制器,经过 I2C_CLKDIV 寄存器配置的分频器,最终产生SCL。
I2C时钟树与速率配置路径 PLL (GPLL/CPLL) CRU (门控+预分频) I2C控制器 SCL输出 ~594 MHz ~99 MHz 分频后 I2C_CLKDIV

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引脚的实际频率,与配置值对比,验证时钟树配置是否正确。