




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
Linux_I2C總線分析(主要是probe的方式)1Linux_I2C總線分析(主要是probe的方式)1/NUMPAGES24Linux_I2C總線分析(主要是probe的方式)1Linux_I2C總線分析(主要是probe的方式)1LinuxI2C總線淺析㈠Overview內(nèi)核空間層次!i2cadapter是一個struct,用來抽象一個物理i2cbus,而且還和linux設(shè)備驅(qū)動架構(gòu)柔和在一起..如果只說硬件的話,就是在CPU內(nèi)部集成的一個I2C控制器(提供給用戶的就是那幾個register),硬件上并沒的所謂的adapter,client這些東東,,adapter和client都是linux驅(qū)動軟件抽象出來的東西資料帖子:structi2c_algorithm{ /*Ifanadapteralgorithmcan'tdoI2C-levelaccess,setmaster_xfer toNULL.IfanadapteralgorithmcandoSMBusaccess,set smbus_xfer.IfsettoNULL,theSMBusprotocolissimulated usingcommonI2Cmessages*/ /*master_xfershouldreturnthenumberofmessagessuccessfully processed,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); /*Todeterminewhattheadaptersupports*/ u32(*functionality)(structi2c_adapter*);};/**i2c_adapteristhestructureusedtoidentifyaphysicali2cbusalong*withtheaccessalgorithmsnecessarytoaccessit.*/structi2c_adapter{ structmodule*owner; unsignedintid; unsignedintclass; /*classestoallowprobingfor*/ conststructi2c_algorithm*algo;/*thealgorithmtoaccessthebus*/ void*algo_data; /*datafieldsthatarevalidforalldevices */ u8level; /*nestinglevelforlockdep*/ structmutexbus_lock; inttimeout; /*injiffies*/ intretries; structdevicedev; /*theadapterdevice*/ intnr; charname[48]; structcompletiondev_released;};Linux的I2C體系結(jié)構(gòu)分為3個組成部分:1·I2C核心:I2C核心提供了I2C總線驅(qū)動和設(shè)備驅(qū)動的注冊、注銷方法,I2C通信方法(即“algorithm”)上層的、與具體適配器無關(guān)的代碼以及探測設(shè)備、檢測設(shè)備地址的上層代碼等。這部分是與平臺無關(guān)的。2·I2C總線驅(qū)動:I2C總線驅(qū)動是對I2C硬件體系結(jié)構(gòu)中適配器端的實現(xiàn)。I2C總線驅(qū)動主要包含了I2C適配器數(shù)據(jù)結(jié)構(gòu)i2c_adapter、I2C適配器的algorithm數(shù)據(jù)結(jié)構(gòu)i2c_algorithm和控制I2C適配器產(chǎn)生通信信號的函數(shù)。經(jīng)由I2C總線驅(qū)動的代碼,我們可以控制I2C適配器以主控方式產(chǎn)生開始位、停止位、讀寫周期,以及以從設(shè)備方式被讀寫、產(chǎn)生ACK等。不同的CPU平臺對應(yīng)著不同的I2C總線驅(qū)動??偩€驅(qū)動的職責(zé),是為系統(tǒng)中每個I2C總線增加相應(yīng)的讀寫方法。但是總線驅(qū)動本身并不會進行任何的通訊,它只是存在在那里,等待設(shè)備驅(qū)動調(diào)用其函數(shù)。這部分在MTK6516中是由MTK已經(jīng)幫我們實現(xiàn)了的,不需要我們更改。3·I2C設(shè)備驅(qū)動:I2C設(shè)備驅(qū)動是對I2C硬件體系結(jié)構(gòu)中設(shè)備端的實現(xiàn)。設(shè)備一般掛接在受CPU控制的I2C適配器上,通過I2C適配器與CPU交換數(shù)據(jù)。I2C設(shè)備驅(qū)動主要包含了數(shù)據(jù)結(jié)構(gòu)i2c_driver和i2c_client,我們需要根據(jù)具體設(shè)備實現(xiàn)其中的成員函數(shù)。在Linux內(nèi)核源代碼中的drivers目錄下的i2c_dev.c文件,實現(xiàn)了I2C適配器設(shè)備文件的功能,應(yīng)用程序通過“i2c-%d”文件名并使用文件操作接口open()、write()、read()、ioctl()和close()等來訪問這個設(shè)備。應(yīng)用層可以借用這些接口訪問掛接在適配器上的I2C設(shè)備的存儲空間或寄存器并控制I2C設(shè)備的工作方式。設(shè)備驅(qū)動則是與掛在I2C總線上的具體的設(shè)備通訊的驅(qū)動。通過I2C總線驅(qū)動提供的函數(shù),設(shè)備驅(qū)動可以忽略不同總線控制器的差異,不考慮其實現(xiàn)細節(jié)地與硬件設(shè)備通訊。這部分在MTK6516中是由具體的設(shè)備實現(xiàn)的。(比如camera)structi2c_client:代表一個掛載到i2c總線上的i2c從設(shè)備,該設(shè)備所需要的數(shù)據(jù)結(jié)構(gòu),其中包括該i2c從設(shè)備所依附的i2c主設(shè)備structi2c_adapter*adapter該i2c從設(shè)備的驅(qū)動程序structi2c_driver*driver作為i2c從設(shè)備所通用的成員變量,比如addr,name等該i2c從設(shè)備驅(qū)動所特有的數(shù)據(jù),依附于dev->driver_data下structi2c_adapter:代表主芯片所支持的一個i2c主設(shè)備。structi2c_algorithm*algo:是該i2c主設(shè)備傳輸數(shù)據(jù)的一種算法,或者說是在i2c總線上完成主從設(shè)備間數(shù)據(jù)通信的一種能力。Linux的i2c子系統(tǒng)新、舊架構(gòu)并存。主要分為舊架構(gòu)(Legacy)也有人稱之為adapter方式,和新的架構(gòu)new-style的方式。這倆者的區(qū)別主要在于設(shè)備注冊和驅(qū)動注冊的不同。對于Legacy的設(shè)備注冊是在驅(qū)動運行的時候動態(tài)的創(chuàng)建,而新式的new-style則是采用靜態(tài)定義的方式。注:MTK在Android2.1版上用的是Legacy的架構(gòu),而在Android2.2版上用的是new-style的架構(gòu)。(在這里我就只說明Android2.2的new-style的實現(xiàn)方法)要完成I2C設(shè)備的驅(qū)動,我們可以分三步走:第一步:完成適配器的注冊(總線);第二步:完成I2Cclient的設(shè)備注冊(設(shè)備);第三步:完成I2Cclient驅(qū)動的注冊(驅(qū)動);我們分別給予介紹:(I2C-mt6516.c)⑴就總線而言,其本質(zhì)只需要我們填充倆個結(jié)構(gòu)體就可以了:i2c_adapter;i2c_algorithm;i2c_add_adapter(i2c->adap);往總線上添加對應(yīng)的適配器;structi2c_adapter{
structmodule*owner;
unsignedintid;
unsignedintclass;
/*classestoallowprobingfor*/
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;
/*injiffies*/
intretries;
structdevicedev;
/*theadapterdevice*/
intnr;/*該成員描述了總線號*/
structlist_headclients;/*i2c_client結(jié)構(gòu)鏈表,該結(jié)構(gòu)包含device,driver和
adapter結(jié)構(gòu)*/
charname[48];
structcompletiondev_released;
};
staticstructi2c_algorithmmt6516_i2c_algorithm={.master_xfer=mt6516_i2c_transfer, .smbus_xfer=NULL, .functionality=mt6516_i2c_functionality,};2、設(shè)備注冊第一步:記得以前的i2c設(shè)備驅(qū)動,設(shè)備部分喜歡驅(qū)動運行的時候動態(tài)創(chuàng)建,新式的驅(qū)動傾向于向傳統(tǒng)的linux下設(shè)備驅(qū)動看齊,采用靜態(tài)定義的方式來注冊設(shè)備,使用接口為:
int__initi2c_register_board_info(intbusnum,
structi2c_board_infoconst*info,unsignedlen)
{
intstatus;
mutex_lock(&__i2c_board_lock);
/*dynamicbusnumberswillbeassignedafterthelaststaticone*/
if(busnum>=__i2c_first_dynamic_bus_num)
__i2c_first_dynamic_bus_num=busnum+1;
for(status=0;len;len--,info++){
structi2c_devinfo*devinfo;
devinfo=kzalloc(sizeof(*devinfo),GFP_KERNEL);//申請表示i2c設(shè)備的結(jié)構(gòu)體空間
if(!devinfo){
pr_debug("i2c-core:can'tregisterboardinfo!\n");
status=-ENOMEM;
break;
}
/*填寫i2c設(shè)備描述結(jié)構(gòu)*/
devinfo->busnum=busnum;
devinfo->board_info=*info;
list_add_tail(&devinfo->list,&__i2c_board_list);//添加到全局鏈表__i2c_board_list中
}
mutex_unlock(&__i2c_board_lock);
returnstatus;
}在系統(tǒng)初始化的過程中,我們可以通過i2c_register_board_info,將所需要的I2C從設(shè)備加入一個名為__i2c_board_list雙向循環(huán)鏈表,系統(tǒng)在成功加載I2C主設(shè)備adapt后,就會對這張鏈表里所有I2C從設(shè)備逐一地完成i2c_client的注冊。
第二步:
系統(tǒng)初始化的時候,會根據(jù)板級i2c設(shè)備配置信息,創(chuàng)建i2c客戶端設(shè)備(i2c_client),添加到i2c子系統(tǒng)中:
staticvoidi2c_scan_static_board_info(structi2c_adapter*adapter)
{
structi2c_devinfo*devinfo;
mutex_lock(&__i2c_board_lock);
list_for_each_entry(devinfo,&__i2c_board_list,list){//遍歷全局鏈表__i2c_board_list
if(devinfo->busnum==adapter->nr
&&!i2c_new_device(adapter,
&devinfo->board_info))
printk(KERN_ERR"i2c-core:can'tcreatei2c%d-%04x\n",
i2c_adapter_id(adapter),
devinfo->board_info.addr);
}
mutex_unlock(&__i2c_board_lock);
}
structi2c_client*i2c_new_device(structi2c_adapter*adap,structi2c_board_infoconst*info){ structi2c_client *client; int status; client=kzalloc(sizeof*client,GFP_KERNEL); if(!client) returnNULL; client->adapter=adap; client->dev.platform_data=info->platform_data; if(info->archdata) client->dev.archdata=*info->archdata; client->flags=info->flags; client->addr=info->addr; client->irq=info->irq; strlcpy(client->name,info->type,sizeof(client->name)); /*Checkforaddressbusiness*/ status=i2c_check_addr(adap,client->addr); if(status) gotoout_err; client->dev.parent=&client->adapter->dev; client->dev.bus=&i2c_bus_type; client->dev.type=&i2c_client_type; dev_set_name(&client->dev,"%d-%04x",i2c_adapter_id(adap), client->addr); status=device_register(&client->dev); if(status) gotoout_err; dev_dbg(&adap->dev,"client[%s]registeredwithbusid%s\n", client->name,dev_name(&client->dev)); returnclient;out_err: dev_err(&adap->dev,"Failedtoregisteri2cclient%sat0x%02x" "(%d)\n",client->name,client->addr,status); kfree(client); returnNULL;}IDR機制:完成的是設(shè)備ID和結(jié)構(gòu)體的關(guān)聯(lián)。__i2c_first_dynamic_bus_num:當(dāng)前系統(tǒng)允許的動態(tài)總線的最大值。i2c_scan_static_board_info(adap);/*完成新類型i2c設(shè)備的注冊,一般只在主板初始化時*/
此函數(shù)為整個I2C子系統(tǒng)的核心,它會去遍歷一個由I2C從設(shè)備組成的雙向循環(huán)鏈表,并完成所有I2C從設(shè)備的i2c_client的注冊。structi2c_devinfo*devinfo;
//已經(jīng)建立好了的I2C從設(shè)備鏈表status=i2c_check_addr(adap,client->addr);注:
特別要提一下的是這個“i2c_check_addr”,引用<<i2c源代碼情景分析>>里的話:“i2c設(shè)備的7位地址是就當(dāng)前i2c總線而言的,是“相對地址”。不同的i2c總線上的設(shè)備可以使用相同的7位地址,但是它們所在的i2c總線不同。所以在系統(tǒng)中一個i2c設(shè)備的“絕對地址”由二元組(i2c適配器的ID和設(shè)備在該總線上的7位地址)表示?!保赃@個函數(shù)的作用主要是排除同一i2c總線上出現(xiàn)多個地址相同的設(shè)備。3、I2C驅(qū)動注冊:第一步:
staticinlineinti2c_add_driver(structi2c_driver*driver)
{
returni2c_register_driver(THIS_MODULE,driver);
}
inti2c_register_driver(structmodule*owner,structi2c_driver*driver){ intres; /*Can'tregisteruntilafterdrivermodelinit*/ if(unlikely(WARN_ON(!i2c_bus_type.p))) return-EAGAIN; /*addthedrivertothelistofi2cdriversinthedrivercore*/ driver->driver.owner=owner; driver->driver.bus=&i2c_bus_type; /*Whenregistrationreturns,thedrivercore *willhavecalledprobe()forallmatching-but-unbounddevices. */ res=driver_register(&driver->driver); if(res) returnres; pr_debug("i2c-core:driver[%s]registered\n",driver->); INIT_LIST_HEAD(&driver->clients); /*Walktheadaptersthatarealreadypresent*/ mutex_lock(&core_lock); bus_for_each_dev(&i2c_bus_type,NULL,driver,__attach_adapter); mutex_unlock(&core_lock); return0;}設(shè)備和驅(qū)動的關(guān)聯(lián)過程:首先當(dāng)I2C從設(shè)備和I2C驅(qū)動如果處于同一條總線上,那么其在設(shè)備和驅(qū)動注冊之后,將會促使I2C_bus_type中的match獲得調(diào)用;()如下:structbus_typei2c_bus_type={ .name ="i2c", .match =i2c_device_match, .probe =i2c_device_probe, .remove =i2c_device_remove, .shutdown =i2c_device_shutdown, .suspend =i2c_device_suspend, .resume =i2c_device_resume,};繼續(xù)跟進i2c_device_match;i2c_match_id(driver->id_table,client)!=NULL;我們回到i2c_device_probe;這個函數(shù)的關(guān)鍵是:status=driver->probe(client,i2c_match_id(driver->id_table,client));它將函數(shù)的流程交回到了driver->probe的手中;流程圖:過程分享:1、設(shè)備和驅(qū)動的關(guān)聯(lián)
大家知道,對于一個驅(qū)動程序有兩個元素不可或缺,即設(shè)備和驅(qū)動,一般驅(qū)動都是通過設(shè)備名和驅(qū)動名的匹配建立關(guān)系的,最開始我從代碼中只能發(fā)現(xiàn)驅(qū)動的注冊,卻不見設(shè)備注冊的蹤影,令人疑惑,跟蹤發(fā)現(xiàn),在i2cadapter注冊時會遍歷i2c_board_info這樣一個結(jié)構(gòu),而這個結(jié)構(gòu)在29以前或更早的內(nèi)核里是不存在的,它會完成驅(qū)動與設(shè)備的匹配問題,
2、名字匹配
一個i2c驅(qū)動是可以有多個名字的,即一個驅(qū)動程序可以支持多個設(shè)備,該機制是通過structi2c_device_id實現(xiàn)的,驅(qū)動中建立這么一個結(jié)構(gòu)體數(shù)組,i2c架構(gòu)層便會掃描該數(shù)組,與設(shè)備名去匹配,匹配成功的都會進入相應(yīng)probe函數(shù)。
3、進入probe
該過程困惑了我一段時間,其實要進入自己驅(qū)動的probe首先需要進入總線的probe,而進入總線probe的前提是與總線的match成功。待解決的困惑:1、I2C從設(shè)備名;Legacy的相關(guān)知識:Linux的I2C驅(qū)動框架中的主要數(shù)據(jù)結(jié)構(gòu)及其關(guān)系Linux的I2C驅(qū)動框架中的主要數(shù)據(jù)結(jié)構(gòu)包括:i2c_driver、i2c_client、i2c_adapter和i2c_algorithm。i2c_adapter對應(yīng)于物理上的一個適配器,這個適配器是基于不同的平臺的,一個I2C適配器需要i2c_algorithm中提供的通信函數(shù)來控制適配器,因此i2c_adapter中包含其使用的i2c_algorithm的指針。i2c_algorithm中的關(guān)鍵函數(shù)master_xfer()以i2c_msg為單位產(chǎn)生I2C訪問需要的信號。不同的平臺所對應(yīng)的master_xfer()是不同的,開發(fā)人員需要根據(jù)所用平臺的硬件特性實現(xiàn)自己的XXX_xfer()方法以填充i2c_algorithm的master_xfer指針。i2c_driver對應(yīng)一套驅(qū)動方法,不對應(yīng)于任何的物理實體。i2c_client對應(yīng)于真實的物理設(shè)備,每個I2C設(shè)備都需要一個i2c_client來描述。i2c_client依附于i2c_adpater,這與I2C硬件體系中適配器和設(shè)備的關(guān)系一致。i2c_driver提供了i2c-client與i2c-adapter產(chǎn)生聯(lián)系的函數(shù)。當(dāng)attacha_dapter()函數(shù)探測物理設(shè)備時,如果確定存在一個client,則把該client使用的i2c_client數(shù)據(jù)結(jié)構(gòu)的ad
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度水上樂園游泳館場地租賃與水上樂園配套設(shè)施租賃協(xié)議
- 2025年度老舊小區(qū)外墻改造工程安全責(zé)任合同
- 二零二五年度國際貿(mào)易信用證業(yè)務(wù)代理及風(fēng)險管理協(xié)議
- 海洋漁業(yè)資源保護與海產(chǎn)品銷售一體化合同
- 二零二五年度企業(yè)用工協(xié)議與勞動權(quán)益保障與員工激勵機制合同
- 二零二五年度廠房裝修施工安全責(zé)任與綠色施工標(biāo)準(zhǔn)協(xié)議書
- 2025年度酒店與旅游紀(jì)念品店合作經(jīng)營合同
- 二零二五年度籃球活動參與者免責(zé)責(zé)任協(xié)議
- 二零二五年度汽車美容店員工勞動爭議解決合同模板
- 二零二五年度農(nóng)村房屋贈與合同附農(nóng)業(yè)保險合作協(xié)議
- (望聞問切-完整版)九型體質(zhì)調(diào)查表
- 芋頭種植技術(shù)要點
- 雞場規(guī)劃與建設(shè)完整版資料課件
- 經(jīng)濟學(xué)彈性理論課件
- 公司員工獎懲制度流程
- 星巴克案例分析-星巴克成功之道
- 把未來點亮歌詞打印版
- 危險化學(xué)品建設(shè)項目竣工驗收報告
- 婦產(chǎn)科學(xué)(第9版)第三章 女性生殖系統(tǒng)生理
- LY/T 2241-2014森林生態(tài)系統(tǒng)生物多樣性監(jiān)測與評估規(guī)范
- GB/T 9086-2007用于色度和光度測量的標(biāo)準(zhǔn)白板
評論
0/150
提交評論