Linux I2C framework(1)_概述
作者:wowo 釋出于:2016-2-14 22:01
分類:通信類協定
1. 前言
I2C協定是嵌入式系統中廣泛使用的一類通信協定,主要用于CPU和各種外設之間的低速資料通信。Linux kernel使用I2C framework抽象、管理相應的資源,并以各種形式,向各類使用者提供API。另外,作為總線(bus)的一種,I2C framework的實作展現了linux裝置模型的精髓,值得研究與學習。這就是攥寫“Linux I2C framework”系列文章的緣由和目的。
按照分析各類framework的老規矩,蝸蝸會從4個角度分4篇文章介紹I2C framework: 1)Linux I2C framework的整體介紹,包括基礎知識、軟體架構、API彙整等。就是本文。
2)從Provider的角度,介紹怎麼借助I2C framework管理I2C相關的SOC資源。換句話說,就是怎麼編寫一個I2C driver。具體可參考“Linux I2C framework(2)_I2C provider”。
3)從Consumer的角度,介紹I2C framework為使用者提供了哪些功能、哪些API,以及怎樣利用I2C framework編寫程式。具體可參考“Linux I2C framework(3)_I2C consumer”。
4)從内部實作的角度,分析I2C framework的實作邏輯。具體可參考“Linux I2C framework(4)_I2C core”。
2. I2C的總線拓撲
I2C是總線的一種,其硬體拓撲如下圖所示:
圖檔1 I2C H/W topology
關于I2C的硬體拓撲,相信驅動工程師都很熟悉,這裡就不過多描述了,但有一點要強調: 我們都知道,I2C協定是主從式的,包括master(主裝置)和slave(從裝置),而Linux kernel的I2C framework隻抽象了I2C master有關的功能,換句話說,linux kernel有這樣的一個假設:
所有運作linux kernel的裝置,在I2C總線裡面,都是I2C master(至于I2C slave,抱歉,kernel不管!)。
正是基于這樣的假設,linux I2C framework才成為目前的樣子,具體可參考本文後續的描述。
linux kernel I2C framework使用如下的軟體拓撲抽象I2C硬體(我們可以一起領會一下其中的“裝置模型”思想):
圖檔2 I2C S/W topology 1)platform bus(/sys/bus/platform)是驅動工程師常見的bus,用于挂載和CPU通過系統總線連接配接的各類外設。在I2C framework中,I2C控制器直接從屬于platform bus,我們在linux kernel中常說的I2C driver,都是指I2C controller driver,都是以platform driver的形式存在,當然,對應的控制器是platform device。
2)與此同時,kernel抽象出I2C bus(/sys/bus/i2c),用于挂載和I2C controller通過I2C總線連接配接的各個I2C slave device。
3)比較特殊的地方是,I2C core使用一個虛拟實體----I2C adapter,抽象I2C controller有關的功能(主要是資料的收發),I2C adapter也挂載在I2C bus上。
4)I2C adapter和I2C slave device都挂載在I2C bus上,就可以友善的進行Master(I2C adapter)和Slave之間的比對操作,并通過I2C core提供的統一接口,通路I2C salve device,進行資料的收發。
5)以上各實體在sysfs中的位置,已經在“圖檔2”中通過紅色字型标注,大家可自行了解。
3. 軟體架構
基于第2章所述的總線拓撲,Linux kernel抽象出如下的軟體架構:
圖檔3 I2C framework software architecture 1)I2C framework的最終目标,是提供一種“通路I2C slave devices”的方法。由于這些slave devices由I2C controller控制,因而主要由I2C controller驅動實作這一目标。
2)經過I2C framework的抽象,consumer可以不用關心I2C總線的技術細節,隻需要通過簡單的API,就可以與slave devices進行資料互動。正常情況下,consumer是位于核心态的其它driver(如HDMI driver、touch screen driver等等)。與此同時,I2C framework也通過字元裝置向使用者空間提供類似的接口,使用者空間程式可以通過該接口通路slave devices。
3)在I2C framework内部,有I2C core、I2C busses、I2C algos和I2C muxes四個子產品。
4)I2C core使用I2C adapter和I2C algorithm兩個子子產品抽象I2C controller的功能,使用I2C client和I2C driver抽象I2C slave device的功能(對應裝置模型中的device和device driver)。另外,基于I2C協定,通過smbus子產品實作SMBus(System Management Bus,系統管理總線)的功能。
5)I2C busses是各個I2C controller drivers的集合,位于drivers/i2c/busses/目錄下,驅動工程師常說的“I2C driver”就是指它們。
6)I2C algos包含了一些通用的I2C algorithm,所謂的algorithm,是指I2C協定包的生成方法,進而組合成I2C的read/write指令,一般情況下,都是由硬體實作,不需要特别關注該目錄。
7)I2C muxes用于實作I2C bus的多路複用功能,屬于奇葩的冷門功能,暫不過多介紹。
4. I2C有關的軟體流程總結
TODO(會在後續文章完成之後再回來補充)。
原創文章,轉發請注明出處。蝸窩科技,www.wowotech.net。
評論:
x
2019-01-09 17:49
咨詢一下各位大神,Linux kernel 4.1.15,兩個程序A和B同時通路同一個SPI總線,會導緻這兩個程序退出嗎?同一個SPI總線 但是有主和從
是不是有可能A通路主SPI,B通路從SPI,然後B再請求主的,A再請求從的 兩邊都沒釋放,導緻的程序僵死了?
2019-01-10 19:26
@x:這和SPI driver的實作有關,當然,一個好的driver不會出現這種問題。
2016-03-28 19:31
I2C slave device driver和I2C client driver在核心代碼中有不同的含義,圖檔3中使用的術語似乎和核心不一緻
2016-03-28 21:58
@hello_world:kernel中有“I2C slave device driver”這個概念嗎?這篇文章中我有意回避了I2C client這個概念,因為覺得它不直覺,不好了解。從本質上來說,I2C client應該是I2C slave device在本地的一個“映像”(這讓我想起了bluez中device的概念)。
2016-03-29 09:01
@wowo:對的i2c client driver其實是驅動I2C 總線上的slave裝置的,是以其實i2c slave driver更順一些,但是,核心代碼其實都是用i2c client的概念。是以,我覺得圖檔3應該表述這一部分的内容的:即i2c client driver子產品應該和i2c slave HW block之間有虛線,表示這兩個子產品之間的關系。BTW,我覺的圖檔3應該可以有更好的表達。
即便是有了I2C slave device的支援(類似USB 的gadget driver),實際上仍然用struct i2c_client來抽象這個slave裝置。
最後:我們覺得我們還是鎖定一個核心版本好了,我建議是4.4.y的核心版本,大家都圍繞這個版本讨論。
2016-03-28 19:19
探讨一個問題啊,我說的也不一定對。
我感覺I2C algos和I2C buses子產品的關系不是平行關系,毫無疑問,I2C buses子產品(I2C controller driver)子產品是和底層硬體相關的,所有和具體的I2C controller的互動都是通過I2C busses子產品進行,I2C algos是和硬體無關的(也不能這麼說,應該說是和硬體操作序列有關)。I2C algos對底層硬體的操作都是通過I2C busses中的adapter的callback完成的,或者說,adapter提供了最底層的通信機制,不同的algos可以利用它實作具體的I2C的資料傳輸服務。
2016-03-28 21:52
@hello_world:這個還真不一定,我覺得kernel的設計初衷,是盡可能的複用I2C algos,也就是說,将adapter和algos分離。當然,現狀是,adapter和algos基本上一一對應了,因而algos似乎變成adapter的一個屬性(從屬關系)了。
2016-03-29 09:04
@wowo:的确,algos像是adapter的一個lib,不過反正在嵌入式的場景中,每一個adapter都有自己獨特的algos,我們沒有必要争論它們之間的關系,algos,就讓它随風飄散吧,^_^
2016-03-28 18:54
所有運作linux kernel的裝置,在I2C總線裡面,都是I2C master(至于I2C slave,抱歉,kernel不管!)。
------------------------------------------
為什麼不管呢?其實隻要有需求,就應該提供支援的。在4.4.6的核心中,已經增加了對I2C slave的支援,同時也複用了目前的I2C framework的代碼。
另外,I2C實體拓撲(圖檔1)以及關于I2C和裝置模型那部分(圖檔2),基本上四着眼于嵌入式平台,其實可以更通用一些。另外,圖檔2中的CPU block的出現容易誤導的,或者建議增加更多的文字描述,對于I2C和裝置模型之間的關系可以多寫一些。
2016-03-28 21:47
@hello_world:4.4.6是3/16才釋出啊,我還沒看呢!已經支援I2C slave了嗎?看來kernel還是妥協了。其實我覺得,一個跑linux kernel的裝置,當做I2C slave的可能性不大,還真不需要管它。
通用一些具體指什麼意思呢?加入slave?還是其它?
2016-03-29 08:50
@wowo:具體是哪一個版本加上的我沒有查證,不過這不重要,重要的是開源社群增加i2c slave的支援也是很糾結的(就像你說的,其實大部分的運作linux的裝置應該都是I2C master),在log中有這樣的描述:最終,我們還是增加了slave的支援......
增加slave的支援是指其他的子產品可以調用i2c core提供的i2c_slave_register/i2c_slave_unregister來注冊一個或者登出一個i2c的slave裝置。一旦注冊了slave裝置,底層的adapter要切換到slave mode。完成這些操作之後,該i2c slave裝置可以響應來自對端i2c master裝置的各種指令和資料了。
2016-03-04 22:05
确實i2c是一個比較清晰的framework,記得第一個接觸的驅動就是i2c slave,清晰的記得當時的迷茫,對各種資料結構的不解,現在看來感覺清楚了不少。
2016-03-05 17:55
@electrlife:是啊,I2C相對比較簡單,不用當做了解裝置模型的一個例子,也挺不錯的。
Jordon Wu
2016-02-19 15:05
@wowo,
請教下,對于I2C,可以在userspace的application裡進行中斷嗎?謝謝
2016-02-19 15:34
@Jordon Wu:我不太明白您的意思,對I2C來說,它負責資料接收,中斷是在Kernel處理的。
我們講的在使用者空間通路,隻是應用程式通過I2C Framework提供的字元裝置接口,通路I2C slave device(資料收發)而已,應該不需要關心中斷。
2016-02-19 16:52
@wowo:@wowo,
是的,是在應用程式中通過字元裝置接口open/read/write資料到slave device,這樣做發資料沒問題,但是收資料需要while循環去讀或者poll去查詢是否有資料可讀。我想知道有沒有辦法把kernel的有資料可接受這個中斷暴露給userspace的應用程式?這樣應用程式隻在這個中斷來了之後才去度slave device的資料。
雲
2016-02-19 17:06
@jordonwu:我大概了解的你的想法。
1.首先中斷隻能在kenerl空間處理,這個是必須的。如果想實作此類模型,一個途徑是應用程式調用read/write,在kernel空間中用諸如wait_even_xx()陷入睡眠,當有中斷來臨時,在ISR中wake_up_xx()來喚醒之前陷入睡眠的程序。
2.i2c的bus驅動已經實作了上述模型,你可以參考drivers/i2c/busess/下的各種driver。也就是說,在應用程式中位元組裝置接口的read/write/ioctl都是同步的。
2016-02-19 17:13
@jordonwu:建議不這樣做,poll已經夠用了,如果poll解決不了,估計是應用層的設計有待商榷。
雲
2016-02-15 10:26
Linux下的i2c framework還是比較直覺的。。不像usb mmc那樣“蕩氣回腸” ;)
這篇比較概括淺顯,期待後續
情人節還在發文章,wowo你可以啊,不擔心跪鍵盤?哈哈
2016-02-15 13:09
@雲:是的,I2C Framework還是比較清晰易懂的。
哈哈,感情好的話哪天都是節,不怕不怕~~~
發表評論:
昵稱
郵件位址 (選填)
個人首頁 (選填)