溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

發(fā)布時間:2021-10-21 17:28:55 來源:億速云 閱讀:135 作者:柒染 欄目:互聯(lián)網(wǎng)科技

本篇文章為大家展示了怎么進(jìn)行Linux的I2C驅(qū)動框架分析,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。

1.基本概念

總線

總線代表著同類設(shè)備需要共同遵守的工作時序,不同的總線對于物理電平的要求是不一樣的,對于每個比特的電平維持寬度也是不一樣,而總線上傳遞的命令也會有自己的格式約束。如I2C總線、USB總線、PCI總線等等。以I2C總線為例,在同一組I2C總線上連接著不同的I2C設(shè)備。

設(shè)備

設(shè)備代表真實(shí)的、具體的物理器件,在軟件上用器件的獨(dú)特的參數(shù)屬性來代表該器件。如I2C總線上連接的I2C從設(shè)備都有一個標(biāo)識自己的設(shè)備地址,由這個設(shè)備地址來確定主設(shè)備發(fā)過來的命令是否該由它來響應(yīng)。

驅(qū)動

簡單的說驅(qū)動代表著操作設(shè)備的方式和流程。

Linux總線設(shè)備框架的工作原理

如果想要弄清楚I2C驅(qū)動框架,必須深刻的理解Linux的總線設(shè)備框架。之所以會形成這樣的框架,很重要的原因是為了代碼的復(fù)用性。因?yàn)轵?qū)動和設(shè)備的關(guān)系是一對多的,對于相同類型的不同的設(shè)備,可共用同一套驅(qū)動程序接口。為了提高驅(qū)動的可移植性,Linux抽象出一套管理資源的函數(shù)。設(shè)備是存在的硬件,在設(shè)備里包含自己的屬性,也包含需要用到的資源。

總線的作用就是在軟件層面上對設(shè)備和驅(qū)動進(jìn)行管理,設(shè)備要讓系統(tǒng)感知到自己的存在,所以需要向總線去注冊設(shè)備,驅(qū)動同樣也要向總線去注冊。對于總線,有I2C總線,Platform總線等等。但是Platform是虛擬總線。

對于總線上設(shè)備與驅(qū)動的匹配,由總線負(fù)責(zé),設(shè)備在注冊的時候,總線會遍歷注冊在總線上的驅(qū)動,如果名字相同,則匹配上了,此時調(diào)用驅(qū)動程序的probe函數(shù)。同樣的驅(qū)動在注冊的時候,也會遍歷總線上的設(shè)備,如果匹配上(名字一樣),則也會調(diào)用驅(qū)動程序的probe函數(shù)。

2.I2C傳輸協(xié)議


對于I2C來說,有如下的特點(diǎn):

1.一條串行數(shù)據(jù)線(SDA),一條串行時鐘線(SCL)

2.每個接到總線上的器件都可以使用軟件根據(jù)它的唯一地址來識別。

3.串行的8位雙向數(shù)據(jù)傳輸,位速率在標(biāo)志模式下可達(dá)100kbit/s,在快速模式下可達(dá)400kbit/s。在高速模式下可達(dá)3.4Mbit/s。

下面來看一下具體的硬件連接

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

以上是TFS上的攝像頭I2C的連接方式,只有兩根線即可實(shí)現(xiàn)數(shù)據(jù)的傳輸。在傳輸過程中,需要注意以下三種類型的信號:

(1)開始信號(S):SCL為高電平時,SDA由高向低電平跳變,開始傳輸數(shù)據(jù)

(2)結(jié)束信號(P):SCL為高電平時,SDA由低向高電平跳變,結(jié)束傳輸數(shù)據(jù)

(3)響應(yīng)信號(ACK):接收器在接收到8位數(shù)據(jù)后,在第9個時鐘周期,拉低SDA的電平

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

以上就是I2C的硬件層與協(xié)議層的基本概述,這部分可以作為基本認(rèn)知。

3.Linux下I2C驅(qū)動程序的體系結(jié)構(gòu)


對于Linux下的I2C驅(qū)動,其體系結(jié)構(gòu)的組成主要分為三個部分

(1)I2C核心:I2C核心提供了I2C總線驅(qū)動和設(shè)備驅(qū)動的注冊,注銷方法,I2C通信方法(”algorithm”)上層的,與具體適配器無關(guān)的代碼以及探測設(shè)備,檢測設(shè)備地址的上層代碼等。

(2)I2C總線驅(qū)動:I2C總線驅(qū)動是對I2C硬件體系結(jié)構(gòu)中適配器端的實(shí)現(xiàn),適配器可由CPU控制,甚至可以直接集成在CPU內(nèi)部。

(3)I2C設(shè)備驅(qū)動:I2C設(shè)備驅(qū)動(也稱為客戶驅(qū)動)是對I2C硬件體系結(jié)構(gòu)中設(shè)備端的實(shí)現(xiàn),設(shè)備一般掛接在受CPU控制的I2C適配器上,通過I2C適配器與CPU交換數(shù)據(jù)。

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

比較重要的文件

\kernel\drivers\i2c\i2c-core.c

這個文件實(shí)現(xiàn)了 I2C 核心的功能以及/proc/bus/i2c*接口。同時對I2C底層的收發(fā)函數(shù)進(jìn)行封裝。會調(diào)用i2c_transfer ,里面實(shí)現(xiàn)了adap->algo->master_xfer(adap, msgs, num)

kernel\drivers\i2c\i2c-dev.c

該函數(shù)注冊了一個設(shè)備文件的功能,也就是注冊了一個字符設(shè)備驅(qū)動程序,可以通過/dev/i2c-0(i2c-0, i2c-1,…, i2c-10,…)找到具體的I2C適配器,這個I2C設(shè)備的主設(shè)備號為89,次設(shè)備號0~255。通過訪問這個接口,可以通過open()、 write()、 read()、 ioctl()和 close()等來訪問這個設(shè)備。

kernel\drivers\i2c\busses\i2c-v12-jz.c

該函數(shù)對君正的x1000底層的I2C操作控制函數(shù),通過設(shè)置寄存器來進(jìn)行I2C的控制。其最底層的收發(fā)函數(shù)都在該文件里定義。重要的是i2c_jz_algorithm,其中algorithm實(shí)現(xiàn)了對底層寄存器的操作。

比較重要的結(jié)構(gòu)體

i2c_driver、 i2c_client、 i2c_adapter 和 i2c_algorithm這四個結(jié)構(gòu)體十分的關(guān)鍵

i2c_driver

對應(yīng)一套驅(qū)動方法,是純粹的用于輔助作用的數(shù)據(jù)結(jié)構(gòu),它不對應(yīng)于任何的物理實(shí)體。

i2c_client

對應(yīng)于真實(shí)的物理設(shè)備,每個 I2C 設(shè)備都需要一個 i2c_client 來描述。i2c_client 一般被包含在 I2C 字符設(shè)備的私有信息結(jié)構(gòu)體中。

i2c_adpater

用來匹配i2c_driver與i2c_client。即 i2c_client 依附于 i2c_adpater。由于一個適配器上可以連接多個 I2C 設(shè)備, 所以一個 i2c_adpater 也可以被多個 i2c_client 依附, i2c_adpater 中包括依附于它的 i2c_client 的鏈表 。

i2c_algorithm

struct i2c_algorithm{
    //i2c模式下,收發(fā)函數(shù)接口
     int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);
    //用于SMBUS模式下,收發(fā)函數(shù)接口
     int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,  unsigned short flags, char read_write,  u8 command, int size, union i2c_smbus_data *data);
    //用于檢查I2C主控制器所支持訪問接口,如I2C_FUNC_SMBUS_BYTE,查看是否支持smbus單字節(jié)讀取和寫操作
     u32 (*functionality) (struct i2c_adapter *);
}

該函數(shù)主要實(shí)現(xiàn)其I2C底層的操作

4.GC0328攝像頭I2C實(shí)例分析


對于攝像頭驅(qū)動程序,首先要知道如何讓攝像頭能夠正常工作。

第一步:攝像頭上電

在這一步的工作中,可以控制相關(guān)的GPIO進(jìn)行攝像頭使能,控制RESET及POWERON來讓攝像頭正常工作。

GC0328的上電時序如下圖所示:

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

第二步:給攝像頭提供時鐘

這一步也比較的關(guān)鍵,對于攝像頭來說,其時鐘就是心跳,如果要讓攝像頭正常的工作,則需要x1000的CIM提供24MHz的時鐘給攝像頭。

第三步:配置攝像頭的寄存器

對于一個攝像頭sensor,需要其輸出指定大小及指定格式的圖片,則需要配置攝像頭的寄存器。而配置攝像頭寄存器就是需要通過I2C來進(jìn)行配置。

第四步:配置CIM

x1000內(nèi)部的攝像頭接口控制模塊,可以將攝像頭數(shù)據(jù)進(jìn)行處理,可以進(jìn)行幀錯誤檢查以及數(shù)據(jù)的傳輸。這部分的控制需要那些CIM相關(guān)的寄存器來完成。

第五步:啟動CIM

配置及初始化完成后就可以啟動攝像頭了,CIM負(fù)責(zé)數(shù)據(jù)傳輸及產(chǎn)生相應(yīng)的中斷。

以上是攝像頭初始化的一個完整的過程,對于攝像頭初始化部分,I2C又是如何進(jìn)行初始化及設(shè)置的呢?這也是本文的重點(diǎn)。

根據(jù)前面的總線設(shè)備驅(qū)動的框架,有driver那么肯定會有device。這兩者的匹配靠的是.id_table

對于gc0308,具體可以通過kernel/arch/mips/xburst/soc-x1000/chip-x1000/halley2/common/i2c_bus.c

可以看到向I2C總線注冊的device的是gc0308

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

如果匹配上了,則調(diào)用driver的.probe函數(shù)。下面我們來看一下該函數(shù)具體做了什么事情。

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

在probe函數(shù)中,主要向v412_i2c_subdev提供了一個可操作的client,也就是相當(dāng)于I2C的操作函數(shù)的接口交給V4L2視頻驅(qū)動框架來進(jìn)行管理。向V4L2視頻驅(qū)動框架提供的函數(shù)如下:

第一個結(jié)構(gòu)體是有關(guān)視頻操作的接口,比如設(shè)備gc0328的輸出格式,得到當(dāng)前的視頻輸出格式等等

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

第二個結(jié)構(gòu)體是控制camera上電與斷電,以及控制白平衡,對焦的其他的參數(shù)

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

通過V4L2的I2C子設(shè)備控制來進(jìn)行設(shè)置。下面來基本分析一下其調(diào)用過程:

當(dāng)應(yīng)用程序通過ioctl傳遞VIDIO_S_FMT,是可以設(shè)置攝像頭輸出的格式

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

然后看一下寫寄存器的過程

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

調(diào)用了i2c_smbus_write_byte_data該函數(shù)在kernel\drivers\i2c\i2c-core.c,這樣就進(jìn)入了i2c總線操作函數(shù)中。

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

該函數(shù)會調(diào)用i2c_smbus_xfer

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

為什么不滿足條件,可以看注冊的i2c的平臺設(shè)備,在kernel\drivers\i2c\busses\i2c-v12-jz.c路徑下

有個i2c_algorithm的結(jié)構(gòu)體

struct i2c_algorithm{
    //i2c模式下,收發(fā)函數(shù)接口
     int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);
   //用于SMBUS模式下,收發(fā)函數(shù)接口
     int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,  unsigned short flags, char read_write,  u8 command, int size, union i2c_smbus_data *data);
    //用于檢查I2C主控制器所支持訪問接口,如I2C_FUNC_SMBUS_BYTE,查看是否支持smbus單字節(jié)讀取和寫操作
     u32 (*functionality) (struct i2c_adapter *);
}
怎么進(jìn)行Linux的I2C驅(qū)動框架分析

所以只會向下執(zhí)行,當(dāng)執(zhí)行到i2c_smbus_xfer_emulated ,會調(diào)用

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

該函數(shù)會調(diào)用

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

最后調(diào)用到kernel\drivers\i2c\busses\i2c-v12-jz.c的最底層的實(shí)現(xiàn)

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

在kernel\drivers\i2c\busses\i2c-v12-jz.c函數(shù)中

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

這個函數(shù)指向i2c_jz_xfer

在這個函數(shù)中,實(shí)現(xiàn)了I2C的讀寫,可以根據(jù)傳遞的flag進(jìn)行判斷是讀操作函數(shù)寫操作

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

最底層操作寄存器來實(shí)現(xiàn)其讀寫函數(shù)

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

到這里,一個I2C完整的傳輸流程就完成了。

5.總結(jié)


對于I2C完整的傳輸協(xié)議,最重要的是弄清楚總線驅(qū)動程序的框架,因?yàn)镮2C也是屬于總線框架。對于I2C總線設(shè)備框架的模型,可以用下圖來說明:

怎么進(jìn)行Linux的I2C驅(qū)動框架分析

也就是device與driver同時向i2c總線上注冊。當(dāng)注冊在總線上時,可以通過id_table進(jìn)行匹配,匹配上之后會調(diào)用driver的.probe函數(shù)。對于一般的I2C設(shè)備,可以在probe函數(shù)中注冊一個字符設(shè)備驅(qū)動,從而應(yīng)用層可以通過open函數(shù)打開/dev/i2c-0等設(shè)備節(jié)點(diǎn)。從而對I2C設(shè)備進(jìn)行讀寫操作。而攝像頭部分,直接將控制接口傳遞給V4L2進(jìn)行管理,這樣通過視頻設(shè)備驅(qū)動框架進(jìn)行攝像頭調(diào)節(jié),從而達(dá)到控制的目的。

上述內(nèi)容就是怎么進(jìn)行Linux的I2C驅(qū)動框架分析,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI