- 论坛徽章:
- 0
|
本帖最后由 yypotato1985 于 2012-05-23 18:39 编辑
最近在学习ARM-LINUX下的I2C设备驱动,我用的linux内核是linux2.6.32版本,开发板是mini2440,我现在在写ADT7410这款温度传感器的的设备驱动,它是基于I2C通信的。
但是我的驱动可以通过内核模块挂载到开发板上,但是通过测试程序却不能打开这个设备。我的这个框架是将I2C设备驱动封装在字符驱动里的。请大家帮我看看是怎么回事。驱动里暂时没有实现IOCTL的功能。只是有读写,初始化的功能。芯片的地址是0x48.
/*
ADT7410温度传感器设备驱动,基于linux I2C Probe(new-style)方式
*/
/*定义调用库函数*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/i2c.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/delay.h>
/*定义ADT7410相关寄存器*/
#define Temperature_Value_MSB_Register 0x00
#define Temperature_Value_LSB_Register 0x01
#define Status_Register 0x02
#define Configuration_Register 0x03
#define T_high_Setpoint_MSB_Register 0x04
#define T_high_Setpoint_LSB_Register 0x05
#define T_low_Setpoint_MSB_Register 0x06
#define T_low_Setpoint_LSB_Register 0x07
#define T_crit_Setpoint_MSB_Register 0x08
#define T_crit_Setpoint_LSB_Register 0x09
#define T_hyst_Setpoint_Register 0x0A
#define ID_Register 0x0B
/*定义字符设备主设备号*/
#define adt7410_MAJOR 0
static int adt7410_major = adt7410_MAJOR;
/*定义字符设备结构体*/
struct adt7410_dev {
struct i2c_client *client;
struct cdev cdev;
};
/*创建字符设备结构体实例*/
struct adt7410_dev *adt7410_devp;
/*打开字符设备*/
static int adt7410_open(struct inode *inode, struct file *file)
{
//struct adt7410_dev *dev;
//dev = container_of(inode->i_cdev,struct adt7410_dev,cdev);
file->private_data = dev;
return 0;
}
/*释放字符设备*/
static int adt7410_release(struct inode *inodep, struct file *file)
{
file->private_data = NULL;
return 0;
}
/*定义write*/
static int adt7410_write(struct i2c_client *client,uint8_t reg,uint8_t data)
{
unsigned char buffer[2];
buffer[0] = reg;
buffer[1] = data;
if(2 != i2c_master_send(client,buffer,2))
{
printk(KERN_ERR "ADT7410 I2C WRITE FAIL! \n"
return -1;
}
return 0;
}
/*定义read*/
static int adt7410_read(struct i2c_client *client,uint8_t *data)
{
if(1 != i2c_master_recv(client,data,1))
{
printk(KERN_ERR "ADT7410 I2C READ FAIL!\n"
return -1;
}
return 0;
}
/*定义ioctl*/
//static int adt7410_ioctl(struct inode *inode,struct file *file,
// unsigned int cmd,unsigned long arg)
//{
// switch(cmd)
//}
/* 定义并填充file_operations */
static const struct file_operations adt7410_fops = {
.owner = THIS_MODULE,
.open = adt7410_open,
.read = adt7410_read,
.write = adt7410_write,
.release = adt7410_release,
//.ioctl = adt7410_ioctl,
};
/*建立字符设备*/
static void adt7410_setup_cdev(struct adt7410_dev *dev, int index)
{
int err, devnum = MKDEV(adt7410_major, index);
/* 设置cdev*/
cdev_init(&dev->cdev, &adt7410_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &adt7410_fops;
/* 注册cdev */
err = cdev_add(&dev->cdev, devnum, 1);
if (err)
printk(KERN_NOTICE"Error %d adding adt7410 %d", err, index);
}
/*字符设备驱动注册*/
static int __devinit adt7410_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
int ret;
dev_t devnum = MKDEV(adt7410_major, 0);
/* 申请设备号 */
if (adt7410_major)
ret = register_chrdev_region(devnum, 1, "adt7410"
else {
ret = alloc_chrdev_region(&devnum, 0, 1, "adt7410"
adt7410_major = MAJOR(devnum);
}
if (ret < 0)
return ret;
/* 分配cdev */
adt7410_devp = kmalloc(sizeof(struct adt7410_dev), GFP_KERNEL);
if (!adt7410_devp){
ret = -ENOMEM;
goto fail_malloc;
}
/*初始化adt7410寄存器*/
adt7410_write(&adt7410_devp->client,Configuration_Register,0x1C);
//adt7410_read(&adt7410_devp->client,Temperature_Value_MSB_Register);
memset(adt7410_devp, 0, sizeof(struct adt7410_dev));
adt7410_devp->client = client;
/* 设置并注册cdev */
adt7410_setup_cdev(adt7410_devp, 0);
return 0;
fail_malloc:
unregister_chrdev_region(devnum, 1);
return ret;
}
/*字符设备驱动注销*/
static int __devexit adt7410_remove(struct i2c_client *client)
{
cdev_del(&adt7410_devp->cdev);
kfree(adt7410_devp);
unregister_chrdev_region(MKDEV(adt7410_major, 0), 1);
return 0;
}
/*注册i2c设备*/
static const struct i2c_device_id adt7410_id[] = {
{ "adt7410", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adt7410_id);
static struct i2c_board_info __initdata adt7410_i2c_board_info[] = {
{
I2C_BOARD_INFO("adt7410", 0x4,/*0x48是ADT7410地址*/
},
};
/*定义并填充i2c_driver:*/
static struct i2c_driver adt7410_driver = {
.driver = {
.name = "adt7410",
.owner = THIS_MODULE,
},
.probe = adt7410_probe,
.remove = __devexit_p(adt7410_remove),
.id_table = adt7410_id,
};
/*注册i2c驱动*/
static int __init adt7410_init(void)
{
printk(KERN_INFO "The adt7410 driver is init!\n"
return i2c_add_driver(&adt7410_driver);
i2c_register_board_info(1, adt7410_i2c_board_info,ARRAY_SIZE(adt7410_i2c_board_info));
}
/*注销i2c驱动*/
static void __exit adt7410_exit(void)
{
printk(KERN_INFO "The adt7410 driver is exit!\n"
i2c_del_driver(&adt7410_driver);
}
module_init(adt7410_init);
module_exit(adt7410_exit);
MODULE_AUTHOR("Yang yu 313889744@qq.com"
MODULE_LICENSE("Dual BSD/GPL"
MODULE_DESCRIPTION("ADT7410 I2C Driver"
|
|