微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 3.4.2内核下的I2C驱动框架解析

3.4.2内核下的I2C驱动框架解析

时间:11-21 来源:互联网 点击:

(void)

{

i2c_unregister_device(at24cxx_client);

}

module_init(at24cxx_dev_init);

module_exit(at24cxx_dev_exit);

MODULE_LICENSE("GPL");

=============================================================

第四种方法:

at24cxx_drv.c源码:

#include "linux/kernel.h"

#include "linux/module.h"

#include "linux/platform_device.h"

#include "linux/i2c.h"

#include "linux/err.h"

#include "linux/regmap.h"

#include "linux/slab.h"

static int __devinit at24cxx_probe(struct i2c_client *client,

const struct i2c_device_id *id)

{

printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

return 0;

}

static int __devexit at24cxx_remove(struct i2c_client *client)

{

printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

return 0;

}

static const struct i2c_device_id at24cxx_id_table[] = {

{ "at24c08", 0 },

{}

};

static int at24cxx_detect(struct i2c_client *client,

struct i2c_board_info *info)

{

// 能运行到这里, 表示该addr的设备是存在的

* 但是有些设备单凭地址无法分辨(A芯片的地址是0x50, B芯片的地址也是0x50)

* 还需要进一步读写I2C设备来分辨是哪款芯片

* detect就是用来进一步分辨这个芯片是哪一款,并且设置info->type

//

printk("at24cxx_detect : addr = 0x%x\n", client->addr);

// 进一步判断是哪一款 //

strlcpy(info->type, "at24c08", I2C_NAME_SIZE);

return 0;

}

static const unsigned short addr_list[] = { 0x60, 0x50, I2C_CLIENT_END };

// 1. 分配/设置i2c_driver //

static struct i2c_driver at24cxx_driver = {

.class = I2C_CLASS_HWMON, // 表示去哪些适配器上找设备 //

.driver = {

.name = "100ask",

.owner = THIS_MODULE,

},

.probe = at24cxx_probe,

.remove = __devexit_p(at24cxx_remove),

.id_table = at24cxx_id_table,

.detect = at24cxx_detect, // 用这个函数来检测设备确实存在 //

.address_list = addr_list, // 这些设备的地址 //

};

static int at24cxx_drv_init(void)

{

// 2. 注册i2c_driver //

i2c_add_driver(&at24cxx_driver);

return 0;

}

static void at24cxx_drv_exit(void)

{

i2c_del_driver(&at24cxx_driver);

}

module_init(at24cxx_drv_init);

module_exit(at24cxx_drv_exit);

MODULE_LICENSE("GPL");

===============================================================

1. 框架

1.1 硬件协议简介

1.2 驱动框架

1.3 bus-drv-dev模型及写程序

a. 设备的4种构建方法(对于以下4种方法建议使用前3种,第四种方法迫不得已情况下使用)

a.1 定义一个i2c_board_info, 里面有:名字, 设备地址

然后i2c_register_board_info(busnum, ...) (把它们放入__i2c_board_list链表)

list_add_tail(&devinfo->list, &__i2c_board_list);

链表何时使用:

i2c_register_adapter > i2c_scan_static_board_info > i2c_new_device

使用限制:必须在 i2c_register_adapter 之前 i2c_register_board_info

所以:不适合我们动态加载insmod

a.2 直接i2c_new_device, i2c_new_probed_device

a.2.1 i2c_new_device : 认为设备肯定存在

a.2.2 i2c_new_probed_device :对于"已经识别出来的设备"(probed_device),才会创建("new")

i2c_new_probed_device

probe(adap, addr_list[i]) // 确定设备是否真实存在 //

info->addr = addr_list[i];

i2c_new_device(adap, info);

a.3 从用户空间创建设备

创建设备

echo at24c08 0x50 > /sys/class/i2c-adapter/i2c-0/new_device

导致i2c_new_device被调用

删除设备

echo 0x50 > /sys/class/i2c-adapter/i2c-0/delete_device

导致i2c_unregister_device

a.4 前面的3种方法都要事先确定适配器(I2C总线,I2C控制器)

如果我事先并不知道这个I2C设备在哪个适配器上,怎么办?去class表示的所有的适配器上查找

有上一些I2C设备的地址是一样,怎么继续分配它是哪一款?用detect函数

static struct i2c_driver at24cxx_driver = {

.class = I2C_CLASS_HWMON, // 表示去哪些适配器上找设备 //

.driver = {

.name = "100ask",

.owner = THIS_MODULE,

},

.probe = at24cxx_probe,

.remove = __devexit_p(at24cxx_remove),

.id_table = at24cxx_id_table,

.detect = at24cxx_detect, // 用这个函数来检测设备确实存在 //

.address_list = addr_list, // 这些设备的地址 //

};

去"class表示的

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top