驱动之路#45:I2C-Tools 不止 i2cdetect 但真正调试 I2C 外设时,光懂这些还不够。
实际工作中,经常会遇到这种情况:
设备树也配了;驱动也编进去了;供电看起来也正常;但设备就是不 probe,或者一直通信失败。
这时候怎么办?
不要一上来就改驱动,也不要立刻怀疑内核。
更高效的做法是:先用 I2C-tools 看看硬件和总线到底通不通。
这篇就聊聊 I2C-tools 在实际调试中的用法。
I2C-tools 是一套用户空间 I2C 调试工具。
常用命令主要有:
i2cdetecti2cgeti2cseti2cdump
它们的作用可以简单理解为:
i2cdetect:扫描总线和设备地址;i2cget :读取单个寄存器;i2cset :写入寄存器;i2cdump :批量读取寄存器。
这几个命令,基本就够覆盖大多数 I2C 调试场景。
它最大的价值是:
不用写驱动,也能直接和 I2C 设备“对话”。
这在调试阶段非常香。
尤其是判断问题属于硬件、设备树、驱动,还是外设本身时,I2C-tools 往往能帮我们快速缩小范围。
在项目开发中,调一个 I2C 外设,如果每改一次都要:
改设备树;重新编译 dtb;烧录;重启;看日志;再改;再烧;再重启。
那效率会非常低。
而 I2C-tools 可以在系统起来后,直接在命令行访问 I2C 总线。
比如:
i2cdetect -y 2
几秒钟就能知道 I2C2 总线上有没有设备应答。
如果扫不到设备,那就优先查硬件、供电、复位、pinctrl、上拉、地址。
如果能扫到设备,但驱动不 probe,那就再去查设备树 compatible、reg、驱动匹配表。
这样思路就清楚很多。
所以 I2C-tools 的核心作用不是“替代驱动”,而是:在写驱动之前,先快速确认底层通信是否正常。
用 I2C-tools 之前,至少要先知道三个东西。
1. 使用哪一路 I2C 总线;2. 外设的 I2C 地址是多少;3. 要读写哪个寄存器。
翻译成工程语言就是:
用哪个 I2C 控制器,访问哪个 I2C 设备,读写哪个寄存器。
比如:
I2C 总线:i2c-2设备地址:0x38寄存器地址:0x00
那么后面命令基本都是围绕这三个信息展开。
先看开发板当前有哪些 I2C 总线:
i2cdetect -l

这里的 i2c-0 / 6,就对应 /dev/i2c-0 / 6。
后面使用工具时,-y 0 里的 0 就是这个总线编号。
如果你预期应该有 /dev/i2c-0,但这里完全看不到,那就要先检查:
[ ] 对应 I2C 控制器设备树是否 status = "okay";[ ] pinctrl 是否配置正确;[ ] 内核是否打开 I2C 控制器驱动;[ ] i2c-dev 是否启用;[ ] 设备节点是否生成。
确认总线存在后,就可以扫描设备地址:
i2cdetect -y 6

其中:
-y:跳过交互确认;6 :I2C 总线编号。
输出结果里常见三种情况:
--:表示没有该地址对应的设备;UU:表示有该设备并且它已经有驱动程序;数值:表示有该设备但是没有对应的设备驱动。
--表示这个地址没有设备应答。
如果整张表都是 --,说明总线上没有扫到任何设备。
这时先别急着改驱动,重点查:
[ ] 外设供电是否正常;[ ] reset / enable 是否释放;[ ] SDA / SCL 是否接反;[ ] 上拉电阻是否存在;[ ] pinctrl 是否复用到 I2C;[ ] 设备地址是否搞错;[ ] 当前扫描的总线编号是否正确。
比如看到:38
说明地址 0x38 上有设备应答,并且当前没有被内核驱动占用。
这通常是好消息,说明硬件通信至少是通的。
UU
UU 表示该地址上有设备,但已经被内核驱动绑定。
比如某个触摸芯片已经被驱动 probe 成功,i2cdetect 可能就会显示 UU。
这时候如果你再强行访问它,可能会提示设备忙。
如果已经知道设备地址和寄存器地址,就可以用 i2cget 读取单个寄存器。
格式如下:
i2cget -y <bus> <chip_addr> <reg_addr>
比如读取 I2C2 总线上 0x38 设备的 0x00 寄存器:
i2cget -y 2 0x38 0x00
如果输出:0x18
说明访问成功,读到了寄存器值。
这个命令很适合验证:
[ ] 设备地址是否正确;[ ] 寄存器是否能正常读取;[ ] 外设是否已经初始化;[ ] I2C 通信是否正常。
不过注意,不是所有 I2C 设备都支持这种“寄存器地址 + 读取一个字节”的访问方式。
有些设备读写流程比较特殊,用 i2cget 不一定能直接读出来,这时候要结合芯片手册看通信格式。
如果想一次性看看设备寄存器分布,可以使用:
i2cdump -y 2 0x38
它会尝试批量读取设备寄存器。
输出类似:
0 1 2 3 4 5 6 7 8 9 a b c d e f00: 18 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
这个命令适合快速观察寄存器变化。
比如:
修改配置前 dump 一次;修改配置后 dump 一次;对比哪些寄存器发生变化。
但也要注意:
i2cdump 不是所有设备都适合乱扫。
有些设备的某些寄存器读一次会清状态,有些地址可能触发特殊行为。特别是 PMIC、触摸、摄像头 sensor 这类设备,批量 dump 前最好先看手册。
调试归调试,别把设备状态扫乱了。
如果需要写设备寄存器,可以使用 i2cset。
格式如下:
i2cset -y <bus> <chip_addr> <reg_addr> <value>
比如向 I2C2 总线 0x38 设备的 0xE1 寄存器写入 0x08:
i2cset -y 2 0x38 0xE1 0x08
写完后,可以再读回来确认:
i2cget -y 2 0x38 0xE1
当然,并不是所有寄存器都支持读回。有些寄存器是写命令型寄存器,写入后不会保存原值。
所以还是那句话:
i2cset 前一定要看芯片手册,别对着未知寄存器乱写。
尤其是 PMIC、电源管理、屏幕、电机驱动这类设备,乱写寄存器可能直接导致系统异常。
前面说过,如果 i2cdetect 显示 UU,说明该设备已经绑定内核驱动。
这时候直接用 i2cget / i2cset 访问,可能会提示 busy。
有时候可以加 -f 强制访问:
i2cget -f -y 2 0x38 0x00
但这里要小心。
-f 是强制访问,可能和内核驱动同时操作同一个设备,导致状态混乱。
更稳妥的做法是:临时解绑驱动。
比如某个设备绑定在 4-005a 上,可以通过 sysfs unbind:
echo 4-005a > /sys/bus/i2c/drivers/drv260x-haptics/unbind
格式一般是:
<bus>-<addr>
比如:
4-005a:I2C4 总线,设备地址 0x5a
解绑后,再用 i2c-tools 访问设备会更安全一些。
调试完成后,如果需要重新绑定,可以再 bind 回去,或者重启系统。
很多人刚开始会疑惑:
i2c-tools 是应用层工具,应用层怎么能直接访问硬件?
这里就要回到前面讲过的 I2C 子系统架构了。

Linux 内核里有一个通用驱动:
drivers/i2c/i2c-dev.c
它会为每个 I2C adapter 创建字符设备节点:
/dev/i2c-0/dev/i2c-1/dev/i2c-2...
i2c-tools 本质上就是通过这些设备节点,调用内核提供的 I2C 访问接口。
大致链路是:
i2c-tools↓/dev/i2c-X↓i2c-dev.c↓i2c-core↓I2C 控制器驱动↓I2C 外设
所以并不是没有驱动。
而是 Linux 内核已经帮我们准备好了一个通用 I2C 用户空间访问驱动。
这也是 i2c-tools 能工作的根本原因。
实际调试时,不用记太多花里胡哨的命令。
我一般按下面这个流程走:
# 1. 查看系统有哪些 I2C 总线
i2cdetect -l
# 2. 扫描目标总线
i2cdetect -y 2
# 3. 读取设备 ID / 状态寄存器
i2cget -y 2 0x38 0x00
# 4. 必要时写初始化寄存器
i2cset -y 2 0x38 0xE1 0x08
# 5. 批量查看寄存器
i2cdump -y 2 0x38
这套命令基本够应付大多数 I2C 外设的前期验证。
如果这些都不通,就别急着调驱动,先回头查:
[ ] 总线编号是否正确;[ ] 设备地址是否正确;[ ] 供电是否正常;[ ] reset / enable 是否释放;[ ] SDA / SCL 是否接反;[ ] 上拉电阻是否正确;[ ] pinctrl 是否配置正确;[ ] 设备是否已被驱动占用。
I2C-tools 在嵌入式 Linux 调试里非常实用。
它不是用来替代正式驱动的,而是用来快速验证:
I2C 总线是否存在;设备地址是否应答;寄存器是否能读写;硬件连接是否基本正常;问题到底更像硬件问题还是驱动问题。
其中最常用的几个命令就是:
i2cdetect -l 查看 I2C 总线i2cdetect -y X 扫描指定总线i2cget 读取寄存器i2cset 写寄存器i2cdump 批量读取寄存器
最后再啰嗦一句:i2c-tools 很好用,但不要乱用。
尤其是 i2cset 和 i2cdump,对某些设备可能有副作用。调试前最好先看芯片手册,确认寄存器读写方式。
Linux 知识很多,不必一口气全背下来。
工具也是一样,真正高频有用的先掌握,剩下的用到再查。
能解决问题,就是好工具。
若有不严谨之处,欢迎交流;如果对你有帮助,也别手下留情,点赞、关注、转发安排一下。
(完)
下期可以继续聊:I2C 信号如何测试与分析?
本人专注 Linux 嵌入式全栈开发,有项目合作 / 技术支持 / 交个朋友,欢迎后台私信。
全部0条评论
快来发表一下你的评论吧 !