基于iicds3231linux驱动说明基于I2C实时时钟DS3231驱动说明:1Linux的I2C的整体架构Linux的i2c框架中各个部分的关系如图(1)所示:图(1)内核中i2c相关代码可以分为三个层次:●i2c框架:i2c.h和i2c-core.c为i2c框架的主体,提供了核心数据结构的定义、i2c适配器驱动和设备驱动的注册、注销管理,i2c通信方法上层的、与具体适配器无关的代码、检测设备地址的上层代码等;i2c-dev.c用于创建i2c适配器的/dev/i2c/%d设备节点,提供i2c设备访问方法等。●i2c总线适配器驱动:定义描述具体i2c总线适配器的i2c_adapter数据结构、实现在具体i2c适配器上的i2c总线通信方法,并由i2c_algorithm数据结构进行描述。●i2c设备驱动:定义描述具体设备的i2c_client和可能的私有数据结构、借助i2c框架的i2c_probe函数实现注册设备的attach_adapter方法、提供设备可能使用的地址范围、以及设备地址检测成功后创建i2c_client数据结构的回调函数。2I2C驱动相关的数据结构I2C传送信息的数据结构体structi2c_msg{__u16addr;/*slaveaddress*/__u16flags;#defineI2C_M_TEN0x10/*wehaveatenbitchipaddress*/#defineI2C_M_RD0x01#defineI2C_M_NOSTART0x4000#defineI2C_M_REV_DIR_ADDR0x2021#defineI2C_M_IGNORE_NAK0x1000#defineI2C_M_NO_RD_ACK0x0800__u16len;/*msglength*/__u8*buf;/*pointertomsgdata*/};其中addr成员是指向器件的地址,flags是读写标志位,len是要发送的信息长度,*buf是发送信息的数据指针,如果是读操作的buf是读到数据的指针。I2C低层数据传输函数结构体structi2c_algorithm{/*Ifanadapteralgorithmcan'tdoI2C-levelaccess,setmaster_xfertoNULL.IfanadapteralgorithmcandoSMBusaccess,setsmbus_xfer.IfsettoNULL,theSMBusprotocolissimulatedusingcommonI2Cmessages*//*master_xfershouldreturnthenumberofmessagessuccessfullyprocessed,oranegativevalueonerror*/int(*master_xfer)(structi2c_adapter*adap,structi2c_msg*msgs,intnum);int(*smbus_xfer)(structi2c_adapter*adap,u16addr,unsignedshortflags,charread_write,u8command,intsize,unioni2c_smbus_data*data);/*---ioctllikecalltosetdiv.parameters.*/int(*algo_control)(structi2c_adapter*,unsignedint,unsignedlong);/*Todeterminewhattheadaptersupports*/u32(*functionality)(structi2c_adapter*);};master_xfer函数为I2C适配器提供数据传输函数,smbu_xfer函数为subus协议函数,functionality函数I2C适配器所支持的功能函数。I2c适配器数据结构体structi2c_adapter{structmodule*owner;unsignedintid;unsignedintclass;conststructi2c_algorithm*algo;/*thealgorithmtoaccessthebus*/void*algo_data;/*---administrationstuff.*/int(*client_register)(structi2c_client*);int(*client_unregister)(structi2c_client*);/*datafieldsthatarevalidforalldevices*/u8level;/*nestinglevelforlockdep*/structmutexbus_lock;structmutexclist_lock;inttimeout;intretries;structdevicedev;/*theadapterdevice*/structclass_deviceclass_dev;/*theclassdevice*/intnr;structlist_headclients;structlist_headlist;charname[I2C_NAME_SIZE];structcompletiondev_released;structcompletionclass_dev_released;};适配器主要通过i2c_algorithm结构体成员确定低层数据的传输方法,client_register函数用来注册一个i2c_client设备,client_unregister函数用来注销一个i2c_client设备,bus_lock总线互斥锁定义,I2C设备的描述结构体structi2c_client{unsignedintflags;/*div.,seebelow*/unsignedshortaddr;/*chipaddress-NOTE:7bit*//*addressesarestoredinthe*//*_LOWER_7bits*/structi2c_adapter*adapter;/*theadapterwesiton*/structi2c_driver*driver;/*andouraccessroutines*/intusage_count;/*Howmanyaccessescurrently*//*totheclient*/structdevicedev;/*thedevicestructure*/structlist_headlist;charname[I2C_NAME_SIZE];structcompletionreleased;};addr设备芯片的地址,adapter指针指向设备所在的适配器结构体,driver指针指向所属的i2c驱动结构,dev设备结体I2C驱动结构体structi2c_driver{intid;unsignedintclass;/*Notifiesthedriverthatanewbushasappeared.Thisroutine*canbeusedbythedrivertotestifthebusmeetsitsconditions*&seekforthepresenceofthechip(s)itsupports.Iffound,it*registerstheclient(s)thatareonthebustothei2cadmin.via*i2c_attach_client.*/int(*attach_adapter)(structi2c_adapter*);int(*detach_adapter)(structi2c_adapter*);/*tellsthedriverthataclientisabouttobedeleted&givesit*thechancetoremoveitsprivatedata.Also,iftheclientstruct*hasbeendynamicallyallocatedbythedriverinthefunctionabove,*itmustbefreedhere.*/int(*detach_client)(structi2c_client*);/*aioctllikecommandthatcanbeusedtoperformspecificfunctions*withthedevice.*/int(*command)(structi2c_client*client,unsignedintcmd,void*arg);structdevice_driverdriver;structlist_headlist;};Attach_adapter注册I2C设备引用的函数指针,detach_adapter注销I2C设备引用的函数指针。3引用到的I2C相关函数3.1.用到的I2C驱动中各个函数的说明staticinlinevoid*dev_get_drvdata(structdevice*dev)返回设备私有数据的指针。staticinlinevoidi2c_set_clientdata(structi2c_client*dev,void*data)保存一个数据到设备的私有数据中。inti2c_transfer(structi2c_adapter*adap,structi2c_msg*msgs,intnum)I2C数据信息到设备中去,s32i2c_smbus_write_byte_data(structi2c_client*client,u8command,u8value)写一个值到指定位置。staticinlineinti2c_check_functionality(structi2c_adapter*adap,u32func)判断I2C适配器所是否支持的功能inti2c_probe(structi2c_adapter*adapter,structi2c_client_address_data*address_data,int(*found_proc)(structi2c_adapter*,int,int))检没I2C设备是否存在。inti2c_attach_client(structi2c_client*client)注册I2C设备inti2c_attach_client(structi2c_client*client)注销I2C设备staticinlineinti2c_add_driver(structi2c_driver*driver)注册I2C设备驱动inti2c_del_driver(structi2c_driver*driver)注销I2C设备驱动3.2.时钟驱动中各个函数的说明staticintds3231_get_time(structdevice*dev,structrtc_time*t)得到时钟数据。staticintds3231_set_time(structdevice*dev,structrtc_time*t)设置数据到时钟中去。staticint__devinitds3231_detect(structi2c_adapter*adapter,intaddress,intkind)进行一些数据的初始化。staticint__devinitds3231_attach_adapter(structi2c_adapter*adapter)检测I2C设备是否存在,如果有存在就进行设备注册。staticint__devexitds3231_detach_client(structi2c_client*client)注销I2C设备驱动。4编译驱动到内核中4.1.在driver/rtc/Kconfig文件添加DS3231驱动的支持增加对DS3231选项,在Kconfig文件中如下蓝色文字添加。commentRTCdriversdependsonRTC_CLASSconfigRTC_DRV_X1205tr