2. RK平台I2C控制器架构
RK平台的I2C控制器是一个挂载在APB总线上的AMBA从设备,负责实现I2C总线的主机通信协议。理解其硬件框图、寄存器映射、时钟树与频率配置,是进行Sensor I2C通信故障排查的基础。本章将深入剖析RK I2C控制器的内部结构,帮助开发者建立清晰的硬件认知。
2.1 I2C控制器硬件框图
RK I2C控制器内部主要由以下几个核心模块组成:APB接口模块、时钟分频与同步模块、状态机控制模块、数据移位寄存器、以及SCL/SDA引脚控制模块。下图展示了其内部架构与数据流。
各模块功能简述如下表所示:
| 模块名称 | 功能描述 | 故障排查关注点 |
|---|---|---|
| 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:内部固定延迟(包含上升/下降沿补偿)
时钟树结构如下图所示:
不同速度模式下的典型配置参数如下表所示(假设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时钟源是否稳定,以及分频寄存器写入是否生效。