i2c总线驱动流程

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

======================================================================
i2c 总线驱动框
static struct i2c_driver at24c02_driver //构建设备驱动
static unsigned short ignore[] = {I2C_CLIENT_END};

/* 每个I2C设备都有一个规定的地址,看芯片手册 */
static unsigned short at24c02_addr[] = { 0xa0, I2C_CLIENT_END };

static struct i2c_client_address_data at24c02_addr_data = {
.normal_i2c = at24c02_addr,
.probe = ignore,
.ignore = ignore,
};

static struct i2c_client *at24c02_client;
static char name[] = "at24c02";

static int major;
static struct class *at24c02_class;
static unsigned char at24c02_buf[1024];
======================================================================
4.构造i2c_drivet
static struct i2c_driver at24c02_driver={
.driver={
.name="at24c02",},
.attache_adapter=at24c02_attach_adapter, //识别i2c设备函数 探测函数
.detach_client =at24c02_detach_client, //释放操作的函数
};
=========================================================================
5,at24c02_attach_adapter函数实现 探测函数
static int at24c02_attach_adapter(struct i2c_adapter *adapter)
{
return i2c_probe(adapter,&at2402c_addr_data,at24c02_detect);
}
//i2c_probe首先会确定是否存在地址为0x50的设备 如果存在,则会使用at24c02_detech处理
==========================================================================
6,at24c02_detech函数实现
static int at24c02_detect(struct i2c_adapter *adap,int addr,int kind)
{
int rc;
int value;
6.1 分配一个i2c_client 结构体
at24c02_client=lzalloc(sizeof(struct i2c_client),GFP_KERNEL);
if(!at24c02_client)
{
return -ENOMEM; //分配失败
}
6.2 初始化i2c_client结构体
strncpy(at24c02_client->name, name, strlen(name)+1);

at24c02_client->addr = addr; /* 0x50 */
at24c02_client->adapter = adap;
at24c02_client->driver = &at24c02_driver;
6.3 将i2c_client注册到子系统
这里会调用到i2c_attach_client函数 此函数由内核完成 作用为 将i2c_client
注册到i2c_adapter的client链表中
if ((rc = i2c_attach_client(at24c02_client)) != 0) {
kfree(at24c02_client);
return rc;
}
6.4 注册主设备号 //file_operations 结构体
major=register_chrdev(0,"at24c02",&at24c02_fops);
6.5 构建设备节点
at24c02_class = class_create(THIS_MODULE, "at24c02");
class_device_create(at24c02_class, NULL, MKDEV(major, 0), NULL, "at24c02");
return 0;
}
===========================================================================
7. at24c02_detach_client 函数的实现 //反操作at24c02_detech函数
static int at24c02_detach_client(struct i2c_client *client)
{
int err;
if ((err = i2c_detach_client(at24c02_client)))
return err;
kfree(at24c02_client);
unregister_chrdev(m

ajor, "at24c02");
class_device_destroy(at24c02_class, MKDEV(major, 0));
class_destroy(at24c02_class);
return 0;
}
============================================================================
8 file_operations 结构体的实现
tatic struct file_operations at24c02_fops = {
.owner = THIS_MODULE,
.read = at24c02_read,
.write = at24c02_write,
};
=============================================================================
9.at24c02_read 函数的实现
static int at24c02_read(struct file *filp, char __user *buff,
size_t count, loff_t *offp)
{
int ret;
struct i2c_msg msg[2];
char addr = 0;

if (count > 1024)
{
return -EINVAL;
}

/* 先写地址 */
msg[0].addr = at24c02_client->addr;
msg[0].flags = 0; /* 0 表示写 */
msg[0].len = 1; /* 1个地址 */
msg[0].buf = &addr;

/* 再读数据 */
msg[1].addr = at24c02_client->addr;
msg[1].flags = I2C_M_RD; /* 1: 表示读 */
msg[1].len = count; /* 要读的数据个数 */
msg[1].buf = at24c02_buf;

ret = i2c_transfer(at24c02_client->adapter, msg, 2);

if (ret == 2)
{
copy_to_user(buff, at24c02_buf, count);
return count;
}
else
return -EIO;

}
============================================================================
10.at24c02_write 函数的实现
static ssize_t at24c02_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
{
int ret;
struct i2c_msg msg[1];

if (count > 1024)
{
return -EINVAL;
}

copy_from_user(&at24c02_buf[1], buff, count);

at24c02_buf[0] = 0; /* 表示写到哪里 */

msg[0].addr = at24c02_client->addr;
msg[0].flags = 0; /* 0 表示写 */
msg[0].len = count + 1; /* 1个地址+count个数据 */
msg[0].buf = at24c02_buf;

ret = i2c_transfer(at24c02_client->adapter, msg, 1);

if (ret == 1)
return count;
else
return -EIO;
}
============================================================================
1. 入口函数
static int __init at24c02_init(void)
{
i2c_add_driver(&at24c02_driver);
return 0;
}
//i2c_add_driver此函数完成将设备驱动 at24c02_driver 加载到i2c_driver中去,
由内核完成,我们只需要调用i2c_add_driver
=========================================================================
2.出口函数
static void at24c02_exit(void)
{
i2c_del_driver(&at24c02_driver);
}
=================================================================================
3.权限申请
module_init(at24c02_init);
module_exit(at24c02_exit);
MODULE_LICENSE("GPL");
==================================================================================

相关文档
最新文档