3. ARM平台I2C控制器概述:常见ARM SoC I2C控制器架构对比

ARM SoC 中的 I2C 控制器虽然都遵循 I²C 总线协议标准,但不同厂商(NXP、ST、Allwinner)在寄存器布局、时钟树设计、DMA 集成和中断处理上存在显著差异。理解这些差异是编写可移植驱动和快速定位硬件故障的前提。本节从架构层面对比三款主流 ARM SoC 的 I2C 控制器。

3.1 控制器架构对比总览

下表从核心参数、时钟源、数据路径和调试特性四个维度对比 i.MX6ULL、STM32MP157 和 Allwinner H3 的 I2C 控制器。

对比维度 i.MX6ULL (NXP) STM32MP157 (ST) Allwinner H3 (全志)
控制器名称 I2C-I.MX (兼容飞思卡尔) I2Cx (ST 标准外设) TWI (Two Wire Interface)
总线速率 标准 100kHz / 快速 400kHz / 高速 3.4MHz 标准 100kHz / 快速 400kHz / 快速+ 1MHz 标准 100kHz / 快速 400kHz
时钟源 IPG_CLK (通常 66MHz) PCLKx (APB 时钟, 通常 50-90MHz) APB2_CLK (通常 100-200MHz)
FIFO 深度 64 字节 (发送/接收共用) 8 字节 (发送/接收独立) 8 字节 (发送/接收共用)
DMA 支持 支持 (需配置 SDMA) 支持 (需配置 MDMA 或 DMA) 不支持 (仅 PIO 模式)
中断事件 单中断线 (状态寄存器轮询) 多中断线 (TX/RX/ERR 独立) 单中断线 (状态寄存器轮询)
寄存器宽度 32-bit 32-bit 32-bit
调试特性 无专用调试寄存器 带超时计数器 (TIMEOUT) 无专用调试寄存器
架构选择提示: i.MX 系列适合需要高速传输和大 FIFO 的场景;STM32MP1 的独立中断和超时机制更适合可靠性要求高的工业控制;Allwinner H3 的 TWI 控制器结构简单,适合低功耗 IoT 设备,但缺乏 DMA 支持,大数据量传输时 CPU 占用较高。

3.2 架构框图对比

下图展示了三种控制器的内部数据路径和关键模块差异。注意 i.MX 的 FIFO 位于 APB 桥与移位寄存器之间,而 STM32MP1 的 FIFO 与移位寄存器之间有独立的时钟同步模块。

三种 ARM SoC I2C 控制器架构对比 i.MX6ULL I2C 控制器 APB 桥 64B FIFO 移位寄存器 SCL/SDA STM32MP157 I2C 控制器 APB 桥 8B TX FIFO 时钟同步 SCL/SDA Allwinner H3 TWI 控制器 APB2 桥 8B FIFO 移位寄存器 SCL/SDA 说明:i.MX 使用大 FIFO 减少中断频率;STM32MP1 增加时钟同步模块以支持多主模式;Allwinner H3 结构最精简,无 DMA 路径。

3.3 寄存器布局差异

三种控制器的寄存器偏移地址和功能定义差异很大。驱动开发时必须使用对应的 struct 映射。以下是各控制器关键寄存器的偏移对比。

功能 i.MX6ULL (I2C_I.MX) STM32MP157 (I2Cx) Allwinner H3 (TWI)
控制寄存器 I2C_IADR (0x00) I2C_CR1 (0x00) TWI_CTL (0x00)
分频寄存器 I2C_IFDR (0x04) I2C_TIMINGR (0x10) TWI_CLK (0x04)
数据寄存器 I2C_I2DR (0x0C) I2C_TXDR (0x28) / I2C_RXDR (0x30) TWI_DATA (0x0C)
状态寄存器 I2C_I2SR (0x08) I2C_ISR (0x18) TWI_STA (0x08)
中断使能 I2C_I2CR (控制位内嵌) I2C_CR1 (TXIE/RXIE/ERRIE) TWI_INT (0x10)
超时计数器 无 I2C_TIMEOUTR (0x40) 无
寄存器映射注意事项: STM32MP1 的 I2C_TIMINGR 寄存器使用 6-bit 的 PRESC、SCLL、SCLH 字段来精确控制时序,而 i.MX 使用 I2C_IFDR 的 6-bit 分频值选择预定义分频比。Allwinner H3 的 TWI_CLK 寄存器直接设置时钟周期数,三者配置方式完全不同。

3.4 时钟树与速率配置

I2C 总线速率由输入时钟和分频系数共同决定。三种 SoC 的时钟树路径如下:

  • i.MX6ULL: IPG_CLK (66MHz) → IFDR 分频器 → I2C 模块时钟。IFDR 寄存器选择 0-63 分频值,对应分频比 22-3200。
  • STM32MP157: PCLKx (APB 时钟) → TIMINGR 的 PRESC 预分频 → SCL 高/低电平计数器。支持更精细的占空比控制。
  • Allwinner H3: APB2_CLK (200MHz) → TWI_CLK 寄存器设置时钟周期数。公式:SCL = APB2_CLK / (2 * (CLK_DIV + 1))。
三种 SoC I2C 时钟树路径 i.MX6ULL IPG_CLK IFDR SCL STM32MP157 PCLKx TIMINGR SCL Allwinner H3 APB2_CLK TWI_CLK SCL

3.5 中断与 DMA 路径差异

中断处理方式直接影响驱动设计的复杂度。STM32MP1 的独立中断线允许更精细的错误处理,而 i.MX 和 Allwinner 需要软件轮询状态寄存器来区分事件。

  • i.MX6ULL: 单中断线 I2C_INT。中断服务程序必须读取 I2C_I2SR 判断是传输完成、仲裁丢失还是 NAK 接收。
  • STM32MP157: 三根独立中断线:TXIS(发送缓冲区空中断)、RXNE(接收缓冲区非空中断)、ERRI(错误中断)。驱动可以分别注册回调。
  • Allwinner H3: 单中断线 TWI_IRQ。中断标志位在 TWI_STA 寄存器中,包括 TF(传输完成)、A_F(地址失败)、GC_F(通用调用)等。
中断处理陷阱: Allwinner H3 的 TWI_STA 寄存器在读取后会自动清零部分标志位,如果 ISR 中未及时保存状态,可能导致丢失中断事件。建议在 ISR 入口立即读取并保存整个 TWI_STA 值。

3.6 故障排查特性对比

在硬件调试阶段,不同 SoC 提供的调试能力差异很大。STM32MP1 内置的超时计数器是排查总线挂死问题的利器。

调试场景 i.MX6ULL STM32MP157 Allwinner H3
SCL 被拉低 只能通过软件超时检测 硬件超时计数器自动复位总线 只能通过软件超时检测
从机 NAK 状态寄存器 I2SR[IAL] 置位 ISR[NACKF] 标志位 + 独立中断 STA[A_F] 标志位
仲裁丢失 I2SR[IAL] 置位 ISR[ARLO] 标志位 STA[A_F] 标志位
总线错误 无专用标志 ISR[BERR] 标志位 STA[A_F] 标志位
调试寄存器 无 I2C_TIMEOUTR (可配置超时值) 无

3.7 驱动适配要点总结

基于上述架构差异,在编写跨平台 I2C 驱动时需重点关注以下适配点:

  1. 时钟配置抽象: 将分频计算封装为平台相关函数,例如 i2c_set_bus_speed() 内部调用不同的寄存器操作。
  2. 中断处理统一: 使用状态机模式,将不同平台的中断事件映射到统一的传输状态(IDLE、START、TX、RX、STOP、ERROR)。
  3. FIFO 管理: i.MX 的 64 字节 FIFO 支持批量传输,而 Allwinner 的 8 字节 FIFO 需要更频繁的中断响应。
  4. 错误恢复: STM32MP1 可以利用硬件超时自动恢复,其他平台需要在软件中实现总线复位序列(发送 9 个 SCL 脉冲 + STOP 条件)。
实战建议: 在驱动初始化阶段,通过读取 SoC 的 ID 寄存器或设备树 compatible 属性,动态选择对应的寄存器操作函数集。这样可以在一个驱动框架下支持多种控制器,减少代码冗余。