Linux IIC设备驱动开发.docx
- 文档编号:3310365
- 上传时间:2022-11-21
- 格式:DOCX
- 页数:16
- 大小:277.03KB
Linux IIC设备驱动开发.docx
《Linux IIC设备驱动开发.docx》由会员分享,可在线阅读,更多相关《Linux IIC设备驱动开发.docx(16页珍藏版)》请在冰豆网上搜索。
LinuxIIC设备驱动开发
目录
1.I2C总线简介1
1.1.I2C总线工作原理1
1.2.I2C总线的几种信号状态1
1.3.I2C总线基本操作1
2.Linux系统I2C驱动程序2
2.1.I2C驱动层次结构2
2.2.I2C核心(I2Ccore)3
2.3.I2C控制器驱动(I2Cadapter)3
2.4.I2C设备驱动(I2Cdriver)3
3.基于SUNXI平台的I2C控制器驱动4
3.1.I2C驱动层次架构4
3.2.I2C驱动源码结构4
3.3.I2C驱动配置说明5
4.I2C设备驱动程序的开发7
4.1.I2C设备驱动一般结构7
4.2.常用数据结构解析7
4.2.1.i2c_adapter7
4.2.2.i2c_algorithm8
4.2.3.i2c_msg8
4.2.4.i2c_client8
4.2.5.i2c_driver9
4.3.常用接口函数解析9
4.3.1.i2c_add_driver9
4.3.2.i2c_del_driver10
4.3.3.i2c_set_clientdata10
4.3.4.i2c_get_clientdata10
4.3.5.i2c_master_send10
4.3.6.i2c_master_resv11
4.3.7.i2c_transfer11
4.4.I2C设备驱动DEMO11
1.I2C总线简介
I2C(Inter-IntegratedCircuit)总线是一种由Philips公司开发的两线式串行总线,用于连接微控制器及其外围设备。
I2C总线最主要的优点就是简单性和有效性。
1.1.I2C总线工作原理
I2C总线是由数据线SDA和时钟SCL构成的串行总线,各种被控制器件均并联在这条总线上,每个器件都有一个唯一的地址识别,可以作为总线上的一个发送器件或接收器件(具体由器件的功能决定)。
I2C总线的接口电路结构如图1所示。
图1I2C总线接口电路结构图
1.2.I2C总线的几种信号状态
1.空闲状态:
SDA和SCL都为高电平。
2.开始条件(S):
SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
3.结束条件(P):
SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
4.数据有效:
在SCL的高电平期间,SDA保持稳定,数据有效。
SDA的改变只能发生在SCL的低电平期间。
5.ACK信号:
数据传输的过程中,接收器件每接收一个字节数据要产生一个ACK信号,向发送器件发出特定的低电平脉冲,表示已经收到数据。
1.3.I2C总线基本操作
I2C总线必须由主器件(通常为微控制器)控制,主器件产生串行时钟(SCL),同时控制总线的传输方向,并产生开始和停止条件。
数据传输中,首先由主器件产生开始条件,随后是器件的控制字节(前七位是从器件的地址,最后一位为读写位)。
接下来是读写操作的数据,以及ACK响应信号。
数据传输结束时,主器件产生停止条件。
具体的过程如图2所示。
图2I2C总线数据传输图
2.Linux系统I2C驱动程序
2.1.I2C驱动层次结构
Linux系统对I2C设备具有很好的支持,Linux系统下的I2C驱动程序从逻辑上可以分为3个部分:
1.I2C核心(I2Ccore):
实现对I2C总线、I2Cadapter及I2Cdriver的管理。
2.I2C控制器驱动I2Cadapter:
针对不同类型的I2C控制器,实现对I2C总线访问的具体方法。
3.I2C设备驱动I2Cdriver:
针对特定的I2C设备,实现具体的功能,包括read,write以及ioctl等对用户层操作的接口。
4.这三个部分的层次关系如图3和图4所示。
图3Linux内核管理I2C原理图
图4LinuxI2C设备驱动工作原理图
2.2.I2C核心(I2Ccore)
I2Ccore是Linux内核用来维护和管理I2C的核心部分,其中维护了两个静态的List,分别记录系统中的I2Cdriver结构和I2Cadapter结构。
I2Ccore提供接口函数,允许一个I2Cadapter,I2Cdriver和I2Cclient初始化时在I2Ccore中进行注册,以及退出时进行注销。
同时还提供了I2C总线读写访问的一般接口(具体的实现在与I2C控制器相关的I2Cadapter中实现),主要应用在I2C设备驱动中。
2.3.I2C控制器驱动(I2Cadapter)
I2Cadapter是针对不同类型I2C控制器硬件,实现比较底层的对I2C总线访问的具体方法。
I2Cadapter构造一个对I2Ccore层接口的数据结构,并通过接口函数向I2Ccore注册一个控制器。
I2Cadapter主要实现对I2C总线访问的算法,master_xfer()函数就是I2Cadapter底层对I2C总线读写方法的实现。
同时I2Cadapter中还实现了对I2C控制器中断的处理函数。
2.4.I2C设备驱动(I2Cdriver)
I2Cdriver是对I2C从设备的软件实现。
I2Cdriver中提供了一个通用的I2C设备的驱动程序,实现了字符类型设备的访问接口,对设备的具体访问是通过I2Cadapter来实现的。
I2Cdriver构造一个对I2Ccore层接口的数据结构,通过接口函数向I2CCore注册一个I2C设备驱动。
同时I2Cdriver构造一个对用户层接口的数据结构,并通过接口函数向内核注册为一个主设备号为89的字符类型设备。
I2Cdriver实现用户层对I2C设备的访问,包括open,read,write,ioctl,release等常规文件操作,可以通过open函数打开I2C设备文件,通过ioctl函数设定要访问I2C设备的地址,然后就可以通过read和write函数完成对I2C设备的读写操作。
通过I2Cdriver提供的通用方法可以访问任何一个I2C的设备,但是其中实现的read,write及ioctl等功能完全是基于一般设备的实现,所有的操作数据都是基于字节流,没有明确的格式和意义。
为了更方便和有效地使用I2C设备,可以为一个具体的I2C设备开发特定的I2C设备驱动程序,在驱动中完成对特定的数据格式的解释以及实现一些专用的功能。
3.基于SUNXI平台的I2C控制器驱动
3.1.I2C驱动层次架构
位于drivers/i2c/busses目录下的文件i2c-sunxi.c,是基于sunxi平台实现的I2C总线控制器驱动。
它的职责是为系统中3条I2C总线实现相应的读写方法,但是控制器驱动本身并不会进行任何的通讯,而是等待设备驱动调用其函数。
图5是基于SUNXI平台的I2C驱动层次架构图,图中有3块I2Cadapter,分别对应SUNXI平台上的3块I2C控制器。
图5I2C驱动层次架构图
系统开机时,I2C控制器驱动首先被装载,I2C控制器驱动用于支持I2C总线的读写。
i2c_sunxi_algorithm结构体中定义了I2C总线通信方法函数i2c_sunxi_xfer(),该函数实现了对I2C总线访问的具体方法,设备驱动通过调用这个函数,实现对I2C总线的访问;而在函数i2c_sunxi_probe()中完成了对I2Cadapter的初始化。
3.2.I2C驱动源码结构
在drivers/i2c/目录下,包含有几个重要文件和目录,如下:
1.文件i2c-core.c:
I2C子系统核心功能的实现;
2.文件i2c-dev.c:
通用的从设备驱动实现;
3.目录busses:
里面包括基于不同平台实现的I2C总线控制器驱动;
4.目录algos:
里面实现了一些I2C总线控制器的algorithm。
3.3.I2C驱动配置说明
对于I2C总线控制器的配置,可通过命令makeARCH=armmenuconfig进入配置主界面,并按以下步骤操作:
首先,选择DeviceDrivers选项进入下一级配置,如图6所示:
图6DeviceDrivers选项配置
然后,选择I2Csupport选项,进入下一级配置,如图7所示:
图7I2Csupport选项配置
接着,选择I2CHardWareBussupport选项,进入下一级配置,如图8所示:
图8I2CHardWareBussupport选项配置
最后,选择AllWinnerTechnologySUN4II2Cinterface选项,可选择直接编译进内核,也可以选择编译成模块。
如图9所示:
图9AllWinnerTechnologySUN4II2Cinterface选项配置
此外,若需要获取指定I2C总线控制器相关的调试打印信息,可选择SUNXI_IIC_PRINT_TRANSFER_INFO选项,并在busnumid选项中指定对应的I2C总线控制器编号,可输入0,1,2,如图10所示:
图10I2C总线控制器调试信息配置
4.I2C设备驱动程序的开发
4.1.I2C设备驱动一般结构
一个具体的I2C设备驱动需要实现两个方面的接口,一方面是对I2Ccore层的接口,用以挂接I2Cadapter来实现对I2C总线及I2C设备具体的访问方法,包括要实现probe,remove,detect等接口函数;另一方面是对用户应用层的接口,提供用户程序访问I2C设备的接口,包括实现open,release,read,write以及最重要的ioctl等标准文件操作的接口函数。
对I2Ccore层的接口函数的具体功能解释如下:
probe:
I2Cdriver进行设备绑定的回调函数。
remove:
I2Cdriver解除设备绑定的回调函数。
detect:
I2C设备探测回调函数,它会识别所支持的设备(返回0表示支持,否则返回-ENODEV);此外,需要定义一个供探测的地址列表(address_list)和一个设备类型(class),这样使那些仅匹配设备类型的i2c总线被探测到。
例如,对于一个自动监测硬件芯片的驱动将会设置它的class域为I2C_CLASS_HWMON,只有那些class域为I2C_CLASS_HWMON的控制器能够被驱动探测。
4.2.常用数据结构解析
4.2.1.i2c_adapter
structi2c_adapter{
structmodule*owner;/*所属模块*/
unsignedintid;/*algorithm的类型,定义于i2c-id.h,以I2C_ALGO_开始*/
unsignedintclass;
conststructi2c_algorithm*algo;/*总线通信方法结构体指针*/
void*algo_data;/*algorithm数据*/
structrt_mutexbus_lock;
inttimeout;/*超时时间,以jiffies为单位*/
intretries;/*重试次数*/
structdevicedev;/*控制器设备*/
intnr;
charname[48];/*控制器名称*/
structcompletiondev_released;/*用于同步*/
structmutexuserspace_clients_lock;
structlist_headuserspace_clients;
};
i2c_adapter对应于物理上的一个控制器。
一个I2C控制器需要i2c_algorithm中提供的通信函数来控制控制器上产生特定的访问周期。
4.2.2.i2c_algorithm
structi2c_algorithm{
/*I2C传输函数指针*/
int(*master_xfer)(structi2c_adapter*adap,structi2c_msg*msgs,intnum);
/*smbus传输函数指针*/
int(*smbus_xfer)(structi2c_adapter*adap,u16addr,
unsignedshortflags,charread_write,
u8command,intsize,unioni2c_smbus_data*data);
/*返回控制器支持的功能*/
u32(*functionality)(structi2c_adapter*);
};
i2c_algorithm中的关键函数master_xfer()用于产生I2C访问周期需要的信号,以i2c_msg(即I2C消息)为单位。
4.2.3.i2c_msg
structi2c_msg{
__u16addr;/*从设备地址*/
__u16flags;/*消息类型*/
__u16len;/*消息长度*/
__u8*buf;/*消息数据*/
};
i2c_msg是I2C传输的基本单位,它包含了从设备的具体地址,消息的类型以及要传输的具体数据信息。
每个I2C消息传输前,都会产生一个开始位,紧接着传送从设备地址,然后开始数据的发送或接收,对最后的消息还需产生一个停止位。
4.2.4.i2c_client
structi2c_client{
unsignedshortflags;/*标志*/
unsignedshortaddr;/*低7位的芯片地址*/
charname[I2C_NAME_SIZE];/*设备名称*/
structi2c_adapter*adapter;/*依附的i2c_adapter*/
structi2c_driver*driver;/*依附的i2c_driver*/
structdevicedev;
intirq;/*设备使用的中断号*/
structlist_headdetected;
};
i2c_client对应于真实的物理设备,每个I2C设备都需要一个i2c_client来描述。
4.2.5.i2c_driver
structi2c_driver{
unsignedintclass;
int(*attach_adapter)(structi2c_adapter*);/*依附i2c_adapter函数指针*/
int(*detach_adapter)(structi2c_adapter*);/*脱离i2c_adapter函数指针*/
int(*probe)(structi2c_client*,conststructi2c_device_id*);
int(*remove)(structi2c_client*);
void(*shutdown)(structi2c_client*);
int(*suspend)(structi2c_client*,pm_message_tmesg);
int(*resume)(structi2c_client*);
void(*alert)(structi2c_client*,unsignedintdata);
int(*command)(structi2c_client*client,unsignedintcmd,void*arg);
structdevice_driverdriver;
conststructi2c_device_id*id_table;/*该驱动所支持的设备ID表*/
int(*detect)(structi2c_client*,structi2c_board_info*);/*设备探测函数*/
constunsignedshort*address_list;/*驱动支持的设备地址*/
structlist_headclients;/*挂接探测到的支持的设备*/
};
i2c_driver对应一套驱动方法,其主要成员函数是probe()、remove()、suspend()、resume()等,另外id_table是该驱动所支持的I2C设备的ID表。
i2c_driver与i2c_client的关系是一对多,一个i2c_driver上可以支持多个同等类型的i2c_client。
4.3.常用接口函数解析
4.3.1.i2c_add_driver
ØPROTOTYPE
staticinlineinti2c_add_driver(structi2c_driver*driver);
ØARGUMENTS
driverthepointertothei2cdevicedriver;
ØRETURNS
initresult;
=0initsuccessful;
<0initfailed;
ØDESCRIPTION
Registerani2cdevicedrivertoi2csub-system;
4.3.2.i2c_del_driver
ØPROTOTYPE
voidi2c_del_driver(structi2c_driver*driver);
ØARGUMENTS
driverthepointertothei2cdevicedriver;
ØRETURNS
None;
ØDESCRIPTION
Unregisterani2cdevicedriverfromi2csub-system;
4.3.3.i2c_set_clientdata
ØPROTOTYPE
staticinlinevoidi2c_set_clientdata(structi2c_client*dev,void*data);
ØARGUMENTS
devhandletoslavedevice;
dataprivatedatathatcanbesettoi2cclient;
ØRETURNS
None;
ØDESCRIPTION
Setprivatedatatoi2cclient;
4.3.4.i2c_get_clientdata
ØPROTOTYPE
staticinlinevoid*i2c_get_clientdata(conststructi2c_client*dev);
ØARGUMENTS
devhandletoslavedevice;
ØRETURNS
None;
ØDESCRIPTION
Getprivatedatafromi2cclient;
4.3.5.i2c_master_send
ØPROTOTYPE
inti2c_master_send(structi2c_client*client,constchar*buf,intcount);
ØARGUMENTS
clinethandletoslavedevice;
bufdatathatwillbewrittentotheslave;
counthowmanybytestowrite,mustbelessthan64ksincemsg.lenisu16;
ØRETURNS
sendresult;
>0thenumberofbyteswritten;
<0negativeerrno;
ØDESCRIPTION
IssueasingleI2Cmessageinmastertransmitmode;
4.3.6.i2c_master_resv
ØPROTOTYPE
inti2c_master_recv(structi2c_client*client,char*buf,intcount);
ØARGUMENTS
clinethandletoslavedevice;
bufwheretostoredatareadfromslave;
counthowmanybytestoread,mustbelessthan64ksincemsg.lenisu16;
ØRETURNS
receiveresult;
>0thenumberofbytesread;
<0negativeerrno;
ØDESCRIPTION
IssueasingleI2Cmessageinmasterreceivemode;
4.3.7.i2c_transfer
ØPROTOTYPE
inti2c_transfer(structi2c_adapter*adap,structi2c_msg*msgs,intnum);
ØARGUMENTS
adaphandletoI2Cbus;
msgsoneormoremessagestoexecutebeforeSTOPisissuedtoterminatetheoperation;eachmessagebeginswithaSTART;
numNumberofmessagestobeexecuted;
ØRETURNS
transferresult;
>0numberofmessagesexecuted;
<0negativeerrno;
ØDESCRIPTION
ExecuteasingleorcombinedI2Cmessage;notethatthereisnorequirementthateachmessagebesenttothesameslaveaddress,althoughthatisthemostcommonmodel.
4.4.I2C设备驱动DEMO
下面给出一个最简单的I2C设备驱动demo,例如i2c_driver_demo.c,文件具体内容如下:
#include
#include
#include
#include
staticinti2c_driver_demo_probe(structi2c_client*client,conststructi2c_device_id*id)
{
return0;
}
sta
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux IIC设备驱动开发 IIC 设备 驱动 开发