linux内核的总线-设备-驱动模型,当总线上的设备与总线上的驱动匹配时,就会调用驱动的probe函数,完成一系列的操作
I2C也是内核的一种总线
一、I2C设备的4种构建方法
1、静态注册设备
(1)定义一个 i2c_board_info 结构体,有名字,和设备地址
static struct i2c_board_info my_i2c_dev_info = {
I2C_BOARD_INFO("my_i2c_dev", 0x2d),
};
(2)注册设备
i2c_register_board_info(int busnum, struct i2c_board_info const * info, unsigned n)
* busnum:哪一条总线,也就是选择哪一个i2c控制器
* info:i2c设备信息
* n:info中有几个设备
i2c_register_board_info做了什么?
i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len)
{
devinfo->busnum = busnum; /* 选择i2c总线 */
devinfo->board_info = *info; /* 绑定设备信息 */
list_add_tail(&devinfo->list, &__i2c_board_list); /* 将设备信息添加进链表中 */
}
在哪里使用了 __i2c_board_list 这个链表?
i2c_scan_static_board_info(struct i2c_adapter *adapter)
list_for_each_entry(devinfo, &__i2c_board_list, list) /* 遍历i2c设备链表 */
i2c_new_device(adapter, &devinfo->board_info); /* 创建一个i2c_client设备 */
struct i2c_client *client;
在哪里调用了 i2c_scan_static_board_info 这个函数?
int i2c_register_adapter(struct i2c_adapter *adap)
{
i2c_scan_static_board_info(adap);
}
adapter是i2c设备器,也就是i2c主机控制器,在启动内核时已经被注册了
调用关系如下
内核启动
int i2c_register_adapter(struct i2c_adapter *adap)
i2c_scan_static_board_info(adap)
list_for_each_entry(devinfo, &__i2c_board_list, list)
所以使用这个方法添加i2c设备,每次都要重新编译内核,无法动态注册i2c设备,不适合我们动态加载insmod
2、直接i2c_new_device,i2c_new_probe_device
i2c_new_device:
struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
* adap:指定i2c设备器,以后访问设备的时候,使用过哪一个设备器(i2c主机控制器)去访问
* info:指定i2c设备信息
i2c_new_device注册i2c设备的代码
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/slab.h>
s