驱动之路#44:硬件 I2C 和软件 I2C 谁更坑?

驱动之路 #44:硬件 I2C 和软件 I2C 谁更坑?

**先说结论:**能用硬件 I2C,就优先用硬件 I2C;软件 I2C 不是不能用,而是更适合做补救方案。

前面几篇文章聊过 I2C 通信机制、上拉电阻、SMBus 以及 Linux I2C 子系统架构。实际项目里经常还会遇到一个选择:硬件 I2C 和软件 I2C 到底有什么区别?

1. I2C 通信的两种实现方式

硬件 I2C

使用 SoC 内部集成的 I2C 控制器,例如 RK3576 的 I2C0、I2C1、I2C2 等。

软件 I2C

使用两个普通 GPIO,通过软件手动控制电平变化,模拟 SDA/SCL 时序。

简单理解:

  • **硬件 I2C:**专用控制器负责传输。
  • **软件 I2C:**CPU 控制 GPIO,模拟总线时序。

两者都能在 SDA/SCL 上产生 I2C 时序并与外设通信,但在实现方式、稳定性、CPU 占用和适用场景上差别很大。

2. 硬件 I2C 是什么?

硬件 I2C 是芯片内部集成的专用 I2C 控制器。以 RK3576 为例,控制器驱动通常位于:

text 复制代码
kernel-6.1/drivers/i2c/busses/i2c-rk3x.c

开发者不需要手动控制 SDA/SCL 的每一次翻转,通常只需要:

  1. 在设备树中打开对应的 I2C 控制器;
  2. 配置 pinctrl、clock、status 等资源;
  3. 在 I2C 节点下挂载从设备;
  4. 通过设备驱动、i2c-tools 或 i2c_transfer() 访问设备。

真正通信时,硬件控制器会自动完成:

  • Start 条件;
  • 地址发送;
  • 读写位处理;
  • ACK/NACK 检测;
  • 数据收发;
  • Stop 条件。

传输完成后,再通过中断或轮询通知 CPU。

硬件 I2C 的核心特点:时序由硬件保证,CPU 不必一直盯着 SDA/SCL 翻转。

3. 软件 I2C 是什么?

软件 I2C 也叫 GPIO 模拟 I2C。既然 I2C 的本质是 SDA/SCL 两根线的电平变化,就可以使用两个普通 GPIO 手动模拟时序。

典型流程如下:

  1. SCL 高电平时,让 SDA 由高变低,产生 Start;
  2. SCL 拉低,准备数据;
  3. SCL 拉高,采样数据;
  4. 第 9 个时钟读取 ACK;
  5. SCL 高电平时,让 SDA 由低变高,产生 Stop。

Linux 内核已经提供 GPIO 模拟 I2C 驱动:

text 复制代码
drivers/i2c/busses/i2c-gpio.c

配置好 SDA/SCL 对应 GPIO 后,可通过 i2c-gpio 注册一个软件模拟的 I2C adapter,通常不需要从零编写 bit-bang 时序。

**优点:**引脚灵活,只要有两个能正常输入输出的 GPIO,理论上就能模拟一条 I2C 总线。

**代价:**时序依赖软件,CPU 需要参与,稳定性更容易受到系统状态影响。

4. 软件 I2C 为什么更容易踩坑?

软件 I2C 最容易出问题的地方是时序敏感。硬件 I2C 的 SCL 高低电平持续时间、SDA 变化时机、ACK 采样等由硬件控制器处理;软件 I2C 则需要 CPU 配合延时函数控制 GPIO。

一次典型的 bit-bang 流程可能是:

text 复制代码
拉低 SCL
设置 SDA
延时
拉高 SCL
延时
读取 SDA
再拉低 SCL

流程看似简单,但系统负载高、中断频繁或线程被调度时,时序就可能抖动。

  • 裸机环境中,CPU 基本只运行当前代码,时序相对可控。
  • Linux 是多任务系统,线程可能被调度,中断也可能随时进入。

因此,软件 I2C 通常更适合低速、低数据量、非关键外设。

5. 硬件 I2C 与软件 I2C 对比

对比项 硬件 I2C 软件 I2C
实现方式 SoC 内部 I2C 控制器 GPIO 手动模拟时序
时序精度 硬件保证,比较稳定 依赖 CPU 延时,容易抖动
CPU 占用 低 较高
通信速率 支持 100 kHz、400 kHz 等常见速率 通常适合低速场景
稳定性 较高 受系统负载影响
引脚灵活性 受 SoC 复用限制 两个 GPIO 即可模拟
调试难度 主要检查 DTS、pinctrl、硬件连接 还要关注 GPIO 时序、延时和系统负载
适用场景 正式产品、核心外设 临时补救、低速外设、控制器不够用

直白地说:

  • **硬件 I2C:**规矩、稳定、省 CPU;
  • **软件 I2C:**灵活、能救急,但更容易出问题。

6. 什么时候应该用硬件 I2C?

绝大多数正式项目里,都应该优先使用硬件 I2C,尤其是:

  • PMIC/电源管理芯片;
  • 触摸芯片;
  • 摄像头 sensor;
  • 音频 codec;
  • 关键传感器;
  • 需要较高通信速率的外设;
  • 需要长期稳定运行或数据量较大的链路。

例如 PMIC 异常可能影响电源控制,触摸芯片通信异常会直接影响用户体验,摄像头 sensor 配置失败则可能导致整条图像链路无法启动。这类场景不建议为了省事使用软件 I2C。

7. 什么时候可以考虑软件 I2C?

可以考虑软件 I2C 的情况包括:

  • SoC 硬件 I2C 控制器数量不够;
  • 对通信速率要求不高;
  • 外设数据量很小;
  • 只是读取简单状态;
  • 临时调试验证;
  • 硬件设计已经定型,无法改线;
  • 某些 I2C 控制器引脚被其他功能占用。

例如,低速温度传感器几秒钟读取一次数据,使用软件 I2C 通常问题不大。但高频读写或对时序敏感的外设,需要谨慎评估。

8. 工程上的选择原则

可以按下面几条判断:

  1. 能用硬件 I2C,就不要优先考虑软件 I2C;
  2. 核心外设、关键链路尽量使用硬件 I2C;
  3. 软件 I2C 适合低速、低频、低风险场景;
  4. 软件 I2C 更适合救急,不适合作为默认方案;
  5. 必须使用软件 I2C 时,最好用示波器确认 SDA/SCL 波形;
  6. 多设备挂载、长线通信、高速通信不建议使用软件 I2C。

软件 I2C 最大的优势是引脚灵活,不是性能强。若只是因为"配置看起来简单"就用它替代硬件 I2C,后期可能给自己埋坑。

9. Linux 中的软件 I2C 如何接入子系统?

软件 I2C 仍然会注册成一个 i2c_adapter,然后接入 I2C 子系统。从上层看,它和硬件 I2C 很像。

底层可能是:

  • i2c-rk3x.c:硬件控制器;
  • i2c-gpio.c:GPIO 模拟。

最终都可以向上提供一个 I2C adapter,上层设备驱动通常不需要关心底层究竟是哪一种实现,仍可通过下面的接口访问外设:

c 复制代码
i2c_transfer();
i2c_smbus_read_byte_data();
i2c_smbus_write_byte_data();

区别在于执行 master_xfer 的实现不同:

  • 硬件 I2C:由 SoC I2C 控制器驱动完成;
  • 软件 I2C:由 i2c-gpio 通过 GPIO 翻转完成。

这正是 Linux 子系统分层的好处。

10. 总结

硬件 I2C 和软件 I2C 都能实现 I2C 通信,但定位完全不同:硬件 I2C 是首选方案,软件 I2C 是补救方案。

硬件 I2C 的优势

  • 时序稳定;
  • CPU 占用低;
  • 速率更高;
  • 异常处理更完善;
  • 适合正式产品和关键外设。

软件 I2C 的优势

  • 引脚灵活;
  • 不依赖专用 I2C 控制器;
  • 适合低速、低频、临时补救场景。

如果必须做选择:

  1. 能用硬件 I2C,就用硬件 I2C;
  2. 硬件资源确实不够,再考虑 GPIO 模拟;
  3. 核心外设不要轻易使用软件 I2C;
  4. 软件 I2C 一定要看波形,不要只看日志。

很多时候,软件 I2C 不是不能用,而是后期调试变量太多。硬件 I2C 主要查设备树、pinctrl、上拉、电源和地址;软件 I2C 除此之外,还要担心 GPIO 翻转时序、系统调度和中断干扰。

硬件 I2C 坑在配置,软件 I2C 坑在不确定性。

相关推荐
不会就选b1 小时前
Linux之再次理解udp
linux·运维·udp
guo_wen_qiang1 小时前
云服务器kibana环境搭建
linux·运维·服务器
流浪0012 小时前
Linux系统篇42——线程(七) pthread库管理线程的工作流,从创建到回收
linux·操作系统·线程·线程创建到销毁
Dragon~Snow2 小时前
Linux server CentOS stream 10系统构建
linux·运维·centos
嵌入式分享2 小时前
嵌入式分享#19:《嵌入式外设调试思路》--I2C设备篇
单片机·嵌入式硬件
霞姐聊IT2 小时前
服务器RAS软件开发经验分享——从Linux、BMC与BIOS三个层面谈工程实践(二)
linux·服务器
WD137298015572 小时前
WD5030K输入工作电压 7.5‑30V,适合12A 及以内量产项目
stm32·单片机·嵌入式硬件·51单片机
千秋岁rr2 小时前
12.IIC
单片机·嵌入式硬件
高山有多高2 小时前
【Linux笔记】Linux磁盘文件系统
linux