免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4905 | 回复: 12
打印 上一主题 下一主题

[驱动] I2C设备驱动基于newstyle方式的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-05-23 18:38 |只看该作者 |倒序浏览
本帖最后由 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";

论坛徽章:
0
2 [报告]
发表于 2012-05-23 20:17 |只看该作者
唉,自己顶一下,没人可以帮忙吗?

论坛徽章:
0
3 [报告]
发表于 2012-05-24 10:32 |只看该作者
本帖最后由 youjujun 于 2012-05-24 15:00 编辑

帮你顶起。

论坛徽章:
0
4 [报告]
发表于 2012-05-24 18:07 |只看该作者
额。。。就么有人帮忙看看吗?

论坛徽章:
0
5 [报告]
发表于 2012-05-25 09:26 |只看该作者
mach-mini2440.c添加的:
//////////////////////////////添加i2c信息////////////////////////////
static struct i2c_board_info __initdata adt7410_i2c_board_info[] = {
{
        I2C_BOARD_INFO("adt7410", 0x4,/*0x48是ADT7410地址*/
},
};

//////////////////////////////添加i2c信息////////////////////////////
static void __init mini2440_machine_init(void)
{
i2c_register_board_info(0,adt7410_i2c_board_info,ARRAY_SIZE(adt7410_i2c_board_info));
}
注意:这一步非常重要,因为你不在板文件中添加i2c信息,那么用i2c_add_drive时就会探
测不到你i2c设备,也就没法执行你的xxxx_probe函数,你的驱动也就无法使用。

论坛徽章:
0
6 [报告]
发表于 2012-05-25 18:35 |只看该作者
哦,意思是还要把i2c_register_board_info(0,adt7410_i2c_board_info,ARRAY_SIZE(adt7410_i2c_board_info));
放到内核里去?

论坛徽章:
0
7 [报告]
发表于 2012-05-26 16:45 |只看该作者
修改一下下面吧:

/*注册i2c驱动*/
static        int        __init        adt7410_init(void)
{
    printk(KERN_INFO "The adt7410 driver is init!\n";      
        return        i2c_add_driver(&adt7410_driver);------------------------------------(1)
        i2c_register_board_info(1, adt7410_i2c_board_info,ARRAY_SIZE(adt7410_i2c_board_info));       ------------(2)
}

(1) (2)两句交换

论坛徽章:
0
8 [报告]
发表于 2012-05-27 09:58 |只看该作者
1,2句换过的,但是编译的时候要出现警告。。

论坛徽章:
0
9 [报告]
发表于 2013-05-07 21:47 |只看该作者
楼主最后问题解决了吗

论坛徽章:
0
10 [报告]
发表于 2013-05-07 21:53 |只看该作者
最近我也在学I2C驱动,有很多疑问,想向楼主请教。
1      new style方式的i2c驱动,为什么不需要参照具体设备的读写时序,比如adt7140,读写的时候应该有固定时序的,先写什么再写什么延迟多少us等等。为什么驱动中不需要涉及呢?难道是读写时序是在应用程序中体现。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP