下载

2下载券

加入VIP
  • 专属下载特权
  • 现金文档折扣购买
  • VIP免费专区
  • 千万文档免费下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 linux 下i2c总线与 时钟芯片pcf8563通信

linux 下i2c总线与 时钟芯片pcf8563通信.pdf

linux 下i2c总线与 时钟芯片pcf8563通信

MR_Han_Via
2012-07-06 0人阅读 举报 0 0 暂无简介

简介:本文档为《linux 下i2c总线与 时钟芯片pcf8563通信pdf》,可适用于IT/计算机领域

作者:韩大卫吉林师范大学电子信息inux驱动对大部分人是枯燥繁琐的事情读linux的驱动代码也是痛苦的事如果没有这份耐心现在就停止下面的阅读。ic总线是嵌入式驱动中不能绕过一个地方为了更深入的了解linux下的ic通信原理我用一个用户程序模拟这个程序简单的说就是可以使用一个addr,一个offset对ic的地址为addr的从设备进行读写访问访问的寄存器是这个从设备的寄存器地址为offset。在我们的版卡上时钟芯片pcf的ic地址为xpcf有f个寄存器通过读写秒分钟小时等的寄存器可以验证我们的程序是否执行成功。需要pcf的datasheet,读者可在网上查找。我们版卡的cpu是CaviumNetworksOCTEONCNXXallthecodewirtenby韩大卫吉林师范大学handaweijusontechcom转载务必表明出处!*********************************************************************************************************************************************{structpcf*pcf=icgetclientdata(client)inti,errunsignedcharbufprintk(KERNDEBUG"s:secs=d,mins=d,hours=d,ecs=d,mins=d,hours=dn",func,tm>tmsec,tm>tmmin,tm>tmhour,tm>tmmday,tm>tmmon,tm>tmyear,tm>tmwday)*hours,minutesandseconds*bufPCFREGSC=binbcd(tm>tmsec)bufPCFREGMN=binbcd(tm>tmmin)bufPCFREGHR=binbcd(tm>tmhour)bufPCFREGDM=binbcd(tm>tmmday)*month,*bufPCFREGMO=binbcd(tm>tmmon)*yearandcentury*bufPCFREGYR=binbcd(tm>tmyear)if(pcf>cpolarity(tm>tmyear>=):(tm>tmyear<))bufPCFREGMO|=PCFMOCbufPCFREGDW=tm>tmwdayx*writeregister'sdata*for(i=i<i){unsignedchardata={PCFREGSCi,bufPCFREGSCi}err=icmastersend(client,data,sizeof(data))if(err!=sizeof(data)){deverr(client>dev,"s:err=daddr=x,data=xn",func,err,data,data)returnEIO}在drivericiccorec中:inticmastersend(structicclient*client,constchar*buf,intcount){intretstructicadapter*adap=client>adapterstructicmsgmsgmsgaddr=client>addrmsgflags=client>flagsICMTENmsglen=countmsgbuf=(char*)bufaddedbyhandweiaddedbyhandweiprintk(KERNDEBUG"s:msgaddr=x,msgflags=x,msglen=d,msgbuf=x,msgbuf=xn",func,msgaddr,msgflags,msglen,msgbuf,msgbuf)ret=ictransfer(adap,msg,)*Ifeverythingwentok(iemsgtransmitted),return#bytestransmitted,elseerrorcode*return(ret==)count:ret}注意:ictransfer(adap,msg,)中的决定了进入octeonicxfer()后要进入if(num==)中。下面是octeonicxfer的代码:staticintocteonicxfer(structicadapter*adap,structicmsg*msgs,intnum){printk(KERNDEBUG"hereisocteonicxfer,num=dn",num)structicmsg*pmsgintiintret=structocteonic*ic=icgetadapdata(adap)if(num==){if(msgslen>msgslen<=){if(msgsflagsICMRD)ret=octeonicsimpleread(ic,msgs)elseret=octeonicsimplewrite(ic,msgs)gotoout}}elseif(num==){if((msgsflagsICMRD)==msgslen>msgslen<=msgslen>msgslen<=msgsaddr==msgsaddr){if(msgsflagsICMRD)ret=octeoniciaread(ic,msgs)elseret=octeoniciawrite(ic,msgs)gotoout}}for(i=ret==i<numi){pmsg=msgsidevdbg(ic>dev,"Doingsdbyte(s)tofromxxdofdmessagesn",pmsg>flagsICMRD"read":"write",pmsg>len,pmsg>addr,i,num)if(pmsg>flagsICMRD)ret=octeonicread(ic,pmsg>addr,pmsg>buf,pmsg>len,i)}octeonicstop(ic)out:return(ret!=)ret:num}通过在iccorec:icmastersend()中添加printkaddedbyhandweiprintk(KERNDEBUG"s:msgaddr=x,msgflags=x,msglen=d,msgbuf(data)=sn",func,msgaddr,msgflags,msglen,msgbuf)运行后可以看到msgflags一直等于那么在octeonicxfer()中if(num==){if(msgslen>msgslen<=){if(msgsflagsICMRD)ret=octeonicsimpleread(ic,msgs)elseret=octeonicsimplewrite(ic,msgs)gotoout会一直进入octeonicsimplewrite()执行写操作。下面是octeonicsimplewrite()的代码:staticintocteonicsimplewrite(structocteonic*ic,structicmsg*msgs){ucmdinti,jintret=octeonicenablehlc(ic)printk(KERNDEBUG"s:n",func)retry:cmd=SWTWSIV|SWTWSISOVR*SIZE*cmd|=(u)(msgslen)<<SWTWSISIZESHIFT*A*cmd|=(u)(msgsaddrxfull)<<SWTWSIASHIFTif(msgsflagsICMTEN)cmd|=SWTWSIOPelsecmd|=SWTWSIOPprintk(KERNDEBUG"s:cmd=llxn",func,cmd)for(i=,j=msgsleni<msgsleni<i,j){cmd|=(u)msgsbufj<<(*i)printk(KERNDEBUG"s:msgsbufd=x,cmd=llxn",func,j,msgsbufj,cmd)}if(msgslen>=){uext=for(i=i<msgsleni<i,j)ext|=(u)msgsbufj<<(*i)printk(KERNDEBUG"s:ext=llxn",func,ext)rawwriteq(ext,ic>twsibaseSWTWSIEXT)}octeonichlcintclear(ic)rawwriteq(cmd,ic>twsibaseSWTWSI)ret=octeonichlcwait(ic)if(ret)gotoerrcmd=rawreadq(ic>twsibaseSWTWSI)if((cmdSWTWSIR)==){if(octeoniclostarb(cmd))gotoretryret=EIOgotoerr}err:returnret}下面是版卡执行hwclockw后的dmesg中的一部分:pcfgetdatetime:secs=,mins=,hours=,ecs=,mins=,hours=pcfsetdatetime:secs=,mins=,hours=,ecs=,mins=,hours=pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=pcfgetdatetime:是读到的时间pcfsetdatetime:是要写的时间在第一个部分:pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=在pcfsetdatetime()中:for(i=i<i){unsignedchardata={PCFREGSCi,注意:#definePCFREGSCxerr=icmastersend(client,data,sizeof(data))if(err!=sizeof(data)){deverr(client>dev,"s:err=daddr=x,data=xn",func,err,data,data)}通过icmastersend()进入octeonicxfer()再进入octeonicsimplewrite{cmd=SWTWSIV|SWTWSISOVRcmd|=(u)(msgslen)<<SWTWSISIZESHIFTAddressfield:<:>cmd|=(u)(msgsaddrxfull)<<SWTWSIASHIFTif(msgsflagsICMTEN)cmd|=SWTWSIOPfor(i=,j=msgsleni<msgsleni<i,j){cmd|=(u)msgsbufj<<(*i)}根据msgs中的lenaddrflags,buf中的内容填充cmd执行cmd并返回执行结果同样的在进入第二次循环时这时操作的是pcf的第三个寄存器h:minutes分钟寄存器。pcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=第三次操作pcf的第四个寄存器:hhourspcfsetdatetime:data=,data=icmastersend:msgaddr=,msgflags=,msglen=,msgbuf=,msgbuf=hereisocteonicxfer,num=octeonicsimplewrite:octeonicsimplewrite:cmd=octeonicsimplewrite:msgsbuf=,cmd=octeonicsimplewrite:msgsbuf=,cmd=我们看到:hwclockw通过octeonicsimplewrite来写pcf时钟芯片其中:msgaddr=x,msglen=,msgflags=,msgbuf=相应地址偏移msgbuf=给相应寄存器的值那么我们的ictest,也这样操作试试:包装一个msg,传入octeonicxfer()再传入octeonicsimplewrite看看能不能得到期望的执行结果。另外还要通过hwclock来观察为什么没有使用octeonicsimpleread来读寄存器的现象。注意到:在关于写的操作中:pcfsetdatetime()icmastersend(){msgaddr=client>addrmsgflags=client>flagsICMTENmsglen=countmsgbuf=(char*)bufret=ictransfer(adap,msg,)}ictransfer最后一个参数是就是写的时候每次只写一个msg这个msg中的成员buf在pcfsetdatetime()中做了相应的填充:for(i=i<i){unsignedchardata={PCFREGSCi,bufPCFREGSCi}err=icmastersend(client,data,sizeof(data))}最后这一个msg中buf内容包括了全部的写的信息。而在pcfgetdatetime(structicclient*client,structrtctime*tm){structpcf*pcf=icgetclientdata(client)unsignedcharbuf={PCFREGST}structicmsgmsgs={{client>addr,,,buf},*setupreadptr*{client>addr,ICMRD,,buf},*readstatusdate*}if((ictransfer(client>adapter,msgs,))!=)}ictransfer第三个参数是即每次读操作时每次操作个msg。两个msgaddr相同flags不同,len不同buf内容也不同。正是由于pcfgetdatetime与pcfsetdatetime每次操作msg的个数不同所以进入octeonicxfer()后执行的函数不同这就是为什么每次pcfgetdatetime操作了octeonicxfer的octeonicwrite()与octeonicread()而pcfsetdatetime每次操作了octeonicxfer的octeonicsimplewrite()这就是为什么使用hwclockw后观察不到octeonicxfer()进入octeonicsimpleread()的原因。Hwclockw后:hereispcfgetdatetime,nextfuncisictransfer!octeonicxfer:num=octeonicxfer:msgsaddr=,msgsflags=,msgslen=octeonicxfer:msgsbuf=octeonicxfer:msgsaddr=,msgsflags=,msgslen=octeonicxfer:msgsbuf=octeonicwrite:data(msgs>buf)=,target(addr)=,length=,phase=octeonicwrite:data=octeonicread:data(msgs>buf)=,target(addr)=,length=,phase=octeonicread:data=octeonicread:data=octeonicread:data=octeonicread:data=octeonicread:data=octeonicread:data=octeonicread:data=docteonicread:data=octeonicread:data=octeonicread:data=aocteonicread:data=octeonicread:data=bocteonicread:data=bherecomebackpcfgetdatetime,thereceiveddata:secs=,mins=,hours=,mday=,mon=,year=,wday=由于num=进入octeonicxfer后先要判断:elseif(num==){if((msgsflagsICMRD)==msgslen>msgslen<=msgslen>msgslen<=msgsaddr==msgsaddr){if(msgsflagsICMRD)ret=octeoniciaread(ic,msgs)elseret=octeoniciawrite(ic,msgs)gotooutfor(i=ret==i<numi){pmsg=msgsidevdbg(ic>dev,"Doingsdbyte(s)tofromxxdofdmessagesn",pmsg>flagsICMRD"read":"write",pmsg>len,pmsg>addr,i,num)if(pmsg>flagsICMRD)ret=octeonicread(ic,pmsg>addr,pmsg>buf,pmsg>len,i)elseret=octeonicwrite(ic,pmsg>addr,pmsg>buf,pmsg>len,i)}由于msgslen=不满足条件因此即使num=,pcfgetdatetime永远不会进入octeoniciareadwrite不会进入内部地址的读写操作。之后程序进入for循环这样经过判断第一次要进入octeonicwrite()函数第二次循环进入octeonicread()在Octeonicwrite()中:staticintocteonicwrite(structocteonic*ic,inttarget,constu*data,intlength,intphase){inti,resultutmprestart:result=octeonicstart(ic)if(result)returnresultocteonicwritesw(ic,SWTWSIEOPTWSIDATA,target<<)octeonicwritesw(ic,SWTWSIEOPTWSICTL,TWSICTLENAB)result=octeonicwait(ic)if(result)returnresultfor(i=i<lengthi){tmp=octeonicreadsw(ic,SWTWSIEOPTWSISTAT)if(phase==octeoniclostarb(tmp))gotorestartif((tmp!=STATTXADDRACK)(tmp!=STATTXDATAACK)){deverr(ic>dev,"s:badstatusbeforewrite(xx)n",func,tmp)returnEIO}printk(KERNDEBUG"s:datad=xn",func,i,datai)octeonicwritesw(ic,SWTWSIEOPTWSIDATA,datai)octeonicwritesw(ic,SWTWSIEOPTWSICTL,TWSICTLENAB)result=octeonicwait(ic)if(result)returnresult}return}其中:octeonicwritesw(ic,SWTWSIEOPTWSIDATA,datai)作用就是将datai数据写进入octeon的数据寄存器即实现了写的操作。staticintocteonicread(structocteonic*ic,inttarget,u*data,intlength,intphase){addedbyhandaweiprintk(KERNDEBUG"s:data(msgs>buf)=xtarget(addr)

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

文档小程序码

使用微信“扫一扫”扫码寻找文档

1

打开微信

2

扫描小程序码

3

发布寻找信息

4

等待寻找结果

我知道了
评分:

/18

linux 下i2c总线与 时钟芯片pcf8563通信

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利