Linux i2c子系统应用之Linux ARM嵌入式i2c通信(设备驱动完成i2c从设备寄存器的配置)

一、前言

        本文主要分为三个部分,第一部分,介绍i2c字符设备驱动应用的背景以及本文测试需要的开发环境;第二部分,介绍主要的字符驱动源码及测试程序;第三部分,测试方法以及测试结果,i2c从设备的器件地址可以在该器件的datasheet查找。文章的最后会给大家分享本文的所有源码。

二、开发背景和环境 

        我已经讲解过利用i2c总线的去配置i2c从设备的方法,本文采用i2c设备驱动的方式完成同样的功能,在此完善工作记录。

优点:(1)当从设备需要多种功能操作时(比如修改摄像头的亮度、放大、曝光、分辨率等配置),把每个功能包装成子模块,相对总线方式的配置层次清晰,而且方便管理维护,而且在扩展时还能够在设备驱动中添加对系统内核资源的访问(操作时请注意安全);

            (2)设备初始化顺序可以随意控制,想i2c从设备启动快点就把设备初始化添加到内核启动,想它启动慢一点,就以.ko的方式加载,等文件系统加载完毕了再初始化;

缺点 :(1)相比总线操作的方式编写代码较复杂,因为首先要熟悉字符驱动架构,而且还需要编写一个操作设备驱动的应用程序;

运行环境:ARM S3C6410平台

交叉编译器:ARM-LINUX-GCC

内核版本:2.6.28.6

三、源码的讲解

        源码的讲解分为两个部分,第一个部分初略地介绍下i2c字符设备初始化过程,具体的字符驱动架构不再本文讲解的范围内,第二部分,讲解利用i2c设备驱动对i2c从设备的寄存器进行读写操作;

驱动源码初始化执行步骤,

module_init(ch7026_init)

首先执行ch7026_init函数

static __init int ch7026_init(void)
{
        int ret;
        dev_t devno;

        printk(DEVICE_NAME " start init...\n");

        p_bank = kmalloc(sizeof(struct ch7026_bank), GFP_KERNEL);
        if (!p_bank)
                return -ENOMEM;
        memset(p_bank, 0, sizeof(struct ch7026_bank));

        devno = MKDEV(CH7026_MAJOR,0);

        ret = register_chrdev_region(devno,1,DEVICE_NAME);
        if(ret<0)
        {
                printk(KERN_NOTICE "can not register ch7026 device");
                return ret;
        }

        cdev_init(&cdev_ch7026,&ch7026_fops);
        cdev_ch7026.owner = THIS_MODULE;

	ret =cdev_add(&cdev_ch7026,devno,1);
        if(ret)
        {
                printk(KERN_NOTICE "can not add ch7026 device");
                return ret;
        }
    
        /*在/sys/class/下创建相对应的类目录*/
        my_class = class_create(THIS_MODULE,"ch7026");
        if(IS_ERR(my_class))
        {
                printk("Err: Failed in creating class\n");
                return -1;
        }
        /*完成设备节点的自动创建,当加载模块时,就会在/dev下自动创建设备文件*/
        device_create(my_class,NULL,MKDEV(CH7026_MAJOR,0),NULL,DEVICE_NAME);

        printk(DEVICE_NAME " initialized\n");
        i2c_add_driver(&ch7026_driver);

        return 0;
}

执行回调函数 ch7026_probe()函数

static struct i2c_driver ch7026_driver = {
      .driver = {
	   .name = "ch7026",
	   .owner = THIS_MODULE,
       },
      .id = I2C_DRIVERID_CH7026,
      .attach_adapter = ch7026_probe,
      .detach_client = ch7026_detach,
};

在执行ch7026_attach()函数

static int ch7026_probe(struct i2c_adapter *adap)
{
	int ret = 0;

	ret = i2c_probe(adap, &addr_data, ch7026_attach);
	if (ret) {
                printk("failed to attach ch7026 driver\n");
                ret = -ENODEV;
        } 

        return ret;
}

执行ch7026_attach函数,执行用户配置i2c从设备ch7026_config()函数

static int ch7026_attach(struct i2c_adapter *adap, int addr, int flags )
{
	int ret = 0;
        strcpy(p_bank->c.name, "ch7026");
        p_bank->c.addr = addr;
        p_bank->c.adapter = adap;
        p_bank->c.driver = &ch7026_driver;

        ret = i2c_attach_client(&p_bank->c);
        ch7026_config(&p_bank->c);
	printk("CH7026 attached successfully\n");

        return ret;
}

 

第二部分下面

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值