Linux環境下基於I2C匯流排的EEPROM 驅動程序

admin @ 2014-03-25 , reply:0

1 引言
    I2C (Inter-Integrated Circuit1匯流排是一種由Philips公司開發的2線式串列匯流排,用於連接微控制器及其外圍設備。它是同步通信的一種特殊形式,具有介麵線少、控制方式簡單、器件封裝形式小、通信速率較高等優點。在主從通信中,可有多個I2C匯流排器件同時接到I2C匯流排上,通過地址來識別通信對象。筆者在開發基於MPC8250的嵌入式Linux系統的過程中發現I2C匯流排在嵌入式系統中應用廣泛,I2C匯流排控制器的類型比較多,對系統提供的操作介面差別也很大。與I2C匯流排相連的從設備主要有微控制器、EEPROM、實時時鐘、A/D轉換器等.MPC8250處理器正是通過內部的I2C匯流排控制器來和這些連接在I2C匯流排上的設備進行數據交換的。由於I2C匯流排的特性,Linux的I2C匯流排設備驅動程序的設計者在設計驅動程序時採用了獨特的體系結構。使開發I2C匯流排設備驅動程序與開發一般設備驅動程序的方法具有很大差別。因此,開發I2C匯流排設備驅動程序除了要涉及一般Linux內核驅動程序的知識外.還要對I2C匯流排驅動的體系結構有深入的了解。筆者在開發過程中使用設備型號為AT24C01A的EEPROM 來測試I2C匯流排驅動。

2 工作原理概述
    在介紹I2C匯流排結構之前。要搞清楚兩個概念:I2C匯流排控制器和I2C設備。I2C匯流排控制器為微控制器或微處理器提供控制I2C匯流排的介面,它控制所有I2C匯流排的特殊序列、協議、仲裁、時序,這裡指MPC8250提供的I2C匯流排控制介面。I2C設備是指通過I2C匯流排與微控制器或微處理器相連的設備,如EEPROM、LCD驅動器等,這裡指EEPROM。
    在一個串列數據通道中.I2C匯流排控制器可以配置成主模式或從模式。開發過程中,MPC8250的I2C匯流排控制器工作在主模式,作為主設備;與匯流排相連的I2C設備為AT24C01A型EEPROM,作為從設備。主設備和從設備都可以工作於接收和發送狀態。匯流排必須由主設備控制,主設備產生串列時鐘控制匯流排的傳輸方向,併產生起始和停止條件。

2.1 I2C匯流排控制器
    I2C使用由串列數據線SDA 和串線時鐘線SCL組成的兩線結構來在外部集成電路與控制器之間交換數據。MPC8250的I2C匯流排控制器包括發送和接收單元、一個獨立的波特率發生器和一個控制單元。發送和接收單元使用相同的時鐘信號,如果I2C為主設備.那麼時鐘信號由I2C的波特率發生器產生;如果I2C為從設備,時鐘信號則由外部提供。
    SDA和SCL為雙向的,通過外部+3.3 V上拉電阻連接至正向電壓。當匯流排處於空閑狀態時,SDA和SCL都應是高電平,I2C通常的配置模式如圖1所示。
 
圖1 I2C配置模式
    I2C的接收和發送單元均為雙緩存,在數據發送時,數據從發送數據寄存器到移位寄存器,以時鐘速率輸出到SDA線;在數據接收時,數據從SDA線進入移位寄存器,然後進入接收寄存器。

2.2 I2C匯流排控制器和EEPROM 的基本操作
    I2C匯流排在傳送數據過程中共有3種類型的信號,分別是:開始信號、結束信號和應答信號。
開始信號:SCL為高電平時,SDA 由高電平向低電平跳變,開始傳送數據;
結束信號:SCL為高電平時,SDA由低電平向高電平跳變,傳送數據結束;
應答信號:接收數據的設備在接收到一個位元組數據后, 向發送數據的設備發出特定的低電平脈衝.表示已收到數據。
    當MPC8250的I2C匯流排空閑時,其SDA和SCL均為高電平,主設備通過發送一個開始信號啟動發送過程。這個信號的時序要求是當SCL為高時,SDA出現一個由高到低的電平跳變。在起始條件之後.必須是從設備的地址位元組,其中高4位為器件類型識別符(不同的晶元類型有不同的定義,EEPROM一般應為1010),接著3位為片選,最後1位為讀寫位,當為1時為讀操作,為0時為寫操作,如圖2所示。
 
圖2 EEPROM設備地址位元組結構
    如果主設備要向EEPROM 中寫數據,在地址位元組中主設備向EEPROM發出一個寫請求(R/W=0),發送的地址位元組之後緊跟著要發送的數據。每發送一個位元組的數據后EEPROM就會產生一個應答信號,主設備也會監控應答信號,如果在發送一個位元組后EEPROM沒有返回應答信號,則主設備就會停止發送,並生成一個結束信號。寫操作的時序如圖3所示。
 
圖3 I2C主設備寫操作時序
    要從EEPROM 中讀取數據時,應設置R/W=1。在EEPROM發送完一個位元組的數據后,主設備產生一個應答信號來響應,告知EEPROM主設備要求更多的數據,對應主設備產生的每個應答信號EEPROM將發送一個位元組的數據。當主設備不發送應答信號並隨後發送結束信號位時結束此操作。讀操作的時序如圖4所示。
 
圖4 I2C主設備讀操作時序

3 Linux中I2C匯流排驅動體系結構
    在Linux系統中,對於一個給定的I2C匯流排硬體配置系統,I2C匯流排驅動程序體系結構由I2C匯流排驅動和I2C設備驅動組成。其中I2C匯流排驅動包括一個具體的控制器驅動和I2C匯流排的演算法驅動.一個演算法驅動適用於一類匯流排控制器.而一個具體的匯流排控制器驅動要使用某一種演算法。例如,Linux內核中提供的演算法i2e-algo-8260可以用在MPC82xx系列處理器提供的I2C匯流排控制器上。Linux內核中提供了一些常見處理器如MPC82xx系列的演算法驅動。對於I2C設備,基本上每種具體設備都有自己的基本特性.其驅動程序一般都需要特別設計。
    在I2C匯流排驅動程序體系結構中.使用數據結構Driver來表示I2C設備驅動,使用數據結構Client表示一個具體的I2C設備。而對於I2C匯流排
控制器,各種匯流排控制器在進行數據傳輸時採用的演算法有好多種,使用相同演算法的控制器提供的控制介面也可能不同。在I2C匯流排驅動程序體系結構中,用數據結構Algorithm來表示演算法,用數據結構Adapter來表示不同的匯流排控制器。Linux內核的I2C匯流排驅動程序體系結構如圖5所示。
 
圖5 Linux內核I2C匯流排驅動程序體系結構
    在圖5中,一個Client對象對應一個具體的I2C匯流排設備,而一種I2C設備的Driver可以同時支持多個Client。每個Adapter對應一個具體的I2C匯流排控制器.不同的I2C匯流排控制器可以使用相同的演算法Algorithm。i2c-core是I2C匯流排驅動程序體系結構的核心,在這個模塊中,除了為匯流排設備驅動提供了一些統一的調用介面來訪問具體的匯流排驅動程序功能,以進行讀寫或設置操作外,還提供了將各種支持的匯流排設備驅動和匯流排驅動添加到這個體系中的方法,以及當不再使用這些驅動時將其從體系中刪除的方法。i2c-core將匯流排驅動程序體系一分為二,相互獨立。可以針對某個I2C匯流排設備來設計一個I2C設備驅動程序,而不需要關心繫統的I2C匯流排控制器是何種類型,所以提高了其可移植性。另一方面,在設計I2C匯流排驅動時也可以不要考慮其將用來支持何種設備。因為i2c-core提供了統一的介面,所以也為設計這兩類驅動
提供了方便。

4 開發實例
    Linux內核已經提供了I2C驅動中所需要的基本模塊。i2c-core、i2c-dev和i2c-proc是匯流排控制器和I2C設備所需要的核心模塊。對於MPC8250處理器,內核中還有MPC8260的演算法模塊i2c-algo-8260,它也適用於MPC8250的I2C控制介面。這些模塊程序在默認條件下是不會被編譯到內核里的,所以需要在配置Linux內核時把這些模塊選中。在筆者的開發中需要實現的是I2C匯流排控制器驅動和I2C設備EEPROM驅動。

4.1 I2C匯流排控制器驅動的設計
    MPC8250的I2C匯流排驅動程序由i2c-algo-8260演算法模塊和MPC8250具體的I2C匯流排控制器驅動組成。其中i2c-algo-8260演算法模塊已經在內核中實現,所以主要實現FC匯流排控制器驅動。
    i2c-algo-8260演算法模塊主要用來描述MPC82xx處理器如何在I2C匯流排上傳輸數據。該模塊中主要實現了MPC82xx處理器上I2C匯流排的初始化、讀寫、ioctl控制和中斷請求等功能。另外,還有i2c_8260_add_bus和i2c_8260_del_bus兩個函數,它們是使用這個演算法的Adapter初始化時和退出時調用的函數,用來註冊和註銷一個匯流排控制器,需要從模塊導出。這些函數功能都被封裝在一個i2c-algorithm結構中,傳遞給使用這個演算法的Adapter。演算法模塊中這些函數需要調用特定控制器模塊中的函數來實現具體的操作。
    在I2C匯流排控制器驅動模塊中主要要實現兩個結構體i2c_adapter和i2c_algo_8260_data,定義這兩個結構中的函數指針成員.並且用己經初始化好的i2c_algo_826o_data結構來初始化struct i2c_adapter結構的algo_data成員變數。其中,定義i2e_algo_8260_data結構為:
struct i2c_algo_8260_data rw8250_data={
setisr:rw8250_install_isr
};
    這裡的成員變數rw8250_install__isr提供了MPC8250的I2C匯流排控制器向內核申請中端請求的功能。結構體i2c_adapter定義如下:
struct i2c_adapter rw8250_ops={"rw8250",I2C_HW_
MPC8250_RW8250,NULL,&rw8250_data,rw8250_inc_use,rw8250_dec_use,rw8250_reg,rw8250_unreg,};
其中,"rw8250"是該匯流排控制器的標識名,宏名I2C_HW_MPC8250_RW8250定義了內核中註冊該適配器的ID號,而成員函數rw8250_inc_use和rw8250_dec_use用來增加和減少內核使用該模塊的次數。
    另外,該模塊還要完成一個註冊模塊時的初始化函數rw8250_iic_init,在該函數中要初始化I2C控制器使用的通用埠號PortD14、PortD15,並在雙埠RAM 中為發送和接受數據的緩衝區分配空間。函數rw8250_iic_init在進行模塊初始化時將被init_module調用。
    總之。I2C控制器模塊中設計的這些函數都是為i2c_algo_8650演算法模塊服務的.最後需要封裝在i2c-adapter結構中.通過i2c_algo_8260_data演算法模塊中輸出的介面函數傳遞給演算法模塊。

4.2 I2C設備驅動的設計
    I2C設備EEPROM 驅動除了要根據EEPROM的具體特性進行設計外.還要考慮I2C匯流排驅動程序體系結構的特性。在EEPROM設備驅動程序中需要實現一個i2c_driver結構.每個對應於具體設備的Client都從這個結構來構造。在i2c_driver結構中有兩個函數attach_adapter和detach_client必須要實現。i2c_driver結構的定義如下:
struct i2c_driver eeprom_driver = {
/*name*/ "I2C_EEPROM_DRIVER",/*id*/I2C_DRIVERID_EEPROM,
/*flags*/ I2C_DF_NOTIFY,/*attach_ adapter*/&eeprom_attach_adapter,/*detach_client */&eeprom_detach_client,
/*command*/&eeprom_command,/*inc_use*/ &eeprom_inc_use,/*dec_use*/ &eeprom_dec_use
};
    在設備驅動中。向EEPROM 寫數據通過調用i2c-core提供的i2c_master_send函數來完成。從EEPROM 讀取數據通過另一個函數i2c_master_read來完成。與一般設備驅動不同的地方就是在EEPROM驅動模塊初始函數中要調用i2c-core提供的i2c_add_driver函數來註冊該設備。在模塊退出函數中調用i2c_del_driver函數來註銷該設備。

5 結束語
    I2C匯流排具有控制簡單、通信速率高等優點,作為一種2線雙向同步串列數據匯流排,它為嵌入式系統設計提供了一種完善的集成電路間的串列匯流排擴展技術,大大簡化了應用系統的硬體設計,為實現應用系統的模塊化設計創造了極為有利的條件。同時,在很多情況下需要對系統中的某些動態信息進行掉電保護。在數據量不太大的場合下,通過I2C匯流排連接的EEPROM在這方面就比較能發揮作用。而Linux作為一種新的操作系統,目前在嵌入式系統中的應用非常廣泛。其發展前景無法估量。由於Linux源碼開放,且非常易於移植,為其編寫設備驅動程序相對容易。本文介紹了Linux下I2C匯流排EEPROM驅動程序的一般設計方法。




[admin via 研發互助社區 ] Linux環境下基於I2C匯流排的EEPROM 驅動程序已經有1382次圍觀

http://cocdig.com/docs/show-post-42157.html