www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > 嵌入式IoT

1.基本概念

總線

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

設(shè)備

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

驅(qū)動(dòng)

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

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

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

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

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


2.I2C傳輸協(xié)議



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

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

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

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

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

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

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

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

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

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


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



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

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

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

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

比較重要的文件

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

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

kernel\drivers\i2c\i2c-dev.c

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

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

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

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

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

i2c_driver

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

i2c_client

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

i2c_adpater

用來匹配i2c_driver與i2c_client。即 i2c_client 依附于 i2c_adpater。由于一個(gè)適配器上可以連接多個(gè) I2C 設(shè)備, 所以一個(gè) i2c_adpater 也可以被多個(gè) 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í)例分析



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

第一步:攝像頭上電

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

GC0328的上電時(shí)序如下圖所示:

第二步:給攝像頭提供時(shí)鐘

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

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

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

第四步:配置CIM

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

第五步:?jiǎn)?dòng)CIM

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

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

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

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

可以看到向I2C總線注冊(cè)的device的是gc0308

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

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

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

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

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

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

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

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

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

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

有個(gè)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 *);
}

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

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

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

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

這個(gè)函數(shù)指向i2c_jz_xfer

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

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

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


5.總結(jié)



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

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


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉