《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 嵌入式技術(shù) > 設(shè)計(jì)應(yīng)用 > ARM-Linux中I2C總線驅(qū)動(dòng)開(kāi)發(fā)
ARM-Linux中I2C總線驅(qū)動(dòng)開(kāi)發(fā)
來(lái)源:微型機(jī)與應(yīng)用2012年第5期
高非非,,劉辛國(guó)
(北京建筑工程學(xué)院 電氣與信息工程學(xué)院,, 北京 100044)
摘要: 針對(duì)I2C總線的特點(diǎn),,Linux內(nèi)核中定義了I2C驅(qū)動(dòng)體系結(jié)構(gòu),。在分析Linux的I2C總線驅(qū)動(dòng)體系結(jié)構(gòu)基礎(chǔ)上,,介紹了在S3C2410中設(shè)計(jì)I2C總線驅(qū)動(dòng)的方法,。
Abstract:
Key words :

摘  要: 針對(duì)I2C總線的特點(diǎn),,Linux內(nèi)核中定義了I2C驅(qū)動(dòng)體系結(jié)構(gòu),。在分析Linux的I2C總線驅(qū)動(dòng)體系結(jié)構(gòu)基礎(chǔ)上,,介紹了在S3C2410中設(shè)計(jì)I2C總線驅(qū)動(dòng)的方法。
關(guān)鍵詞: ARM-Linux,;I2C體系結(jié)構(gòu),;I2C總線驅(qū)動(dòng)程序

 I2C總線是一種串行數(shù)據(jù)傳輸標(biāo)準(zhǔn)總線,,使用數(shù)據(jù)線SDA和時(shí)鐘線SCL就可實(shí)現(xiàn)設(shè)備間的數(shù)據(jù)交互,它使得電路系統(tǒng)結(jié)構(gòu)設(shè)計(jì)簡(jiǎn)單,,具有使用方便,、通信速率高等優(yōu)點(diǎn)。因此,,在嵌入式系統(tǒng)中,,I2C總線被廣泛地應(yīng)用在與RAM、EEPROM,、RTC等設(shè)備間的接口電路中,。近年來(lái),隨著嵌入式系統(tǒng)應(yīng)用不斷升溫,,Linux憑借源碼開(kāi)放,、內(nèi)核穩(wěn)定以及可裁剪性強(qiáng)等優(yōu)點(diǎn)成為在通信、工業(yè)控制,、消費(fèi)電子等領(lǐng)域的主流操作系統(tǒng),。而Linux設(shè)備驅(qū)動(dòng)程序是所有Linux應(yīng)用系統(tǒng)中不可或缺的組成部分,是現(xiàn)在Linux開(kāi)發(fā)中的熱門領(lǐng)域,。Linux內(nèi)核已經(jīng)把I2C總線協(xié)議定義為內(nèi)核驅(qū)動(dòng)的一部分,,并形成了一種體系結(jié)構(gòu)。本文正是在研究I2C總線驅(qū)動(dòng)體系結(jié)構(gòu)基礎(chǔ)上,,提出了其在S3C2410中實(shí)現(xiàn)的基本方法,。
1 I2C總線
 I2C總線是由雙向數(shù)據(jù)傳輸線SDA和時(shí)鐘線SCL構(gòu)成的二線制串行總線,可構(gòu)成主從和多主系統(tǒng),。I2C總線多采用主從雙向通信,,即總線上在某一時(shí)刻只有一個(gè)主設(shè)備,總線上的其他設(shè)備都作為從設(shè)備,。任何能夠進(jìn)行發(fā)送和接收的設(shè)備都可以成為主設(shè)備,,但是在同一時(shí)間內(nèi)只能有一個(gè)設(shè)備作為主設(shè)備(通常為微控制器),其他每個(gè)I2C器件作為從設(shè)備與主設(shè)備進(jìn)行通信,,它們都有唯一的地址用來(lái)識(shí)別,。
I2C總線的時(shí)序圖[1]如圖1所示。


 從圖1可以看到,,I2C總線在傳送數(shù)據(jù)過(guò)程中使用了三種信號(hào)[2],。(1)開(kāi)始信號(hào):SCL為高電平時(shí),SDA由高電平向低電平跳變,,表示將要開(kāi)始傳送數(shù)據(jù),;(2)應(yīng)答信號(hào):從設(shè)備在接收到1 B數(shù)據(jù)后,向主設(shè)備發(fā)出一個(gè)低電平脈沖應(yīng)答信號(hào),,表示已收到數(shù)據(jù),,主設(shè)備根據(jù)從設(shè)備的應(yīng)答信號(hào)做出是否繼續(xù)傳輸數(shù)據(jù)的操作(I2C總線每次數(shù)據(jù)傳輸時(shí)字節(jié)數(shù)不限制,,但是每發(fā)送1 B都要有一個(gè)應(yīng)答信號(hào));(3)結(jié)束信號(hào):SCL為低電平時(shí),,SDA由低電平向高電平跳變,,表示數(shù)據(jù)傳送結(jié)束。
I2C總線具體的通信工作原理如下:主設(shè)備首先發(fā)出開(kāi)始信號(hào),,接著發(fā)送1 B的數(shù)據(jù),,其由高7 bit地址碼和最低1 bit方向位組成(方向位表明主設(shè)備與從設(shè)備間數(shù)據(jù)的傳送方向)。系統(tǒng)中所有從設(shè)備將自己的地址與主設(shè)備發(fā)送到總線上的地址進(jìn)行比較,,如果從設(shè)備地址與總線上的地址相同,,該設(shè)備就是與主設(shè)備進(jìn)行數(shù)據(jù)傳輸?shù)脑O(shè)備。接著進(jìn)行數(shù)據(jù)傳輸,,根據(jù)方向位,,主設(shè)備接收從設(shè)備數(shù)據(jù)或發(fā)送數(shù)據(jù)到從設(shè)備。當(dāng)數(shù)據(jù)傳送完成后,,主設(shè)備發(fā)出一個(gè)停止信號(hào),,釋放I2C總線,然后所有從設(shè)備等待下一個(gè)開(kāi)始信號(hào)的到來(lái),。
2 系統(tǒng)硬件設(shè)計(jì)
2.1 Linux驅(qū)動(dòng)程序

 設(shè)備驅(qū)動(dòng)程序是Linux內(nèi)核的重要組成部分,是操作系統(tǒng)內(nèi)核與底層硬件之間的接口,。在ARM系統(tǒng)中,,每個(gè)物理設(shè)備都有自己的控制器,每個(gè)硬件控制器都有自己的控制狀態(tài)寄存器(CSR),,并且各不相同,。這些寄存器用來(lái)啟動(dòng)、停止,、初始化設(shè)備,,并對(duì)設(shè)備進(jìn)行診斷,對(duì)硬件的控制主要是針對(duì)這些寄存器進(jìn)行操作,。設(shè)備驅(qū)動(dòng)程序?yàn)閼?yīng)用程序屏蔽了硬件的底層細(xì)節(jié),,這樣在應(yīng)用程序看來(lái),硬件設(shè)備只是一個(gè)文件,,應(yīng)用程序通過(guò)對(duì)應(yīng)的設(shè)備驅(qū)動(dòng)程序中定義的通信接口(write,、read和ioctl等)像操作普通文件一樣實(shí)現(xiàn)對(duì)硬件設(shè)備的操作,簡(jiǎn)化了對(duì)設(shè)備的訪問(wèn),,使得應(yīng)用程序的編寫相對(duì)簡(jiǎn)單,。
設(shè)備驅(qū)動(dòng)程序一般有以下功能[3]:對(duì)硬件設(shè)備的初始化、加載和釋放,;對(duì)設(shè)備進(jìn)行管理,,包括實(shí)時(shí)參數(shù)設(shè)置以及提供對(duì)設(shè)備的統(tǒng)一操作接口,;讀取應(yīng)用程序傳遞給設(shè)備文件的數(shù)據(jù)或回送應(yīng)用程序請(qǐng)求的數(shù)據(jù);檢測(cè)或處理設(shè)備出現(xiàn)的錯(cuò)誤等,。
 Linux內(nèi)核將打開(kāi),、關(guān)閉、讀/寫和ioctl等所有相關(guān)操作封裝在一個(gè)結(jié)構(gòu)體file_operations中,,設(shè)備驅(qū)動(dòng)程序利用結(jié)構(gòu)體file_operations與文件系統(tǒng)聯(lián)系起來(lái),。另外還要使用module_init()和module_exit()兩個(gè)宏。module_init()的本質(zhì)是在.initcall.init段使用空間中定義的一個(gè)指向初始化函數(shù)的指針,。設(shè)備驅(qū)動(dòng)程序通過(guò)調(diào)用代碼段中設(shè)備初始化函數(shù),,完成初始化硬件和向內(nèi)核注冊(cè)設(shè)備驅(qū)動(dòng)程序。module_exit()功能與module_init()相反,。
2.2 I2C總線驅(qū)動(dòng)體系結(jié)構(gòu)
 直接數(shù)字頻率合成器(DDS)是一種產(chǎn)生模擬波形的方法,,其通常是通過(guò)數(shù)字形式的時(shí)間轉(zhuǎn)換信號(hào)再執(zhí)行數(shù)模轉(zhuǎn)換產(chǎn)生正弦波。因?yàn)镈DS設(shè)備的運(yùn)行基于數(shù)字,,所以能夠在輸出頻率,、正弦波頻率分解和運(yùn)行于寬頻率頻譜之間相互轉(zhuǎn)換。本系統(tǒng)采用DDS AD9833作為超聲波發(fā)射單元的脈沖生成器,,AD9833是可編程的,,通過(guò)高速串口外圍接口(SPI),只需要一個(gè)外部時(shí)鐘去產(chǎn)生簡(jiǎn)單的正弦波就可以工作了,。AD9833可以在基于25 MHz的時(shí)鐘下產(chǎn)生0~12.5 MHz的波形[6],。
 I2C設(shè)備在Linux下完全可以作為一個(gè)字符設(shè)備,可以根據(jù)需要編寫一個(gè)字符設(shè)備驅(qū)動(dòng)程序來(lái)支持I2C通信,。但是由于I2C總線是一種標(biāo)準(zhǔn)總線,,在PC和嵌入式系統(tǒng)中都得到了廣泛的應(yīng)用,Linux專門為I2C總線定義了I2C驅(qū)動(dòng)程序體系結(jié)構(gòu)[4],,使驅(qū)動(dòng)程序有統(tǒng)一的接口,,方便了驅(qū)動(dòng)設(shè)計(jì)者設(shè)計(jì),也便于移植,。
在Linux系統(tǒng)中,,I2C總線驅(qū)動(dòng)體系由I2C核心、總線適配器驅(qū)動(dòng)和設(shè)備驅(qū)動(dòng)三部分組成,。
?。?)I2C核心
 I2C核心即i2c-core.c,是Linux內(nèi)核用來(lái)維護(hù)和管理的I2C總線的核心部分,,實(shí)現(xiàn)了I2C總線驅(qū)動(dòng)的框架,。I2C核心為總線提供了統(tǒng)一的接口函數(shù),實(shí)現(xiàn)了I2C總線驅(qū)動(dòng)和設(shè)備驅(qū)動(dòng)的注冊(cè)、注銷及通信等功能,。I2C核心是I2C總線適配器驅(qū)動(dòng)和設(shè)備驅(qū)動(dòng)之間的橋梁,。
 (2)I2C總線適配器驅(qū)動(dòng)
 I2C總線適配器驅(qū)動(dòng)主要包括了對(duì)應(yīng)具體硬件I2C控制器的I2C總線適配器i2c_adapter以及I2C總線適配器的通信傳輸算法i2c_algorithm以及總線驅(qū)動(dòng)控制適配器通信函數(shù)等,,為I2C核心提供了底層支持,,是與硬件相關(guān)的。需要注意的是,,I2C總線驅(qū)動(dòng)程序只是提供了I2C總線的讀寫方法,,其本身并不進(jìn)行任何通信,它只是等待設(shè)備驅(qū)動(dòng)調(diào)用其函數(shù)來(lái)對(duì)具體的硬件設(shè)備進(jìn)行訪問(wèn),。
?。?)I2C設(shè)備驅(qū)動(dòng)程序
 I2C設(shè)備驅(qū)動(dòng)程序通過(guò)I2C總線適配器驅(qū)動(dòng)與具體的硬件設(shè)備進(jìn)行通信。I2C設(shè)備驅(qū)動(dòng)程序中主要包括了數(shù)據(jù)結(jié)構(gòu)i2c_driver(用于管理i2c_client),、i2c_client(掛在I2C總線上的設(shè)備驅(qū)動(dòng)程序)和需要根據(jù)具體設(shè)備實(shí)現(xiàn)的成員函數(shù),。標(biāo)準(zhǔn)的I2C驅(qū)動(dòng)程序也是一個(gè)字符設(shè)備驅(qū)動(dòng)程序,通過(guò)i2c-dev.c來(lái)進(jìn)行管理,,包括open,、release、read,、write,、ioctl和lseek等。
    Linux內(nèi)核I2C總線驅(qū)動(dòng)程序構(gòu)架如圖2所示,,其反映了I2C總線驅(qū)動(dòng)體系間的關(guān)系,。

3 S3C2410中I2C總線驅(qū)動(dòng)程序的實(shí)現(xiàn)

 


 S3C2410處理器集成了I2C總線控制器,支持主,、從模式,通過(guò)對(duì)它的4個(gè)寄存器I2CCON,、I2CSTAT,、I2CDS和I2CADD的操作就可以方便地對(duì)I2C總線進(jìn)行控制。此外,,S3C2410還為I2C總線提供了一個(gè)中斷號(hào)為27的I2C總線中斷,,這樣可以在編寫數(shù)據(jù)發(fā)送和接收程序時(shí)使用中斷來(lái)完成。
由于I2C核心提供了統(tǒng)一的,、不需要修改的接口函數(shù),,因此驅(qū)動(dòng)程序開(kāi)發(fā)者只需要實(shí)現(xiàn)特定的I2C總線適配器驅(qū)動(dòng)和I2C設(shè)備驅(qū)動(dòng),這樣大大提高了嵌入式 Linux的I2C總線驅(qū)動(dòng)程序的移植性[5],。
3.1 I2C總線適配器驅(qū)動(dòng)的實(shí)現(xiàn)
 對(duì)于S3C2410上的I2C總線驅(qū)動(dòng)程序,,按照I2C驅(qū)動(dòng)程序體系結(jié)構(gòu)與硬件的對(duì)應(yīng)關(guān)系,首先需要給S3C2410的I2C控制器添加對(duì)應(yīng)的I2C總線適配器驅(qū)動(dòng)程序,即填充結(jié)構(gòu)體i2c_adapter,。其通過(guò)i2c-core中的接口函數(shù)i2c_add_adapter將i2c_adapter和i2c_algorithm注冊(cè)到操作系統(tǒng)中,。
 再者,實(shí)現(xiàn)S3C2410中I2C適配器的通信方法,,主要實(shí)現(xiàn)i2c_algorithm中處理I2C消息的函數(shù)master_xfer(),。master_xfer()負(fù)責(zé)S3C2410中I2C控制器的寄存器,用于產(chǎn)生I2C訪問(wèn)周期需要的函數(shù),,以i2c_msg(即I2C消息)為單位,,以此控制I2C總線發(fā)送和接收數(shù)據(jù)的方法。另外,,函數(shù)需實(shí)現(xiàn)functionality()函數(shù),,其只返回一個(gè)algorithm所支持的通信傳輸模式,較容易實(shí)現(xiàn),。
3.2 設(shè)備驅(qū)動(dòng)程序的實(shí)現(xiàn)
 首先在芯片的總線適配器驅(qū)動(dòng)程序中需要實(shí)現(xiàn)一個(gè)i2c_driver結(jié)構(gòu)并設(shè)置I2C芯片的初始化和卸載函數(shù),,實(shí)現(xiàn)i2c_driver中的數(shù)據(jù)成員attach_adapter和detach_client。初始化時(shí),,向系統(tǒng)注冊(cè)一個(gè)I2C字符設(shè)備,,接著使用函數(shù)i2c_add_driver()注冊(cè)一個(gè)I2C驅(qū)動(dòng)管理結(jié)構(gòu)體i2c_driver,使I2C芯片相應(yīng)結(jié)構(gòu)中的成員attach_adapter執(zhí)行,,進(jìn)而調(diào)用I2C核心的i2c_probe()遍歷所有的i2c_adapter,,當(dāng)?shù)刂穮?shù)與芯片設(shè)備地址一致時(shí),則會(huì)調(diào)用結(jié)構(gòu)i2c_driver中detach_client成員函數(shù)來(lái)初始化芯片的i2c_client結(jié)構(gòu),,最后通過(guò)I2C核心提供的i2c_attach_client向I2C總線適配器i2c_adapter來(lái)注冊(cè)該芯片的I2C設(shè)備[6],。I2C總線識(shí)別這個(gè)設(shè)備后就會(huì)調(diào)用相應(yīng)的i2c_driver驅(qū)動(dòng)該設(shè)備。
 在應(yīng)用層實(shí)現(xiàn)用戶程序訪問(wèn)I2C設(shè)備的結(jié)構(gòu)file_operations接口函數(shù),,包括打開(kāi),、釋放、讀/寫和ioctl等標(biāo)準(zhǔn)文件操作的接口函數(shù),。open()和release()這兩個(gè)函數(shù)已經(jīng)在內(nèi)核中實(shí)現(xiàn),,read()和write()函數(shù)用來(lái)實(shí)現(xiàn)用戶和系統(tǒng)內(nèi)核之間相互傳遞數(shù)據(jù),進(jìn)而實(shí)現(xiàn)對(duì)設(shè)備的讀寫操作,,它們分別調(diào)用了I2C核心的i2c_master_recv()和i2c_master_send()函數(shù)來(lái)構(gòu)造一條I2C消息并在一個(gè)讀寫周期內(nèi)進(jìn)行傳輸,。ioctl()函數(shù)則用來(lái)向用戶提供一些命令以控制具體芯片設(shè)備,因?yàn)椴煌酒瑢?shí)現(xiàn)數(shù)據(jù)傳遞需要的時(shí)序是不同的,,針對(duì)具體的芯片,,應(yīng)用程序需要通過(guò)構(gòu)造i2c_rdwr_ioctl_data結(jié)構(gòu)體來(lái)給內(nèi)核傳遞一條或數(shù)條I2C消息,從而實(shí)現(xiàn)控制數(shù)據(jù)傳輸?shù)淖x寫周期,。
 I2C總線由于具有電路結(jié)構(gòu)簡(jiǎn)單,、使用方便、通信速率高等優(yōu)點(diǎn),已在嵌入式系統(tǒng)中得到了廣泛的應(yīng)用,。本文在介紹了I2C總線和分析了Linux系統(tǒng)下I2C總線的體系結(jié)構(gòu)基礎(chǔ)上,,以S3C2410為例,給出了在其中編寫I2C總線驅(qū)動(dòng)程序的基本開(kāi)發(fā)過(guò)程,。
參考文獻(xiàn)
[1] 朱瑜亮,,黃曉革.數(shù)字溫度傳感器DS1621在Linux下的I2C接口驅(qū)動(dòng)設(shè)計(jì)[J].電子設(shè)計(jì)工程,2011,,19(2):133-136.
[2] 李俊.嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解[M].北京:人民郵電出版社,,2008.
[3] BECK M,BOHME H,,DZIADZKA M,,等.Linux內(nèi)核編程指南[M].張瑜,楊繼萍,,等,,譯.北京:清華大學(xué)出版社,2004.
[4] 劉淼.嵌入式系統(tǒng)接口設(shè)計(jì)與Linux驅(qū)動(dòng)程序開(kāi)發(fā)[M].北京:北京航空航天大學(xué)出版社,,2006.
[5] 李祥兵,,鄭扣根.Linux中I2C總線驅(qū)動(dòng)程序的開(kāi)發(fā)[J].計(jì)算機(jī)工程與設(shè)計(jì),2005,,26(1):41-43.
[6] 宋寶華.Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解[M].北京:人民郵電出版社,,2008.

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載,。