2. RK平台I2C控制器架构

RK平台的I2C控制器是一个挂载在APB总线上的AMBA从设备,负责实现I2C总线的主机通信协议。理解其硬件框图、寄存器映射、时钟树与频率配置,是进行Sensor I2C通信故障排查的基础。本章将深入剖析RK I2C控制器的内部结构,帮助开发者建立清晰的硬件认知。

2.1 I2C控制器硬件框图

RK I2C控制器内部主要由以下几个核心模块组成:APB接口模块、时钟分频与同步模块、状态机控制模块、数据移位寄存器、以及SCL/SDA引脚控制模块。下图展示了其内部架构与数据流。

RK I2C控制器硬件框图 RK I2C控制器硬件框图 APB总线接口 寄存器读写控制 时钟分频与同步 SCL时钟生成 状态机控制 主/从模式切换 数据移位寄存器 8位数据收发 SCL/SDA引脚控制 开漏输出与滤波 中断与DMA接口 事件通知 说明: APB接口负责寄存器读写;时钟分频模块根据IC_CLK生成SCL;状态机控制数据收发流程; 移位寄存器完成串并转换;引脚控制模块处理开漏输出与毛刺滤波。

各模块功能简述如下表所示:

模块名称 功能描述 故障排查关注点
APB总线接口 负责与CPU进行寄存器读写交互,解析地址与数据 寄存器读写超时、地址对齐错误
时钟分频与同步 根据IC_CLK输入时钟,通过分频系数生成SCL时钟 SCL频率异常、时钟毛刺
状态机控制 管理I2C总线状态(空闲、起始、数据、停止) 状态机卡死、总线超时
数据移位寄存器 实现并行数据与串行数据的转换 数据位丢失、ACK/NACK异常
SCL/SDA引脚控制 控制GPIO复用为I2C功能,提供开漏输出与输入滤波 引脚电平异常、波形畸变
中断与DMA接口 向CPU发送传输完成、错误等中断信号 中断丢失、DMA传输错位

2.2 寄存器映射

RK I2C控制器的寄存器空间通常映射在APB地址段,基地址由芯片手册定义。以下列出核心寄存器及其偏移地址,这些寄存器是驱动开发和故障排查的直接操作对象。

偏移地址 寄存器名称 位宽 功能描述
0x00 IC_CON 32 控制寄存器:主从模式选择、速度模式、重启使能
0x04 IC_TAR 32 目标地址寄存器:从设备地址(7位或10位)
0x08 IC_SAR 32 自身地址寄存器(从模式时使用)
0x10 IC_DATA_CMD 32 数据命令寄存器:读写数据与命令控制
0x14 IC_SS_SCL_HCNT 16 标准模式SCL高电平计数
0x18 IC_SS_SCL_LCNT 16 标准模式SCL低电平计数
0x1C IC_FS_SCL_HCNT 16 快速模式SCL高电平计数
0x20 IC_FS_SCL_LCNT 16 快速模式SCL低电平计数
0x30 IC_INTR_STAT 32 中断状态寄存器:读取当前中断源
0x34 IC_INTR_MASK 32 中断掩码寄存器:使能/屏蔽特定中断
0x38 IC_RAW_INTR_STAT 32 原始中断状态寄存器(不受掩码影响)
0x40 IC_ENABLE 1 控制器使能寄存器
0x44 IC_STATUS 32 状态寄存器:总线活动、FIFO空/满、传输进行中
0x48 IC_TXFLR 5 发送FIFO深度寄存器
0x4C IC_RXFLR 5 接收FIFO深度寄存器
调试提示:在排查I2C通信故障时,优先检查 IC_ENABLE 寄存器确认控制器是否使能,读取 IC_STATUS 判断总线状态,并通过 IC_INTR_STAT 或 IC_RAW_INTR_STAT 查看是否有未处理的中断事件。

2.3 时钟树与频率配置

RK I2C控制器的时钟源通常来自PLL分频后的APB总线时钟(PCLK)或专用外设时钟。SCL频率由时钟分频寄存器精确控制,其计算公式如下:

SCL频率 = IC_CLK / (SCL_HCNT + SCL_LCNT + 7)
其中:
- IC_CLK:输入时钟频率(通常为50MHz或100MHz)
- SCL_HCNT:高电平计数寄存器值(IC_SS_SCL_HCNT 或 IC_FS_SCL_HCNT)
- SCL_LCNT:低电平计数寄存器值(IC_SS_SCL_LCNT 或 IC_FS_SCL_LCNT)
- 7:内部固定延迟(包含上升/下降沿补偿)

时钟树结构如下图所示:

RK I2C时钟树与频率配置 RK I2C时钟树与频率配置 PLL ~594MHz APB分频器 /6 ~ /12 IC_CLK 50/100MHz SCL分频器 HCNT + LCNT SCL输出 100kHz/400kHz SCL频率 = IC_CLK / (SCL_HCNT + SCL_LCNT + 7)。标准模式目标100kHz,快速模式目标400kHz。

不同速度模式下的典型配置参数如下表所示(假设IC_CLK = 50MHz):

速度模式 目标SCL频率 SCL_HCNT SCL_LCNT 实际SCL频率 占空比
标准模式 (Standard) 100 kHz 250 250 98.6 kHz 50%
快速模式 (Fast) 400 kHz 60 60 393.7 kHz 50%
快速模式+ (Fast Plus) 1 MHz 22 22 980.4 kHz 50%
高速模式 (High Speed) 3.4 MHz 6 6 2.63 MHz 50%
常见配置错误:SCL_HCNT和SCL_LCNT的值过小会导致SCL频率超出I2C总线规范上限,造成从设备无法响应。建议在驱动初始化时,根据实际IC_CLK频率动态计算分频系数,并保留一定的余量(通常不超过目标频率的±5%)。

2.4 驱动初始化流程中的时钟配置

在RK平台I2C驱动中,时钟配置通常在 i2c_rockchip_probe() 或 i2c_rockchip_set_scl() 函数中完成。以下是一个典型的时钟配置代码片段:

static void rk3x_i2c_set_scl_freq(struct rk3x_i2c *i2c, unsigned int freq)
{
    unsigned long clk_rate = clk_get_rate(i2c->clk);
    unsigned int scl_hcnt, scl_lcnt;
    unsigned int div;

    /* 计算分频系数,确保SCL频率不超过目标值 */
    div = DIV_ROUND_UP(clk_rate, freq * 2);
    scl_hcnt = div;
    scl_lcnt = div;

    /* 根据速度模式写入对应寄存器 */
    if (freq <= 100000) {
        i2c_writel(i2c, scl_hcnt, REG_SS_SCL_HCNT);
        i2c_writel(i2c, scl_lcnt, REG_SS_SCL_LCNT);
    } else {
        i2c_writel(i2c, scl_hcnt, REG_FS_SCL_HCNT);
        i2c_writel(i2c, scl_lcnt, REG_FS_SCL_LCNT);
    }

    dev_dbg(i2c->dev, "SCL freq: %lu Hz, HCNT: %u, LCNT: %u\n",
            clk_rate / (scl_hcnt + scl_lcnt + 7), scl_hcnt, scl_lcnt);
}
调试建议:在驱动中添加 dev_dbg 或 printk 打印实际计算出的SCL频率,与示波器测量值对比,可以快速定位时钟配置错误。如果实际频率与目标偏差超过10%,应检查IC_CLK时钟源是否稳定,以及分频寄存器写入是否生效。