999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

嵌入式Linux的I2C設備驅動程序的分析

2013-04-12 00:00:00余熾業宋躍雷瑞庭
現代電子技術 2013年16期

摘 要: I2C總線是飛利浦公司推出的一種串行總線技術,由于其簡單易用性,已經被廣泛地應用于電子系統設計的許多芯片當中。利用I2C總線通信可以達到很高的速率,而且總線上可以掛接多個節點,每個節點都由惟一的地址確定。在此主要講述了嵌入式Linux中I2C總線設備驅動程序的結構,并給出了Linux下基于I2C總線設備驅動的編寫思路。

關鍵詞: 嵌入式Linux; I2C設備; I2C總線; 設備驅動程序

中圖分類號: TN919?34 文獻標識碼: A 文章編號: 1004?373X(2013)16?0038?03

0 引 言

由于I2C總線的通用性,Linux作為一款優秀的嵌入式操作系統[1?2],也必須要對其要有很好的支持。在Linux內核源碼中對I2C總線的驅動[3?4]是基于總線設備驅動模型的,其驅動程序用到了特殊的幾個數據結構,對I2C總線協議進行了更抽象更通用的定義,極大的增加了設備驅動的可移植性。要寫編寫出自己的I2C設備驅動程序,必須對這種內核I2C總線驅動的架構有深刻的理解。

1 I2C總線的硬件構成

I2C總線協議只有兩條總線線路,一條是串行數據線(SDA),一條是串行時鐘線(SCL)。SDA負責數據的傳輸,SCL負責數據傳輸的時鐘同步。I2C設備通過這兩條總線連接到處理器的I2C總線控制器[5?6]上,不同設備之間通過7位地址來區別,而且數據的傳輸是雙向的,方向的確定由1位二進制數確定,地址位加方向位是操作I2C設備的惟一標示,I2C設備與CPU的連接如圖1所示。

I2C總線上有3種類型的信號,分別是:開始信號,結束信號和應答信號。這些信號都是由SDA和SCL上的電平變化來表示的。

開始信號(S):當SCL為高電平時,SDA由高電平向低電平跳變,表示開始傳輸數據。

結束信號(P):當SCL為高電平時,SDAY由低電平向高電平跳變,表示結束傳輸數據。

相應信號(ACK):從機接收到8位數據后,在第9個時鐘周期,拉低SDA電平,表示已經接收到數據。

當總線空閑時,SDA和SCL都處于高電平,主機檢測到總線空閑就可以向從機發送數據。主機首先發送開始信號S,接著發出8位數據(包括前7位的從機地址和1為的方向位),然后等待從機發回確認信號ACK。當第8位為0時,表示向從機傳輸數據,主機收到確認信號后就可以連續的向從機寫入8位數據;當第8位為1時,表示向從讀取數據,這時主機就可以接收來自從機的一系列數據。最后當總個數據傳輸過程完成后,由主機發送結束信號P,表示本次的數據傳輸完成。

2 Linux的I2C設備驅動程序的層次結構

因為I2C設備的種類繁多,如果為每一款I2C設備都編寫一個驅動程序,顯然不太現實也不太可能做到。所以,Linux中是對I2C設備驅動采取了層次化處理,分為總線層和設備層。將I2C設備驅動的一些共同屬性抽象起來歸結起來作為總線層,而將具體I2C設備特殊操作作為設備層。在Linux中I2C設備驅動中用到的數據結構[4,7?8]的關系如圖2所示。關于這部分代碼位于Linux內核源碼樹的/driver/i2c中。

理解這層次結構重點是要理解4個數據結構,分別是屬于設備層的i2c_driver與i2c_client,屬于總線層的i2c_adapter與i2c_algorithm。下面分別對這四個數據結構做簡要的說明。

struct i2c_driver:具體的每一個I2C設備都應該對應著的一個驅動,這個結構體里面定義了Linux設備模型中用于I2C總線管理的一系列函數指針和I2C設備的信息。其中最重要的兩個成員是適配器檢測函數指針attach_adapter,和設備ID表id_table。

struct i2c_client:一個連接在SDA和SCL總線上的具體設備是由i2c_client結構體描述的,定義了兩個成員變量表示這個具體設備所對應的適配器和驅動。

struct i2c_adapter:此結構體表示CPU里面具體的I2C控制器,本質上也是對應著一個物理設備,其中最要的成員變量是指向適配器驅動的程序的algo結構體指針。

struct i2c_algorithm:里面定義了具體適配器驅動程序的函數指針。特別是master_xfer函數指針,這個函數實現了適配器最底層的操作方法,也是I2C設備驅動中總線層里面要編寫的重要函數。

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

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

3 編寫I2C設備驅動的思路

在了解Linux中I2C設備驅動的基本框架后,要編寫自己的設備驅動首先要弄清楚的一個問題是到底內核已經實現了那部分,需要實現的又是那部分。因為I2C設備驅動是基于總線設備驅動模型的,一般而言在移植Linux操作系統中,Linux內核已經對總線部分已經有了很好的實現,所以總線部分的驅動一般可以不必關心。在此需要實現的是設備層的i2c_driver與i2c_client結構體,并利用I2C子系統提供的接口函數掛接到I2C總線上。

每一個I2C設備驅動,必須首先創造一個i2c_driver結構體對象[8?9],該結構體包含了I2C設備探測和注銷的一些基本方法和信息。其中包括設備驅動的名字,適配器的掛接/取消函數指針等。一個例子如下所示,name字段標識本驅動的名稱(不要超過31個字符),attach_adapter和detach_client字段為函數指針,這兩個函數在I2C設備注冊的時候會自動調用,需要自己實現這兩個函數。

static struct i2c_driver xxx_i2c_driver = {

.driver = {

.name = \"xxx_i2c_driver\",

},

.attach_adapter = xxx_attach_adapter,

.detach_client = xxx_detach_client,

.command = NULL,

};

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

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

static unsigned short normal_i2c[] = {

0xbc >> 1, //設備節點的地址

I2C_CLIENT_END };

I2C_CLIENT_INSMOD;

有了i2c_client結構體代表了具體的設備和設備ID后就可以實現attach_adapter和detach_client 函數。這兩個函數是系統自動調用的,它的實現是有一定的框架的,可以在linux內核源碼的驅動例子中找到,由于代碼過長這里不做具體的分析。針對不同的設備函數的實現會略有不同,一般attach_adapte需要完成的工作是對i2c_client結構體成員賦值和調用接口函i2c_attach_client把設備掛接到適配其中。而detach_client 函數則是完成相反的工作。

最后的一步是編寫模塊的初始化與退出函數把驅動加進I2C驅動子系統中,示例可以是:

static int __init xxx_i2c_init(void) {

return i2c_add_driver(xxx_i2c_driver); }

static void __exit xxx_i2c_exit(void) {

i2c_del_driver(xxx_i2c_driver); }

至此,I2C設備的驅動已經完成了,但是到了這一步本驅動并沒有實際的用處,它僅僅提供的是一個設備驅動程序的管理框架,所以必須還要進行兩方面的補充。第一方面是,利用I2C總線讀寫外部芯片的控制/狀態寄存器;第二方面是,向應用層提供I2C設備的讀寫接口,令應用程序可以對設備節點的讀寫實現對I2C具體物理設備的讀寫[10]。為了實現I2C設備寄存器的讀寫操作,必須要用到Linux的I2C子系統提供的讀寫接口函數:

extern int i2c_master_send(struct i2c_client *,const char* ,int); //從I2C總線發數據

extern int i2c_master_recv(struct i2c_client *,char* ,int); //從I2C總線收數據

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

static int tvp5158_i2c_write( struct i2c_client* client,uint8_t reg,uint8_t data) {

unsigned char buffer[2];

buffer[0] = reg;

buffer[1] = data;

if( 2!= i2c_master_send(client,buffer,2) ) { //錯誤處理

printk( KERN_ERR \" tvp5158_i2c_write fail! \n\" );

return-1; }

return 0;

}

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

定義一個字符設備結構體cdev,將I2C設備當做一個普通的字符設備處理

struct xxx_i2c_device{

struct cdev cdev;

//設備其他的數據部分};

定義一個文件操作函數結構體,填寫里面函數指針,指出設備操作所對應的具體函數,一般的例子是:

struct file_operations xxx_dev_fileops = {

.owner = THIS_MODULE,

.open = xxx_devOpen,

.release = xxx_devRelease,

.ioctl = xxx_devIoctl, };

接著就是編寫file_operations所對應的具體函數。

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

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

4 結 語

I2C總線在電子系統設計中是十分普遍的一種接口技術,而Linux又是十分流行的嵌入式操作系統。編寫嵌入式Linux下I2C總線設備的驅動驅動程序是嵌入式開發中十分重要的一項技術,不容忽視。本文首先講述了Linux系統I2C設備驅動程序的總體框架,然后給出了編寫I2C設備驅動的總體思路與框架,其中包括設備驅動,訪問I2C設備寄存器,和向應用層提供訪問接口三方面。希望給讀者理清思路,加深對編寫I2C設備驅動的理解。

參考文獻

[1] 李樺,高飛,孫磊.嵌入式Linux設備驅動程序研究[J].微計算機信息,2010(14):68?70.

[2] 錢晨,徐榮華,王欽若.基于Linux操作系統的設備驅動程序開發[J].微計算機信息,2004(9):131?133.

[3] Philips Corporation. I2C bus specification, version 2.1 [R]. Netherland: Philips Corporation, 2000.

[4] Samsung Electronics. S3C2410A 200 MHz 266 MHz 32?bit RISC microprocessor user’s manual, revision 1.0 [R]. South Korea: Samsung Electronics, 2004.

[5] 王瑩.Linux下基于I2C總線的CAT1025設備驅動實現[J].棗莊學院學報,2011(2):87?91.

[6] 董志國,李式巨.嵌入式Linux設備驅動程序開發[J].計算機工程與設計,2006(10):3737?3740.

[7] 葉順流.基于ARM的嵌入式Linux研究與實現[D].重慶:重慶大學,2005.

[8] 江澤濤,吳俊安.用Kylix實現Linux環境下的串行通信[J].計算機應用研究,2005,22(9):214?216.

[9] 鄭燕飛,余海燕.Linux的多線程機制探討與實踐[J].計算機應用,2001,21(1):81?83.

[10] BRUCE J W. Personal digital assistant(PDA)based I2C bus analysis [J]. IEEE Transactions on Consumer Electronics, 2003, 49: 1482?1487.

主站蜘蛛池模板: 日韩美一区二区| 丁香婷婷综合激情| 国产极品美女在线播放| 亚洲一级毛片| 国产精品嫩草影院av| 久久久无码人妻精品无码| 亚洲日韩久久综合中文字幕| 久久综合成人| 国产精品亚洲五月天高清| 中文字幕在线欧美| 欧美精品亚洲精品日韩专区va| 制服丝袜一区| av一区二区无码在线| 91免费国产在线观看尤物| 91美女视频在线| 97综合久久| 国产日韩欧美在线播放| 色噜噜在线观看| 精品国产亚洲人成在线| 亚洲午夜天堂| 一级爆乳无码av| 直接黄91麻豆网站| 98超碰在线观看| 成人免费一级片| 91亚瑟视频| 波多野结衣久久高清免费| 亚洲床戏一区| 97在线公开视频| www.亚洲国产| 亚洲伊人久久精品影院| 国产精品久久精品| 色久综合在线| 国产成人综合日韩精品无码不卡 | 在线中文字幕日韩| 国产亚洲精品97AA片在线播放| 超清无码一区二区三区| 自偷自拍三级全三级视频| 欧美一区二区精品久久久| 国产乱人伦AV在线A| 日韩a级毛片| 在线一级毛片| 国产日韩欧美一区二区三区在线| 宅男噜噜噜66国产在线观看| 一区二区三区在线不卡免费 | 无码精品国产VA在线观看DVD | 国产自产视频一区二区三区| 欧美精品啪啪| 国产AV无码专区亚洲精品网站| 亚洲精品第一在线观看视频| 亚洲视频免| 亚洲综合精品香蕉久久网| 亚洲最新在线| 日韩最新中文字幕| 欧美激情第一区| 午夜精品一区二区蜜桃| 97国产成人无码精品久久久| 久久精品人人做人人爽电影蜜月| 亚洲欧州色色免费AV| 欧美激情,国产精品| 9999在线视频| 亚洲天堂网在线播放| 国产精品区网红主播在线观看| 免费在线国产一区二区三区精品| 亚欧成人无码AV在线播放| 日韩一区精品视频一区二区| 五月激激激综合网色播免费| 日韩精品亚洲精品第一页| h网址在线观看| 欧美一级高清片久久99| 成年人国产网站| 国产一级小视频| 国产男人天堂| 奇米影视狠狠精品7777| 亚洲综合日韩精品| 91久草视频| 亚洲水蜜桃久久综合网站| 18禁影院亚洲专区| 久久成人国产精品免费软件| 国产一区在线观看无码| 日本欧美中文字幕精品亚洲| 亚洲一区二区三区在线视频| h视频在线播放|