基于嵌入式Linux 的I2C设备驱动程序的分析
i2c_dev 里面定义了读写I2C 设备应用层的读写接口,但由于其缺少通用性,一般很少用到所以并不做详细的介绍。
i2c_core在驱动框架中起到了承上启下的作用,里面定义了许多重要的函数。例如:adapter注册/注销函数,增加/删除设备驱动函数,增加/删除I2C设备的函数,I2C传输,发送和接收函数。这些函数都是在编写I2C设备驱动程序中必须要用到的接口函数,正是由于这些通用的接口函数才使得代码具有很强的可移植性和重用性。
3 编写I2C设备驱动的思路
在了解Linux中I2C设备驱动的基本框架后,要编写自己的设备驱动首先要弄清楚的一个问题是到底内核已经实现了那部分,需要实现的又是那部分。因为I2C设备驱动是基于总线设备驱动模型的,一般而言在移植Linux操作系统中,Linux内核已经对总线部分已经有了很好的实现,所以总线部分的驱动一般可以不必关心。
在此需要实现的是设备层的i2c_driver与i2c_client结构体,并利用I2C 子系统提供的接口函数挂接到I2C 总线上。
每一个I2C设备驱动,必须首先创造一个i2c_driver结构体对象,该结构体包含了I2C设备探测和注销的一些基本方法和信息。其中包括设备驱动的名字,适配器的挂接/取消函数指针等。一个例子如下所示,name字段标识本驱动的名称(不要超过31 个字符),at-tach_adapter和detach_client字段为函数指针,这两个函数在I2C设备注册的时候会自动调用,需要自己实现这两个函数。
上面定义的i2c_driver对象,抽象为一个I2C的驱动模型,提供对I2C设备的探测和注销方法,接下来就是要定义i2c_client 结构体,其代表着一个具体的I2C 设备,该结构体有一个data指针,可以指向任何私有的设备数据,在复杂点的驱动中可能会用到。
每一个I2C设备芯片,都通过硬件连接设定好了该设备的I2C设备地址。因此,I2C设备的探测一般是靠设备地址来完成的。那么,首先要在驱动代码中声明你要探测的I2C设备地址列表以及一个宏,示例如下:
有了i2c_client结构体代表了具体的设备和设备ID后就可以实现attach_adapter 和detach_client 函数。这两个函数是系统自动调用的,它的实现是有一定的框架的,可以在linux内核源码的驱动例子中找到,由于代码过长这里不做具体的分析。针对不同的设备函数的实现会略有不同,一般attach_adapte需要完成的工作是对i2c_client结构体成员赋值和调用接口函i2c_attach_cli-ent把设备挂接到适配其中。而detach_client 函数则是完成相反的工作。
最后的一步是编写模块的初始化与退出函数把驱动加进I2C驱动子系统中,示例可以是:
至此,I2C设备的驱动已经完成了,但是到了这一步本驱动并没有实际的用处,它仅仅提供的是一个设备驱动程序的管理框架,所以必须还要进行两方面的补充。
第一方面是,利用I2C总线读写外部芯片的控制/状态寄存器;第二方面是,向应用层提供I2C设备的读写接口,令应用程序可以对设备节点的读写实现对I2C具体物理设备的读写。为了实现I2C 设备寄存器的读写操作,必须要用到Linux的I2C子系统提供的读写接口函数:
利用这两个函数根据芯片的读写时序进行封装,就可以读写芯片内部的寄存器,以写芯片寄存器为例,必须写往总线上写寄存器的地址,然后写入要往寄存器里写入的数据,示例代码如下所示。读寄存器的时序则是则是先写入要读寄存器的地址,然后接受总线上的数据,区别不大,不做示例。
要想向应用层提供读写接口,则必须再对I2C设备驱动进行一次简单字符设备驱动的封装,将I2C设备作为一个简单字符设备,依次实现字符设备文件操作函数结构体file_operation 里面的函数指针所对应的接口函数,这里只给出了大体的框架,具体的实现对于不同的芯片有很大的不同。
定义一个字符设备结构体cdev,将I2C 设备当做一个普通的字符设备处理。
定义一个文件操作函数结构体,填写里面函数指针,指出设备操作所对应的具体函数,一般的例子是:
接着就是编写file_operations所对应的具体函数。
最后一步是在模块的初始化和退出函数中增加对简单字符设备的注册和注销操作,包括设备号申请与注销,设备注册与注销两方面。
至此,将编译好的模块加载进内核后就可以在用户空间利用文件系统的API对设备文件进行各种操作。
4 结语
I2C总线在电子系统设计中是十分普遍的一种接口技术,而Linux又是十分流行的嵌入式操作系统。编写嵌入式Linux下I2C总线设备的驱动驱动程序是嵌入式开发中十分重要的一项技术,不容忽视。本文首先讲述了Linux系统I2C设备驱动程序的总体框架,然后给出了编写I2C设备驱动的总体思路与框架,希望给读者理清思路,加深对编写I2C设备驱动的理解。总而言之,利用I2C总线通信可以达到很高的速率,而且总线上可以挂接多个节点,每个节点都由惟一的地址确定
linux操作系统文章专题:linux操作系统详解(linux不再难懂)linux相关文章:linux教程
评论