i2c總線是一種十分常見的板級(jí)總線,本文以linux3.14.0為參考, 討論Linux中的i2c驅(qū)動(dòng)模型并利用這個(gè)模型寫一個(gè)mpu6050的驅(qū)動(dòng), 最后在應(yīng)用層將mpu6050中的原始數(shù)據(jù)讀取出來
i2c子系統(tǒng)框架
下圖就是我理解的i2c驅(qū)動(dòng)框架示意圖, 類似中斷子系統(tǒng), i2c子系統(tǒng)中也使用一個(gè)對(duì)象來描述一個(gè)物理實(shí)體, 設(shè)備對(duì)象與驅(qū)動(dòng)分離, 驅(qū)動(dòng)結(jié)合設(shè)備對(duì)象對(duì)硬件設(shè)備的描述才可以驅(qū)動(dòng)一個(gè)具體的物理設(shè)備, 體現(xiàn)了分離的設(shè)計(jì)思想, 實(shí)現(xiàn)了代碼的復(fù)用, 比如:
一個(gè)i2c控制器就對(duì)應(yīng)一個(gè)i2c_board_info, 它驅(qū)動(dòng)就是s3c2410_i2c_driver, 他們通過platform_bus_type協(xié)調(diào)工作。
一個(gè)i2c總線上的設(shè)備就對(duì)應(yīng)內(nèi)核中的一個(gè)i2c_client類型的對(duì)象, 它的驅(qū)動(dòng)就是的i2c_driver, 二者通過i2c_bus_type協(xié)調(diào)工作。
同樣是抽象的思路, 對(duì)于i2c總線本身, 內(nèi)核也使用i2c_bus_type來描述。
事實(shí)上, 對(duì)于任何一種總線, 內(nèi)核都有一個(gè)bus_type類型的對(duì)象與之對(duì)應(yīng), 但是platform_bus_type并沒有對(duì)應(yīng)的實(shí)際的物理總線, 這也就是platform總線也叫虛擬總線的原因.
除了分離,i2c子系統(tǒng)也體現(xiàn)的軟件分層的設(shè)計(jì)思想, 整個(gè)i2c子系統(tǒng)由3層構(gòu)成:設(shè)備驅(qū)動(dòng)層--i2c核心--控制器驅(qū)動(dòng)
除了經(jīng)典的分層與分離模型,我們也可以看到一個(gè)有意思的現(xiàn)象——Linux 的應(yīng)用程序不但可以通過設(shè)備驅(qū)動(dòng)來訪問i2c從設(shè)備,還可以通過一個(gè)并沒有直接掛接到i2c_bus_type的i2c_cleint來找到主機(jī)控制器進(jìn)而訪問任意一個(gè)i2c設(shè)備, 這是怎么回事呢? 我會(huì)在下一篇說^-^
核心結(jié)構(gòu)和方法簡述
核心結(jié)構(gòu)
i2c_adapter對(duì)象實(shí)現(xiàn)了一組通過一個(gè)i2c控制器發(fā)送消息的所有信息, 包括時(shí)序, 地址等等, 它被i2c主機(jī)驅(qū)動(dòng)創(chuàng)建, 通過i2c-core.c和i2c_client和i2c_driver聯(lián)系到一起, 這樣設(shè)備端驅(qū)動(dòng)就可以通過其中的方法以及i2c物理控制器來和一個(gè)i2c總線的物理設(shè)備進(jìn)行交互
i2c_algorithm描述一個(gè)i2c主機(jī)的發(fā)送時(shí)序的信息,該類的對(duì)象algo是i2c_adapter的一個(gè)域
i2c_client描述一個(gè)掛接在硬件i2c總線上的設(shè)備的設(shè)備信息,即i2c設(shè)備的設(shè)備對(duì)象
i2c_driver描述一個(gè)掛接在硬件i2c總線上的設(shè)備的驅(qū)動(dòng)方法,即i2c設(shè)備的驅(qū)動(dòng)對(duì)象,通過i2c_bus_type和設(shè)備對(duì)象相連
i2c_msg描述一個(gè)在設(shè)備端和主機(jī)端之間進(jìn)行流動(dòng)的數(shù)據(jù), 在設(shè)備驅(qū)動(dòng)中打包并通過i2c_transfer()發(fā)送。相當(dāng)于skbuf之于網(wǎng)絡(luò)設(shè)備,urb之于USB設(shè)備。