linux有哪些总线驱动程序,Linux的I2C驱动程序

1写入口函数at24cxx_init()

在入口函数中主要有一个增加设备驱动的函数i2c_add_driver(),该函数会调用i2c_register_driver(THIS_MODULE,

驱动名字)完成注册。

2写出口函数at24cxx_exit()

在出口函数里主要有一个删除设备驱动的函数i2c_del_driver(),这个函数功能有从设备驱动链表中删除驱动,卸载注册的驱动等

3修饰入口函数和出口函数

module_init(at24cxx_init); 这样,使用insmod命令加载驱动模块时,入口函数

at24cxx_init()就会被调用

module_exit(at24cxx_exit); 这样,使用rmmod命令加载驱动模块时,入口函数

at24cxx_exit()就会被调用

4写I2C驱动主要是:分配一个i2c_driver结构体

设置填充i2c_driver结构体

staticstruct i2c_driver at24cxx_driver={

.driver = {

.name = “at24cxx”,

}

.attach_adapter = at24cxx_attach,

.detach_client = at24cxx_detach

};

函数at24cxx_attach()和at24cxx_detach需要自己构造

5构造at24cxx_attach()函数和at24cxx_detach()函数

Static int at24cxx_attach(struct i2c_adapter *adapter){

return i2c_probe(adapter,&addr_data,at24cxx_detect);

}

I2c_probe函数主要是通过适配器adapter发送结构体addr_data的地址,这个地址就是i2c设备的地址,需要自己根据硬件原理图定义的,如果收到回应,就是说有这个i2c设备,就调用at24cxx_detect处理,这个函数需要自己去构造的。

class_device_destroy(cls, MKDEV(major, 0));

class_destroy(cls);

unregister_chrdev(major, "at24cxx");

i2c_detach_client(client);

kfree(i2c_get_clientdata(client));

卸载函数主要是把申请的主设备号注销掉,注销掉注册的设备,解除适配器上的设备驱动,最后释放申请的设备空间。

6、构造addr_data结构体

static unsigned short ignore[] = { I2C_CLIENT_END };

static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };

这里需要注意的是,I2C 设备的设备地址为7 位地址,不算第八位的R/W控制位,由电路图和i2c的数据手册可得出设备的地址。

所以i2c设备的地址为1010000,即0x50

staticstruct i2c_client_address_data addr_data = {

.normal_i2c = normal_addr,

.probe = ignore,

.ignore = ignore,

//.forces = forces,

};

7、构造at24cxx_detect()函数

收到回应说明有i2c设备,然后调用at24cxx_detect()函数,在函数里面主要是分配一个i2c_client结构体,然后设置填充该结构体。

at24cxx_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);

//分配空间

at24cxx_client->addr = address; //i2c设备的地址

at24cxx_client->adapter = adapter; //分配一个适配器

at24cxx_client->driver = &at24cxx_driver; //指向驱动

strcpy(at24cxx_client->name, "at24cxx"); //设备的名字

i2c_attach_client(at24cxx_client); //把设备驱动依附在适配器adapter上 major =

register_chrdev(0, "at24cxx", &at24cxx_fops);

//注册,新的注册方法不再这样

注册了

cls = class_create(THIS_MODULE, "at24cxx");

class_device_create(cls, NULL, MKDEV(major, 0), NULL,

"at24cxx");

以后收发数据要用到该结构体的

8、构造file_operations结构体中的各成员函数

主要构造.read函数、.write函数

a. 构造读函数

staticssize_t at24cxx_read(struct file *file, char __user *buf,

size_t size, loff_t * offset)

首先要从应用程序中获得要读的地址copy_from_user(&address, buf, 1);

msg[0].addr = at24cxx_client->addr;

msg[0].buf = &address;

msg[0].len = 1;

msg[0].flags = 0;

msg[1].addr = at24cxx_client->addr;

msg[1].buf = &data;

msg[1].len = 1;

msg[1].flags = I2C_M_RD;

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

if (ret == 2)

{

copy_to_user(buf, &data, 1);

return 1;

}

调用i2c传输函数,这会按i2c协议进行,然后把读到的数据返回给用户。

b、构造写函数

copy_from_user(val, buf, 2);

msg[0].addr = at24cxx_client->addr;

msg[0].buf = val;

msg[0].len = 2;

msg[0].flags = 0;

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

第一句是从用户获得要写的数据,下面的msg就是设备地址、要写的地址,长度,写 最后就是调用传输函数进行写。

9、填充file_operations结构体

staticstructfile_operations at24cxx_fops = {

.owner = THIS_MODULE,

.read = at24cxx_read,

.write = at24cxx_write,

};

这样在调用read函数时,就会调用at24cxx_read,在调用write函数时,就会调用at24cxx_write

三、问题

本总结的基于Linux2.6.22内核,与本开发板用的3.0.1内核的驱动有差别,3.0.1内核的很多i2c驱动都归到混杂设备驱动中去了

四、I2C驱动程序

#include linux/kernel.h

#include linux/init.h

#include linux/module.h

#include linux/slab.h

#include linux/jiffies.h

#include linux/i2c.h

#include linux/mutex.h

#include linux/fs.h

#include asm/uaccess.h

static unsigned short ignore[] = { I2C_CLIENT_END };

static unsigned short normal_addr[] = { 0x50, I2C_CLIENT_END };

static unsigned short force_addr[] = {ANY_I2C_BUS, 0x60,

I2C_CLIENT_END};

static unsigned short * forces[] = {force_addr, NULL};

staticstruct i2c_client_address_data addr_data = {

.normal_i2c = normal_addr,

.probe = ignore,

.ignore = ignore,

//.forces = forces,

};

staticstruct i2c_driver at24cxx_driver;

staticint major;

staticstruct class *cls;

struct i2c_client *at24cxx_client;

staticssize_t at24cxx_read(struct file *file, char __user *buf,

size_t size, loff_t * offset) {

unsigned char address;

unsigned char data;

struct i2c_msg msg[2];

int ret;

if (size != 1)

return -EINVAL;

copy_from_user(&address, buf, 1);

msg[0].addr = at24cxx_client->addr;

msg[0].buf = &address;

msg[0].len = 1;

msg[0].flags = 0;

msg[1].addr = at24cxx_client->addr;

msg[1].buf = &data;

msg[1].len = 1;

msg[1].flags = I2C_M_RD;

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

if (ret == 2)

{

copy_to_user(buf, &data, 1);

return 1;

}

else

return -EIO;

}

staticssize_t at24cxx_write(struct file *file, const char __user

*buf, size_t size, loff_t *offset) {

unsigned char val[2];

struct i2c_msg msg[1];

int ret;

if (size != 2)

return -EINVAL;

copy_from_user(val, buf, 2);

msg[0].addr = at24cxx_client->addr;

msg[0].buf = val;

msg[0].len = 2;

msg[0].flags = 0;

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

if (ret == 1)

return 2;

else

return -EIO;

}

staticstructfile_operations at24cxx_fops = {

.owner = THIS_MODULE,

.read = at24cxx_read,

.write = at24cxx_write,

};

staticint at24cxx_detect(struct i2c_adapter *adapter, int address,

int kind)

{

printk("at24cxx_detect\n");

at24cxx_client = kzalloc(sizeof(struct i2c_client),

GFP_KERNEL);

at24cxx_client->addr = address;

at24cxx_client->adapter = adapter;

at24cxx_client->driver =&at24cxx_driver;

strcpy(at24cxx_client->name, "at24cxx");

i2c_attach_client(at24cxx_client);

major = register_chrdev(0, "at24cxx", &at24cxx_fops);

cls = class_create(THIS_MODULE, "at24cxx");

class_device_create(cls, NULL, MKDEV(major, 0), NULL,

"at24cxx");

return 0;

}

staticint at24cxx_attach(struct i2c_adapter *adapter)

{

return i2c_probe(adapter, &addr_data, at24cxx_detect);

}

staticint at24cxx_detach(struct i2c_client *client)

{

printk("at24cxx_detach\n");

class_device_destroy(cls, MKDEV(major, 0));

class_destroy(cls);

unregister_chrdev(major, "at24cxx");

i2c_detach_client(client);

kfree(i2c_get_clientdata(client));

return 0;

}

staticstruct i2c_driver at24cxx_driver = { .driver = {

.name = "at24cxx", },

.attach_adapter = at24cxx_attach, .detach_client = at24cxx_detach,

};

staticint at24cxx_init(void)

{

i2c_add_driver(&at24cxx_driver); return 0;

}

static void at24cxx_exit(void) {

i2c_del_driver(&at24cxx_driver); }

module_init(at24cxx_init);

module_exit(at24cxx_exit);

MODULE_LICENSE("GPL");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值