手把手教你写LinuxI2C设备驱动_第1页
手把手教你写LinuxI2C设备驱动_第2页
手把手教你写LinuxI2C设备驱动_第3页
手把手教你写LinuxI2C设备驱动_第4页
手把手教你写LinuxI2C设备驱动_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、手把手教你写Linux I2C设备驱动Linux I2C驱动是嵌入式Linux驱动开发人员经常需要编写的一种驱动,因为凡是系统中使用到的I2C设备,几乎都需要编写相应的 I2C驱动去配置和控制它,例如 RTC实时时钟 芯片、音视频采集芯片、音视频输出芯片、EEROM芯片、AD/DA转换芯片等等。Linux I2C驱动涉及的知识点还是挺多的,主要分为 Linux I2C的总线驱动(I2C BUS Driver)和设备驱动(I2C Clients Driver),本文主要关注如何快速地完成一个具体的I2C设备驱动(I2C Clients Driver )。关于Linux I2C驱动的整体架构、核心

2、原理等可以在网上 搜索其他相关文章学习。本文主要参考了 Linux内核源码目录下的./Documentation/i2c/writing-clients文档。以手头的一款视频采集芯片TVP5158为驱动目标,编写 Linux I2C设备驱动。1. i2c_driver 结构体对象每一个I2C设备驱动,必须首先创造一个i2c_driver结构体对象,该结构体包含了I2C设备探测和注销的一些基本方法和信息,示例如下:1. static struct i2c_driver tvp5158_i2c_driver = 2. .driver = .8.;3. .n ame = "t

3、vp51582c_driver".,.attach_adapter = & tvp5158_attach_adapter, .detach_clie nt = &tvp5158_detach_clie nt, .comma nd= NULL,其中,name字段标识本驱动的名称(不要超过 31个字符),attach_adapter和detac h_client字段为函数指针,这两个函数在 I2C设备注册的时候会自动调用,需要自己实现这 两个函数,后面将详细讲述。2. i2c_clie nt结构体对象上面定义的i2c_driver对象,抽象为一个i2c的驱动模型,提供对i

4、2C设备的探测和注销 方法,而i2c_client结构体则是代表着一个具体的i2c设备,该结构体有一个data指针,可以指向任何私有的设备数据,在复杂点的驱动中可能会用到。示例如下:1. struct tvp5158_obj2. struct i2c_clie nt clie nt;3. int users; / how many users using the driver4. ;5.5. struct tvp5158_obj* g_tvp5158_obj;其中,users为示例,用户可以自己在 tvp5158_obj这个结构体里面添加感兴趣的字段, 但是i2c_client字段不可少。具体

5、用法后面再详细讲。3. 设备注册及探测功能这一步很关键,按照标准的要求来写, 则Linux系统会自动调用相关的代码去探测你的I2C设备,并且添加到系统的I2C设备列表中以供后面访问。我们知道,每一个I2C设备芯片,都通过硬件连接设定好了该设备的I2C设备地址。因此,I2C设备的探测一般是靠设备地址来完成的。那么,首先要在驱动代码中声明你要探测 的I2C设备地址列表,以及一个宏。示例如下:1.static un sig ned short no rmal_i2c = 2.0xbc >> 1,3.0xbe >> 1,4.I2C_CLIENT_END5.;6.I2C_CLIE

6、NT_INSMOD;normal_i2c数组包含了你需要探测的I2C设备地址列表,并且必须以I2C_CLIENT_END作为结尾,注意,上述代码中的0xbc和Oxbe是我在硬件上为我的 tvp5158分配的地址,硬件上我支持通过跳线将该地址设置为Oxbc或者Oxbe ,所以把这两个地址均写入到探测列表中,让系统进行探测。如果你的I2C设备的地址是固定的,那么,这里可以只写你自己的I2C设备地址,注意必须向右移位1。宏I2C_CLIENT_INSMOD 的作用网上有许多文章进行了详细的讲解,这里我就不详细 描述了,记得加上就行,我们重点关注实现。下一步就应该编写第 1步中的两个回调函数,一个用于

7、注册设备,一个用于注销设备。 探测函数示例如下:1. static int tvp5158_attach_adapter(struct i2c_adapter *adapter)2. 3. retur n i2c_probe(adapter, &addr_data, &tvp5158_detect_cli en t);4. 这个回调函数系统会自动调用,我们只需要按照上述代码形式写好就行,这里调用了系 统的I2C设备探测函数,i2c_probe(),第三个参数为具体的设备探测回调函数,系统会在 探测设备的时候调用这个函数,需要自己实现。示例如下:1. static int tvp

8、5158_detect_clie nt(struct i2c_adapter *adapter, int address,i nt kind)2. 3. struct tvp5158_obj *pObj;4. int err = 0;5.5. prin tk(KERN_INFO "I2C: tvp5158_detect_clie nt at address %x . n", address);7.6. if( g_tvp5158_obj != NULL ) 7. /already allocated,i nc user count, and return the al lo

9、cated han dle8. g_tvp5158_obj->users+;9. return 0;10. 13.11. /* allocobj */12. pObj =kmalloc(sizeof(struct tvp5158_obj), GFP_KERNEL);13. if (pObj=0)14. return -ENOMEM;15. 16. memset(pObj, 0, sizeof(struct tvp5158_obj);17. pObj->clie nt.addr= address;18. pObj->clie nt.adapter = adapter;19. p

10、Obj->clie nt.driver= & tvp5158_i2c_driver;20. pObj->clie nt.flags= I2C_CLIENT_ALLOW_USE;21. pObj->users+;25.22. /* attach i2c clie nt to sys i2c clie nts list */23. if(err = i2c_attach_clie nt(&pObj->clie nt)24. prin tk( KERN_ERR "I2C: ERROR: i2c_attach_clie nt fail! address

11、=%xn",address);25. return err;26. 31.27. / store the pObj28. g_tvp5158_obj = pObj;34.29. printk( KERN_ERR "I2C: i2c_attach_clie nt ok! address=%x n ",address);36.30. return 0;31. 到此为止,探测并且注册设备的代码已经完成,以后对该I2C设备的访问均可以通过g_tvp5158_obj 这个全局的指针进行了。背景:阅读新闻手把手教你写Linux I2C设备驱动字体:大中小日期:2012-01-

12、11来源:Linux 社区 作者:ticktick4. 注销I2C设备同理,设备注销的回调函数也会自动被系统调用,只需要按照模板写好设备注销代码,示例如下:1. static int tvp5158_detach_client(struct i2c_client *client)2. 3. int err;4.4. if( ! client->adapter )5. return -ENODEV;6. 8.7. if( (err = i2c_detach_client(client) ) 8. printk( KERN_ERR "Client deregistration fa

13、iled (address=%x), client not detached.n ", client->addr);9. return err;10. 13.11. client->adapter = NULL;15.12. if( g_tvp5158_obj )13. kfree(g_tvp5158_obj);14. 19.15. return 0;16. 到此为止,设备的注册和注销代码已经全部完成,下面要做的就是提供读写I2C设备的方法。5. I2C设备的读写对I2C设备的读写,Linux系统提供了多种接口,可以在内核的i2c.h中找到,这里简单介绍其中的两种接口。【

14、接口一】:1. extern int i2c_master_send(struct i2c_client *,const char* ,int);2.3. extern int i2c_master_recv(struct i2c_client *,char* ,int);第一个参数是i2c_client对象指针,第二个参数是要传输的数据buffer指针,第三个参数为 buffer的大小。【接口二】:41. extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num);这个接口支持一次向I2C设备

15、发送多个消息,每一个消息可以是读也可以是写,读或者写以及读写的目标地址(寄存器地址)均包含在msg消息参数里面。这些接口仅仅是最底层的读写方法,关于具体怎么与I2C设备交互,比如具体怎么读芯片的某个特定寄存器的值,这需要看具体的芯片手册,每个I2C芯片都会有具体的I2C寄存器读写时序图。因此,为了在驱动中提供更好的访问接口,还需要根据具体的时序要求对这些读写函数进行进一步封装,这些内容将在 后面的文章中讲述。6. 模块初始化及其他下一步就是整个模块的初始化代码和逆初始化代码,以及模块声明了。1. static int _init tvp5158_i2c_init(void)2. 3. g_tv

16、p5158_obj = NULL;4.4. return i2c_add_driver(&tvp5158_i2c_driver);5. 7.6. static void _exit tvp5158_i2c_exit(void)7. 8. i2c_del_driver(&tvp5158_i2c_driver);9. 12.13. module_init(tvp5158_i2c_init);14. module_exit(tvp5158_i2c_exit);15.15. MODULE_DESCRIPTION("TVP5158 i2c driver");16. MODULE_AUTHOR("Lujun hust");17. MODULE_LICENSE("GPL");在初始化的代码里面,添加本模块的i2c driver对象,在逆初始化代码里面,删除本模块的i2c driver对象。7. 总结到此为止,算是从应用的角度把编写一个 I2C的设备驱动代码讲完了

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论