树莓派 3b+ 没有 /dev/i2c-*
Posted Li-Yongjun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树莓派 3b+ 没有 /dev/i2c-*相关的知识,希望对你有一定的参考价值。
引言
今天,使用树莓派驱动 mpu6050 时,发现 /dev 目录下没有 i2c-0、i2c-1 类似的文件。查看 BananaPi M1 中是存在的。
咦?树莓派中的 i2c 设备文件去哪了?
环境
硬件:树莓派 3b+
软件:buildroot,make O=RPi3/ raspberrypi3_defconfig
问题
使用 buildroot 编译出来的 sdcard.img 烧录到 SD 卡运行后,在 /dev 目录下没有生成 i2c-0、i2c-1 类似的文件。
相关原因
由于 buildroot 支持的板子只有 raspberrypi3,没有 3b+ ,所以使用 3b+ 的用户需要自己再适配下。
原因 1:i2c-dev.ko
内核需要开启在 /dev 目录下产生 i2c 设备文件的功能—— I2C device interface,
我这边是将其编译成了模块(M),不然要替换 Kernel,比较麻烦,不利于调试。
编译好后,会生成 i2c-dev.ko。
兴致冲冲地跑去将 i2c-dev.ko 安装到内核,想着问题就解决了。
没成想,安装完后 /dev 目录下依然没有产生 i2c-* 文件。
🙄🙄🙄 什么情况。。。
查看 /proc/devices
# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
5 ttyprintk
7 vcs
10 misc
13 input
14 sound
29 fb
89 i2c
128 ptm
136 pts
...
已然看到 89 i2c,说明 i2c 驱动已经注册成功了啊,为什么不产生 /dev/i2c-* 呢?
那就手动创建一下
mknod /dev/i2c-1 c 89 1
竟然能够创建成功,那就使用一下
# i2cdetect -y 1
i2cdetect: can't open '/dev/i2c-1': No such device or address
报错了,说明驱动还是有问题。
原因 2:i2c-bcm2835.ko
束手无策,只能查看源码了,打开 i2c-dev.c,
module_init(i2c_dev_init);
i2c_dev_init()
i2c_for_each_dev(NULL, i2cdev_attach_adapter);
i2cdev_attach_adapter()
dev_set_name(&i2c_dev->dev, "i2c-%d", adap->nr);
cdev_device_add()
看到是在 i2cdev_attach_adapter() 中创建 “i2c-%d” 文件的。
没有执行到这里?
经过加 printk() 调试,发现果真没有执行过 i2cdev_attach_adapter(),
那是哪个条件不满足呢?
那就追踪它的调用者 i2c_for_each_dev()
i2c_for_each_dev()
bus_for_each_dev()
while (!error && (dev = next_device(&i)))
error = fn(dev, data);
原来是没有找到 device,那它在找什么设备呢?为什么没找到呢?
最后发现,原来它是在找 I2C adaptor 或者叫 I2C controller(我认为它俩是一个东西的不同叫法),
树莓派 3b+ 的 I2C controller 如下
咦?M?那就去安装它
# insmod /lib/modules/5.10.92-v7/kernel/drivers/i2c/busses/i2c-bcm2835.ko
再次查看 /dev 目录,
还是没有 i2c-*
崩溃!!!
原因 3:设备树
最后发现,原来是安装了 I2C 控制器的驱动,但是设备树里面并没有让 I2C 控制器使能,也就是说系统中只有驱动,没有硬件
使能 I2C 控制器编译出 bcm2710-rpi-3-b-plus.dtb 后,使用上一篇文章介绍的方法,更新到 SD 卡中,重启并执行如下命令
# insmod /lib/modules/5.10.92-v7/kernel/drivers/i2c/i2c-dev.ko
# insmod /lib/modules/5.10.92-v7/kernel/drivers/i2c/busses/i2c-bcm2835.ko
检查
# ls /dev/i2c-*
/dev/i2c-1 /dev/i2c-2
哇!终于有了
使用
# i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
漂亮!
总结
- I2C 总线在 kernel 中就一个,bus->name = “i2c”
- 在树莓派 3b+ SOC 中,有两个 I2C 控制器,i2c1、i2c2。它们是同种类型的器件,所以使用相同的驱动:i2c-bcm2835.ko。
- 在设备树中填写这两个控制器,在安装 i2c-bcm2835.ko 驱动时,就会通过 i2c bus 对 驱动 和 外设 进行匹配,匹配之后,就会在 /dev 目录产生两个设备节点文件 i2c-1、i2c-2,这两个设备节点文件就对应两个 I2C 控制器。
- 对这两个设备文件读写,就会在对应的引脚发出 I2C 信号。这样就可以在应用层写具体外设(如 mpu6050)的驱动代码了,如《Banana Pi M1 读取 MPU6050(Shell 脚本方式)》。
- 通过上面这点,就能明白,I2C 控制器 及其 驱动,I2C 外设 及其 驱动,的区别与联系了。
以上是关于树莓派 3b+ 没有 /dev/i2c-*的主要内容,如果未能解决你的问题,请参考以下文章