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

描述

 

欢迎关注,每周更新!☞

本合集分享的是,我当初学习Linux驱动的来时路——《《驱动之路》开篇:自序&前言》。

正文

前面几篇文章,我们已经陆续聊了 I2C 通信机制、上拉电阻、SMBus 关系,以及 Linux I2C 子系统架构。

到这里,基本就能看懂 I2C 的大部分基础概念了。

不过实际项目里,还有一个问题也挺常见:硬件 I2C 和软件 I2C 到底有什么区别?这篇就简单聊聊硬件 I2C 和软件 I2C。

先说结论:

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

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

从实现方式看,I2C 通信大致可以分成两类。

第一类是硬件 I2C。

也就是使用 SoC 内部自带的 I2C 控制器,比如 RK3576 里的 I2C0、I2C1、I2C2 等。

第二类是软件 I2C。

也就是找两个普通 GPIO,通过软件手动控制电平变化,模拟出 SDA / SCL 的时序。

简单理解:

 

硬件 I2C:专用控制器干活软件 I2C:CPU 控 GPIO 硬模拟

 

两者最终都能在 SDA / SCL 上产生 I2C 时序,也都能和 I2C 外设通信。

但实现方式、稳定性、CPU 占用、适用场景差别很大。

2. 硬件 I2C 是什么?

硬件 I2C,就是芯片内部已经集成了专门的 I2C 控制器。

I2C

以 RK3576 为例,I2C 控制器驱动一般在类似路径下:

 

kernel-6.1/drivers/i2c/busses/i2c-rk3x.c、

 

这一层驱动会对接 RK3576 内部的 I2C 硬件模块。

开发者不需要自己手动控制 SDA / SCL 的每一次翻转。

正常情况下,我们只需要:

 

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

 

比如设备树里可能会看到:

I2C

真正通信时,上层只要发起传输请求,硬件控制器就会自动完成:

 

Start;地址发送;读写位;ACK/NACK 检测;数据收发;Stop。

 

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

所以硬件 I2C 最大的特点是:

 

I2C 时序由硬件保证,CPU 不用一直盯着 SDA / SCL 翻电平。

 

这也是为什么实际项目里,能用硬件 I2C 就优先用硬件 I2C。

3. 软件 I2C 是什么?

软件 I2C,也叫 GPIO 模拟 I2C。

它的思路很直接:

既然 I2C 本质就是 SDA / SCL 两根线的电平变化,那我用两个普通 GPIO 手动模拟这些时序,不也能通信吗?

答案是:确实可以。

比如用 GPIOA 做 SDA,用 GPIOB 做 SCL,然后软件依次模拟:

 

SCL 高电平时 SDA 高变低 -> StartSCL 低电平时准备数据SCL 高电平时采样数据第 9 个时钟读取 ACKSCL 高电平时 SDA 低变高 -> Stop

 

这就是软件 I2C 的基本原理。

Linux 内核里已经有现成的 GPIO 模拟 I2C 驱动:

 

drivers/i2c/busses/i2c-gpio.c
I2C

 

所以正常情况下,不需要自己从零写 bit-bang 时序。

在设备树里配置好 SDA / SCL 对应 GPIO 后,就可以通过 i2c-gpio 注册出一个软件模拟的 I2C adapter。

这种方案的好处是:引脚灵活。

只要有两个能正常输入输出的 GPIO,理论上就可以模拟一条 I2C 总线。

但代价也很明显:时序靠软件,CPU 要参与,稳定性更依赖系统状态。

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

软件 I2C 最容易坑的地方,在于它对时序非常敏感。

硬件 I2C 的时序由硬件控制器保证,SCL 拉高多久、SDA 什么时候变化、ACK 什么时候采样,这些都由硬件处理。

软件 I2C 不一样。

它需要 CPU 通过代码控制 GPIO,并通过延时函数模拟时序。

比如:

 

拉低 SCL;设置 SDA;延时;拉高 SCL;延时;读取 SDA;再拉低 SCL;

 

这套流程看起来简单,但一旦系统负载高、中断频繁、调度打断,时序就可能抖动。

在裸机里模拟 I2C 还相对可控,因为 CPU 基本只跑你的代码。

但在 Linux 系统里,情况就复杂很多。

Linux 是多任务系统,当前线程可能被调度出去,中断也可能随时进来。

所以软件 I2C 的时序很难像硬件 I2C 那样稳定。

这也是为什么软件 I2C 通常只适合低速、低数据量、非关键外设。

5. 硬件 I2C 和软件 I2C 对比

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

如果再说得直白一点:

 

硬件 I2C:规矩、稳定、省 CPU;软件 I2C:灵活、能救急,但更容易出幺蛾子。

 

6. 什么时候用硬件 I2C?

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

尤其是这些场景:

 

[ ] PMIC / 电源管理芯片;[ ] 触摸芯片;[ ] 摄像头 sensor;[ ] 音频 codec;[ ] 关键传感器;[ ] 需要较高通信速率;[ ] 需要长期稳定运行;[ ] 数据量相对较大。
这些外设一旦通信异常,影响可能比较大。

 

比如 PMIC 出问题,可能影响电源控制;触摸芯片通信异常,用户直接感知;摄像头 sensor 配置失败,图像链路起不来。

这类场景就不建议为了省事去用软件 I2C。

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

软件 I2C 不是不能用,只是要知道它适合什么场景。

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

 

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

 

比如挂一个低速温度传感器,几秒钟读一次数据,这种场景用软件 I2C 问题一般不大。

但如果你要高频读写数据,或者外设对时序比较敏感,那就要慎重。

8. 实际工作中的选择原则

工程上可以简单按下面几条判断。

 

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

 

这里再强调一点:软件 I2C 最大的优势是引脚灵活,不是性能强。

如果只是因为“软件 I2C 配起来好像简单”,就拿它替代硬件 I2C,后期很可能给自己埋坑。

9. Linux 里软件 I2C 怎么来的?

在 Linux 内核里,软件 I2C 并不神秘。

它仍然会注册成一个 i2c_adapter,然后接入 I2C 子系统。

也就是说,从上层看,它和硬件 I2C 很像。

比如不管底层是:i2c-rk3x.c 硬件控制器

还是:i2c-gpio.c GPIO 模拟

最终都可以向上提供一个 I2C adapter。

所以上层设备驱动一般不需要关心这条总线到底是硬件 I2C 还是软件 I2C。

设备驱动仍然可以通过:

 

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 控制器;适合低速、低频、临时补救场景。

 

如果在项目里要做选择,我的建议很简单:

 

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

 

很多时候,软件 I2C 不是不能用,而是后期调试变量太多。

硬件 I2C 主要查设备树、pinctrl、上拉、电源、地址;软件 I2C 除了这些,还要担心 GPIO 翻转时序、系统调度、中断干扰。

所以要问“硬件 I2C 和软件 I2C 谁更坑?”

我的答案是:硬件 I2C 坑在配置,软件 I2C 坑在不确定性。

(完)

下期可以继续聊:如何更好使用 I2C-Tools ?

本人专注 Linux 嵌入式全栈开发,有项目合作 / 技术支持 / 交个朋友,欢迎后台私信。

更多原创技术文章:《README 2026》。

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分