新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

作者: 時間:2014-01-22 來源:網(wǎng)絡(luò) 收藏

  i2c_dev 里面定義了讀寫I2C 設(shè)備應(yīng)用層的讀寫接口,但由于其缺少通用性,一般很少用到所以并不做詳細的介紹。

  i2c_core在驅(qū)動框架中起到了承上啟下的作用,里面定義了許多重要的函數(shù)。例如:adapter注冊/注銷函數(shù),增加/刪除設(shè)備驅(qū)動函數(shù),增加/刪除的函數(shù),I2C傳輸,發(fā)送和接收函數(shù)。這些函數(shù)都是在編寫中必須要用到的接口函數(shù),正是由于這些通用的接口函數(shù)才使得代碼具有很強的可移植性和重用性。

  3 編寫驅(qū)動的思路

  在了解中I2C設(shè)備驅(qū)動的基本框架后,要編寫自己的設(shè)備驅(qū)動首先要弄清楚的一個問題是到底內(nèi)核已經(jīng)實現(xiàn)了那部分,需要實現(xiàn)的又是那部分。因為I2C設(shè)備驅(qū)動是基于總線設(shè)備驅(qū)動模型的,一般而言在移植操作系統(tǒng)中,內(nèi)核已經(jīng)對總線部分已經(jīng)有了很好的實現(xiàn),所以總線部分的驅(qū)動一般可以不必關(guān)心。

  在此需要實現(xiàn)的是設(shè)備層的i2c_driver與i2c_client結(jié)構(gòu)體,并利用I2C 子系統(tǒng)提供的接口函數(shù)掛接到I2C 總線上。

  每一個I2C設(shè)備驅(qū)動,必須首先創(chuàng)造一個i2c_driver結(jié)構(gòu)體對象,該結(jié)構(gòu)體包含了I2C設(shè)備探測和注銷的一些基本方法和信息。其中包括設(shè)備驅(qū)動的名字,適配器的掛接/取消函數(shù)指針等。一個例子如下所示,name字段標識本驅(qū)動的名稱(不要超過31 個字符),at-tach_adapter和detach_client字段為函數(shù)指針,這兩個函數(shù)在I2C設(shè)備注冊的時候會自動調(diào)用,需要自己實現(xiàn)這兩個函數(shù)。

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

  上面定義的i2c_driver對象,抽象為一個I2C的驅(qū)動模型,提供對I2C設(shè)備的探測和注銷方法,接下來就是要定義i2c_client 結(jié)構(gòu)體,其代表著一個具體的I2C 設(shè)備,該結(jié)構(gòu)體有一個data指針,可以指向任何私有的設(shè)備數(shù)據(jù),在復(fù)雜點的驅(qū)動中可能會用到。

  每一個I2C設(shè)備芯片,都通過硬件連接設(shè)定好了該設(shè)備的I2C設(shè)備地址。因此,I2C設(shè)備的探測一般是靠設(shè)備地址來完成的。那么,首先要在驅(qū)動代碼中聲明你要探測的I2C設(shè)備地址列表以及一個宏,示例如下:

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

  有了i2c_client結(jié)構(gòu)體代表了具體的設(shè)備和設(shè)備ID后就可以實現(xiàn)attach_adapter 和detach_client 函數(shù)。這兩個函數(shù)是系統(tǒng)自動調(diào)用的,它的實現(xiàn)是有一定的框架的,可以在linux內(nèi)核源碼的驅(qū)動例子中找到,由于代碼過長這里不做具體的分析。針對不同的設(shè)備函數(shù)的實現(xiàn)會略有不同,一般attach_adapte需要完成的工作是對i2c_client結(jié)構(gòu)體成員賦值和調(diào)用接口函i2c_attach_cli-ent把設(shè)備掛接到適配其中。而detach_client 函數(shù)則是完成相反的工作。

  最后的一步是編寫模塊的初始化與退出函數(shù)把驅(qū)動加進I2C驅(qū)動子系統(tǒng)中,示例可以是:

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

  至此,I2C設(shè)備的驅(qū)動已經(jīng)完成了,但是到了這一步本驅(qū)動并沒有實際的用處,它僅僅提供的是一個設(shè)備的管理框架,所以必須還要進行兩方面的補充。

  第一方面是,利用I2C總線讀寫外部芯片的控制/狀態(tài)寄存器;第二方面是,向應(yīng)用層提供I2C設(shè)備的讀寫接口,令應(yīng)用程序可以對設(shè)備節(jié)點的讀寫實現(xiàn)對I2C具體物理設(shè)備的讀寫。為了實現(xiàn)I2C 設(shè)備寄存器的讀寫操作,必須要用到Linux的I2C子系統(tǒng)提供的讀寫接口函數(shù):

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

  利用這兩個函數(shù)根據(jù)芯片的讀寫時序進行封裝,就可以讀寫芯片內(nèi)部的寄存器,以寫芯片寄存器為例,必須寫往總線上寫寄存器的地址,然后寫入要往寄存器里寫入的數(shù)據(jù),示例代碼如下所示。讀寄存器的時序則是則是先寫入要讀寄存器的地址,然后接受總線上的數(shù)據(jù),區(qū)別不大,不做示例。

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

  要想向應(yīng)用層提供讀寫接口,則必須再對I2C設(shè)備驅(qū)動進行一次簡單字符設(shè)備驅(qū)動的封裝,將I2C設(shè)備作為一個簡單字符設(shè)備,依次實現(xiàn)字符設(shè)備文件操作函數(shù)結(jié)構(gòu)體file_operation 里面的函數(shù)指針所對應(yīng)的接口函數(shù),這里只給出了大體的框架,具體的實現(xiàn)對于不同的芯片有很大的不同。

  定義一個字符設(shè)備結(jié)構(gòu)體cdev,將I2C 設(shè)備當做一個普通的字符設(shè)備處理。

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

  定義一個文件操作函數(shù)結(jié)構(gòu)體,填寫里面函數(shù)指針,指出設(shè)備操作所對應(yīng)的具體函數(shù),一般的例子是:

嵌入式Linux下的I2C設(shè)備驅(qū)動程序設(shè)計

  接著就是編寫file_operations所對應(yīng)的具體函數(shù)。

  最后一步是在模塊的初始化和退出函數(shù)中增加對簡單字符設(shè)備的注冊和注銷操作,包括設(shè)備號申請與注銷,設(shè)備注冊與注銷兩方面。

  至此,將編譯好的模塊加載進內(nèi)核后就可以在用戶空間利用文件系統(tǒng)的API對設(shè)備文件進行各種操作。

  4 結(jié)語

  I2C總線在電子系統(tǒng)設(shè)計中是十分普遍的一種接口技術(shù),而Linux又是十分流行的操作系統(tǒng)。編寫Linux下I2C總線設(shè)備的驅(qū)動開發(fā)中十分重要的一項技術(shù),不容忽視。本文首先講述了Linux系統(tǒng)I2C設(shè)備驅(qū)動程序的總體框架,然后給出了編寫I2C設(shè)備驅(qū)動的總體思路與框架,希望給讀者理清思路,加深對編寫I2C設(shè)備驅(qū)動的理解??偠灾?,利用I2C總線通信可以達到很高的速率,而且總線上可以掛接多個節(jié)點,每個節(jié)點都由惟一的地址確定。

linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

上一頁 1 2 下一頁

評論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉