㈠ 如何在linux中讓I2C驅動支持Sub Address的兩種方法
【目的】
AS3527有一個模擬部分,稱作AFE,其與數字部分通過i2c通信,此處AFE部分有很多寄存器供外界操作訪問,如果想要訪問這些寄存器,就要用到Sub Address,所以,要實現讓i2c 驅動支持Sub Address的模式。
i2C本身的架構中,沒有支持sub address,所以,我們只能想辦法,讓其I2C支持(方法1)或者用smbus的架構(方法2).
【方法】
方法1:
在i2c的message中傳遞一個2個位元組的buffer,分別存放Sub Address和data
比如,對於讀操作,就可以這么實現:
int afe_read_reg(int addr, u8 *pdata)
{
u8 msgbuf[2];
struct i2c_msg msg =
{
.addr = save_client->addr | ( << 8),
.flags = I2C_M_RD ,
.len = 2,
.buf = msgbuf,
};
msgbuf[0] = addr; //存放Sub Address,此處的Addr是寄存器地址,也就是Sub Address
msgbuf[1] = 0; //初始化
if (i2c_transfer(save_client->adapter, &msg, 1) < 0) {
dev_warn(&save_client->dev,
"can't read from afe /n");
return -ENOMEM;
}
*pdata = msgbuf[1];
return 0;
}
方法2:
使用SMBUS的框架,其支持Sub Address
在i2c讀操作中,直接調用SMBUS架構中的函數i2c_smbus_read_byte_data:
int afe_read_reg(int addr, u8 *pdata)
{
int ret;
ret = i2c_smbus_read_byte_data(save_client, addr);
if (ret < 0)
return ret;
else {
*pdata = (u8)ret;
return 0;
}
}
然後函數調用順序是
i2c_smbus_read_byte_data -> i2c_smbus_xfer ->
adapter->algo->smbus_xfer 或 i2c_smbus_xfer_emulated
(1)此處如果你自己的I2C驅動中沒有實現
adapter->algo->smbus_xfer
那麼就會去調用i2c_smbus_xfer_emulated,其會把I2C的讀一個位元組的操作,
分成2個message,然後
i2c_smbus_xfer_emulated -> i2c_transfer -> adap->algo->master_xfer(adap,msgs,num)
去調用底層自己的i2c傳輸的函數master_xfer去實現兩個message的傳輸。
此處要注意的是,如果你的i2C的控制器和i2c設備,支持將此I2C的讀一個位元組操作分兩個message傳輸,
那麼此處此方法也是可以的。
而你的底層的master_xfer函數,只要負責將對應的message發送出去也就可以實現對應的功能了。
否則,就像我此處遇到的,我這里的AFE的i2c控制器,不支持讀操作分成兩次message,只支持一個I2C message的傳輸,
所以,只能是在底層特殊處理,將2個message自己整理成一個message,或者是用下面的辦法。
(2)自己實現了adapter->algo->smbus_xfer
自己仿照i2c_smbus_xfer_emulated,在具體實現的時候,對於讀和寫都只是發送一個message,然後讓底層代碼
adap->algo->master_xfer去處理這個message,實現對應的讀和寫。
【注意】
1.以上,不論是1還是2,都是在實現了自己I2C驅動底層message傳輸的基本函數之後,才可以工作的。
而對於這個基本函數,即adap->algo->master_xfer,
都是要在實現的時候,注意上層傳遞過來的buffer的第一個位元組是sub address,第二個位元組才是要用於寫入或讀取的buffer。
2.對於方法2(2),在模擬i2c_smbus_xfer_emulated實現自己的xfer函數的時候,
不能直接調用i2c_transfer,因為i2c_transfer裡面,去獲得adapter->bus_lock,而i2c_smbus_xfer中,調用adapter->algo->smbus_xfer之前,已經進行了對於adapter->bus_lock鎖定,而因此會形成死鎖的的,辦法是不要再去獲得鎖,而直接調用adapter->algo->master_xfer即可。
㈡ linux下怎麼直接使用iic介面
利用Linux中IIC設備子系統移植IIC設備驅動
背景描述
IIC匯流排在嵌入式系統中應用十分廣泛,常見的有eeprom,rtc。一般的處理器會包含IIC的控制器,用來完成IIC時序的控制;另外一方面,由於IIC的時序簡單,使用GPIO口來模擬時序也是常見的做法。面對不同的IIC控制器,各種各樣的晶元以及linux源碼,如何更快做好IIC設備驅動。
問題描述
在我們的方案中,我們會用到eeprom,rtc以及tw2865。由於Hi3520的IIC控制器設計有問題,無法正常使用。而IIC控制器的SDA和SCL管腳正好是和兩個GPIO管腳復用的。Hisi將控制gpio來實現IIC的時序,從而對IIC設備進行操作。這種設計方式簡單明了,但使用IIC子系統,可以更方便的移植和維護其他的設備驅動。
問題分析
Hisi對於gpio口,rtc晶元以及tw2865的處理方式如下:將gpio口做成一個模塊化的驅動,該驅動模擬IIC時序,並向外提供一些函數介面,比如:EXPORT_SYMBOL(gpio_i2c_read_tw2815);等。對於具體的rtc晶元,將其注冊為一個misc設備,並利用gpio模塊導出的函數進行rtc晶元的配置操作。
其實對於linux-2.6.24\drivers\i2c目錄下代碼,我們可以加以利用。
Linux的IIC字結構分為三個組成部分:
IIC核心
IIC核心提供了IIC匯流排驅動和設備驅動的注冊、注銷方法,IICalgorithm上層的、與具體適配器無關的代碼以及探測設備、檢測設備地址的上層代碼。
IIC匯流排驅動
IIC匯流排驅動是對IIC硬體體系結構中適配器端的實現。
IIC設備驅動
IIC設備驅動是對IIC硬體體系總設備端的實現。
我們查看下該目錄下的makefile和kconfig:
obj-$(CONFIG_I2C_BOARDINFO) +=i2c-boardinfo.o
obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) +=i2c-dev.o
obj-y +=busses/ chips/ algos/
i2c-core.c就是IIC核心,buses中的文件是主流處理器中IIC匯流排的匯流排驅動,而chips中的文件就是常用晶元的驅動,algos中的文件實現了一些匯流排適配器的algorithm,其中就包括我們要用到的i2c-algo-bit.c文件。
我們首先利用i2c-gpio.c和i2c-algo-bit.c做好匯流排驅動。
在i2c-gpio.c中,mole_initi2c_gpio_initplatform_driver_probe(&i2c_gpio_driver,i2c_gpio_probe);
將其注冊為platform虛擬匯流排的驅動。
在staticint __init i2c_gpio_probe(struct platform_device *pdev)中,
定義了如下三個結構體:
structi2c_gpio_platform_data *pdata;//平台相關的gpio的設置
structi2c_algo_bit_data *bit_data;//包含algorithm的具體函數,setor
get SDA和SCL
structi2c_adapter *adap;//適配器
i2c_gpio_probe主要做了下面幾件事:
填充bit_data結構的各個函數指針,關聯到具體的操作SDA和SCl函數。
填充adap結構,adap->algo_data= bit_data;
pdata= pdev->dev.platform_data;
bit_data->data= pdata;
pdev->dev->driver_data= adap;
在i2c-core中注冊適配器類型。
inti2c_bit_add_numbered_bus(struct i2c_adapter *adap)
在staticint i2c_bit_prepare_bus(struct i2c_adapter *adap)中
adap->algo= &i2c_bit_algo;
將i2c_bit_algo與adap關聯上。
static const structi2c_algorithm i2c_bit_algo = {
.master_xfer = bit_xfer,
.functionality = bit_func,
};
其中,master_xfer函數指針就是IIC傳輸函數指針。
I2c-algo-bit.c還實現了IIC開始條件,結束條件的模擬,發送位元組,接收位元組以及應答位的處理。
i2c-gpio.c中的i2c_gpio_setsda_val等函數是與具體平台gpio相關的。
修改對應arch-hi3520v100目錄下的gpio.h中的各個函數,這些函數是通過操作寄存器來控制gpio的方向和值。
在對應mach-hi3520v100中的platform-devices.c中添加如下:
static structi2c_gpio_platform_data pdata = {
.sda_pin = 1<<0,
.sda_is_open_drain = 1,
.scl_pin = 1<<1,
.scl_is_open_drain = 1,
.udelay = 4, /* ~100 kHz */
};
static struct platform_devicehisilicon_i2c_gpio_device = {
.name = "i2c-gpio",
.id = -1,
.dev.platform_data = &pdata,
};
static struct platform_device*hisilicon_plat_devs[] __initdata = {
&hisilicon_i2c_gpio_device,
};
int __inithisilicon_register_platform_devices(void)
{
platform_add_devices(hisilicon_plat_devs,ARRAY_SIZE (hisilicon_plat_devs));
return 0;
}
通過platform添加devices和driver,使得pdev->dev.platform_data=pdata
綜合上面的過程,我們完成了adapter的注冊,並將用gpio口模擬的algorithm與adapter完成了關聯。
這樣,在rtc-x1205.c中,x1205_attach函數利用i2c核心完成client和adap的關聯。
在x1205_probe函數中填充i2c_client結構體,並調用i2c_attach_client通知iic核心。
接著注冊rtc驅動。
最後我們要讀取時間,就需要構造i2c_msg結構體,如下所示:
struct i2c_msg msgs[] = {
{ client->addr, 0, 2,dt_addr }, /* setup read ptr */
{ client->addr, I2C_M_RD,8, buf }, /* read date */
};
/* read date registers */
if((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
dev_err(&client->dev,"%s: read error\n", __FUNCTION__);
return -EIO;
}
dt_addr是寄存器的地址,I2C_M_RD表示iicread。
㈢ arm平台下linux驅動。。想製作一個鍵盤驅動,介面為iic,能夠捕獲iic值產生相應的鍵盤事件
IIC規范
IIC(Inter-Integrated Circuit)匯流排是一種由PHILIPS公司開發的兩線式串列匯流排,用於連接微控制器及其外圍設備。IIC匯流排產生於在80年代,最初為音頻和視頻設備開發,如今主要在伺服器管理中使用,其中包括單個組件狀態的通信。例如管理員可對各個組件進行查詢,以管理系統的配置或掌握組件的功能狀態,如電源和系統風扇。可隨時監控內存、硬碟、網路、系統溫度等多個參數,增加了系統的安全性,方便了管理。
2.1 IIC匯流排的特點
IIC匯流排最主要的優點是其簡單性和有效性。由於介面直接在組件之上,因此IIC匯流排佔用的空間非常小,減少了電路板的空間和晶元管腳的數量,降低了互聯成本。匯流排的長度可高達25英尺,並且能夠以10Kbps的最大傳輸速率支持40個組件。IIC匯流排的另一個優點是,它支持多主控(multimastering), 其中任何能夠進行發送和接收的設備都可以成為主匯流排。一個主控能夠控制信號的傳輸和時鍾頻率。當然,在任何時間點上只能有一個主控。
2.2 IIC匯流排工作原理
2.2.1 匯流排構成及信號類型
IIC匯流排是由數據線SDA和時鍾SCL構成的串列匯流排,可發送和接收數據。在CPU與被控IC之間、IC與IC之間進行雙向傳送,最高傳送速率100kbps。各種被控制電路均並聯在這條匯流排上,但就像電話機一樣只有撥通各自的號碼才能工作,所以每個電路和模塊都有唯一的地址,在信息的傳輸過程中,IIC匯流排上並接的每一模塊電路既是主控器(或被控器),又是發送器(或接收器),這取決於它所要完成的功能。
CPU發出的控制信號分為地址碼和控制量兩部分:
? 地址碼用來選址,即接通需要控制的電路,確定控制的種類;
? 控制量決定該調整的類別(如對比度、亮度等)及需要調整的量。
這樣,各控制電路雖然掛在同一條匯流排上,卻彼此獨立,互不相關。
IIC匯流排在傳送數據過程中共有三種類型信號:
? 開始信號:SCL為高電平時,SDA由高電平向低電平跳變,開始傳送數據。
? 結束信號:SCL為高電平時,SDA由低電平向高電平跳變,結束傳送數據。
? 數據傳輸信號:在開始條件以後,時鍾信號SCL的高電平周期期問,當數據線穩定時,數據線SDA的狀態表示數據有效,即數據可以被讀走,開始進行讀操作。在時鍾信號SCL的低電平周期期間,數據線上數據才允許改變。每位數據需要一個時鍾脈沖。
? 應答信號:接收數據的IC在接收到8bit數據後,向發送數據的IC發出特定的低電平脈沖,表示已收到數據。CPU向受控單元發出一個信號後,等待受控單元發出一個應答信號,CPU接收到應答信號後,根據實際情況作出是否繼續傳遞信號的判斷。若未收到應答信號,由判斷為受控單元出現故障。
目前有很多半導體集成電路上都集成了IIC介面。帶有IIC介面的單片機有:CYGNAL的 C8051F0XX系列,PHILIPSP87LPC7XX系列,MICROCHIP的PIC16C6XX系列等。很多外圍器件如存儲器、監控晶元等也提供IIC介面。
2.3 匯流排基本操作
IIC規程運用主/從雙向通訊。器件發送數據到匯流排上,則定義為發送器,器件接收數據則定義為接收器。主器件和從器件都可以工作於接收和發送狀態。 匯流排必須由主器件(通常為微控制器)控制,主器件產生串列時鍾(SCL)控制匯流排的傳輸方向,並產生起始和停止條件。SDA線上的數據狀態僅在SCL為低電平的期間才能改變,SCL為高電平的期間,SDA狀態的改變被用來表示起始和停止條件。
2.3.1 控制位元組
在起始條件之後,必須是器件的控制位元組,其中高四位為器件類型識別符(不同的晶元類型有不同的定義,EEPROM一般應為1010),接著三位為片選,最後一位為讀寫位,當為1時為讀操作,為0時為寫操作。
2.3.2 寫操作
寫操作分為位元組寫和頁面寫兩種操作,對於頁面寫根據晶元的一次裝載的位元組不同有所不同。關於頁面寫的地址、應答和數據傳送的時序。
2.3.3 讀操作
讀操作有三種基本操作:當前地址讀、隨機讀和順序讀。圖4給出的是順序讀的時序圖。應當注意的是:最後一個讀操作的第9個時鍾周期不是「不關心」。為了結束讀操作,主機必須在第9個周期間發出停止條件或者在第9個時鍾周期內保持SDA為高電平、然後發出停止條件。
2.3.4 匯流排仲裁
主機只能在匯流排空閑的時候啟動傳輸。兩個或多個主機可能在起始條件的最小持續內產生一個起始條件,結果在匯流排上產生一個規定的起始條件。
當SCL線是高電平時,仲裁在SDA線發生:這樣,在其他主機發送低電平時,發送高電平的主機將斷開它的數據輸出級,因為匯流排上的電平和它自己的電平不同。
仲裁可以持續多位。從地址位開始,同一個器件的話接著就是數據位(如果主機-發送器),或者比較相應位(如果主機-接收器)。IIC匯流排的地址和數據信息由贏得仲裁的主機決定,在這個過程中不會丟失信息。
仲裁不能在下面情況之間進行:
? 重復起始條件和數據位;
? 停止條件和數據位;
? 重復起始條件和停止條件。
2.4 特性總結
? IIC肯定是2線的(不算地線)IIC協議確實很科學,比3/4線的SPI要好,當然線多通訊速率相對就快了
? IIC的原則是
l 在SCL=1(高電平)時,SDA千萬別忽悠!!!否則,SDA下跳則"判罰"為"起始信號S",SDA上跳則"判罰"為"停止信號P".
l 在SCL=0(低電平)時,SDA隨便忽悠!!!(可別忽悠過火到SCL跳高)
? 每個位元組後應該由對方回送一個應答信號ACK做為對方在線的標志.非應答信號一般在所有位元組的最後一個位元組後.一般要由雙方協議簽定.
? SCL必須由主機發送,否則天下大亂
? 首位元組是"片選信號",即7位從機地址加1位方向(讀寫)控制.從機收到(聽到)自己的地址才能發送應答信號(必須應答!!!)表示自己在線.其他地址的從機不允許忽悠!!!(當然群呼可以忽悠但只能聽不許說話)
? 讀寫是站在主機的立場上定義的."讀"是主機接收從機數據,"寫"是主機發送數據給從機.
? 重復位主要用於主機從發送模式到接收模式的轉換"信號",由於只有2線,所以收發轉換肯定要比SPI復雜,因為SPI可用不同的邊沿來收發數據,而IIC不行.
? 在硬體IIC模塊,特別是MCU/ARM/DSP等每個階段都會得到一個准確的狀態碼,根據這個狀態碼可以很容易知道現在在什麼狀態和什麼出錯信息.
? 7位IIC匯流排可以掛接127個不同地址的IIC設備,0號"設備"作為群呼地址.10位IIC匯流排可以掛接更多的10位IIC設備.
原文地址:linux下IIC驅動開發分析(2) 作者:putiancaijunyu
3.1 Linux下IIC驅動架構
Linux定義了系統的IIC驅動體系結構,在Linux系統中,IIC驅動由3部分組成,即IIC核心、IIC匯流排驅動和IIC設備驅動。這3部分相互協作,形成了非常通用、可適應性很強的IIC框架。
3.1.1 IIC核心
IIC 核心提供了IIC匯流排驅動和設備驅動的注冊、注銷方法,IIC通信方法(即「algorithm」,筆者認為直譯為「運算方法」並不合適,為免引起誤解, 下文將直接使用「algorithm」)上層的、與具體適配器無關的代碼以及探測設備、檢測設備地址的上層代碼等。
在我們的Linux驅動的i2c文件夾下有algos,busses,chips三個文件夾,另外還有i2c-core.c和i2c-dev.c兩個文件。
i2c-core.c文件實現了I2Ccore框架,是Linux內核用來維護和管理的I2C的核心部分,其中維護了兩個靜態的List,分別記錄系統中的I2Cdriver結構和I2Cadapter結構。I2Ccore提供介面函數,允許一個I2Cadatper,I2Cdriver和I2Cclient初始化時在I2Ccore中進行注冊,以及退出時進行注銷。同時還提供了I2C匯流排讀寫訪問的一般介面,主要應用在I2C設備驅動中。
3.1.2 IIC匯流排驅動
IIC匯流排驅動是對IIC硬體體系結構中適配器端的實現,適配器可由CPU控制,甚至直接集成在CPU內部。匯流排驅動的職責,是為系統中每個I2C匯流排增加相應的讀寫方法。但是匯流排驅動本身並不會進行任何的通訊,它只是存在那裡,等待設備驅動調用其函數。
IIC匯流排驅動主要包含了IIC適配器數據結構i2c_adapter、IIC適配器的algorithm數據結構i2c_algorithm和控制IIC適配器產生通信信號的函數。經由IIC匯流排驅動的代碼,我們可以控制IIC適配器以主控方式產生開始位、停止位、讀寫周期,以及以從設備方式被讀寫、產生ACK等。
Busses文件夾下的i2c-mpc.c文件實現了PowerPC下I2C匯流排適配器驅動,定義描述了具體的I2C匯流排適配器的i2c_adapter數據結構,實現比較底層的對I2C匯流排訪問的具體方法。I2Cadapter 構造一個對I2Ccore層介面的數據結構,並通過介面函數向I2Ccore注冊一個控制器。I2Cadapter主要實現對I2C匯流排訪問的演算法,iic_xfer() 函數就是I2Cadapter底層對I2C匯流排讀寫方法的實現。同時I2Cadpter 中還實現了對I2C控制器中斷的處理函數。
3.1.3 IIC設備驅動
IIC設備驅動是對IIC硬體體系結構中設備端的實現,設備一般掛接在受CPU控制的IIC適配器上,通過IIC適配器與CPU交換數據。設備驅動則是與掛在I2C匯流排上的具體的設備通訊的驅動。通過I2C匯流排驅動提供的函數,設備驅動可以忽略不同匯流排控制器的差異,不考慮其實現細節地與硬體設備通訊。
IIC設備驅動主要包含了數據結構i2c_driver和i2c_client,我們需要根據具體設備實現其中的成員函數。
i2c-dev.c文件中實現了I2Cdriver,提供了一個通用的I2C設備的驅動程序,實現了字元類型設備的訪問介面,實現了對用戶應用層的介面,提供用戶程序訪問I2C設備的介面,包括實現open,release,read,write以及最重要的ioctl等標准文件操作的介面函數。我們可以通過open函數打開 I2C的設備文件,通過ioctl函數設定要訪問從設備的地址,然後就可以通過 read和write函數完成對I2C設備的讀寫操作。
通過I2Cdriver提供的通用方法可以訪問任何一個I2C的設備,但是其中實現的read,write及ioctl等功能完全是基於一般設備的實現,所有的操作數據都是基於位元組流,沒有明確的格式和意義。為了更方便和有效地使用I2C設備,我們可以為一個具體的I2C設備開發特定的I2C設備驅動程序,在驅動中完成對特定的數據格式的解釋以及實現一些專用的功能。
㈣ 嵌入式ubuntu怎麼載入i2c匯流排
Linux定義了系統的IIC驅動體系結構,在Linux系統中,IIC驅動由3部分組成,即IIC核心、IIC匯流排驅動和IIC設備驅動。這3部分相互協作,形成了非常通用、可適應性很強的IIC框架。
3.1.1IIC核心
IIC核心提供了IIC匯流排驅動和設備驅動的注冊、注銷方法,IIC通信方法(即algorithm」,筆者認為直譯為「運算方法」並不合適,為免引起誤解,下文將直接使用「algorithm」)上層的、與具體適配器無關的代碼以及探測設備、檢測設備地址的上層代碼等。
在我們的Linux驅動的i2c文件夾下有algos,busses,chips三個文件夾,另外還有i2c-core.c和i2c-dev.c兩個文件。
i2c-core.c文件實現了I2Ccore框架,是Linux內核用來維護和管理的I2C的核心部分,其中維護了兩個靜態的List,分別記錄系統中的I2Cdriver結構和I2Cadapter結構。I2Ccore提供介面函數,允許一個I2Cadatper,I2Cdriver和I2Cclient初始化時在I2Ccore中進行注冊,以及退出時進行注銷。同時還提供了I2C匯流排讀寫訪問的一般介面,主要應用在I2C設備驅動中。
3.1.2IIC匯流排驅動
IIC匯流排驅動是對IIC硬體體系結構中適配器端的實現,適配器可由CPU控制,甚至直接集成在CPU內部。匯流排驅動的職責,是為系統中每個I2C匯流排增加相應的讀寫方法。但是匯流排驅動本身並不會進行任何的通訊,它只是存在那裡,等待設備驅動調用其函數。
IIC匯流排驅動主要包含了IIC適配器數據結構i2c_adapter、IIC適配器的algorithm數據結構i2c_algorithm和控制IIC適配器產生通信信號的函數。經由IIC匯流排驅動的代碼,我們可以控制IIC適配器以主控方式產生開始位、停止位、讀寫周期,以及以從設備方式被讀寫、產生ACK等。
Busses文件夾下的i2c-mpc.c文件實現了PowerPC下I2C匯流排適配器驅動,定義描述了具體的I2C匯流排適配器的i2c_adapter數據結構,實現比較底層的對I2C匯流排訪問的具體方法。I2Cadapter構造一個對I2Ccore層介面的數據結構,並通過介面函數向I2Ccore注冊一個控制器。I2Cadapter主要實現對I2C匯流排訪問的演算法,iic_xfer()函數就是I2Cadapter底層對I2C匯流排讀寫方法的實現。同時I2Cadpter中還實現了對I2C控制器中斷的處理函數。
3.1.3IIC設備驅動
IIC設備驅動是對IIC硬體體系結構中設備端的實現,設備一般掛接在受CPU控制的IIC適配器上,通過IIC適配器與CPU交換數據。設備驅動則是與掛在I2C匯流排上的具體的設備通訊的驅動。通過I2C匯流排驅動提供的函數,設備驅動可以忽略不同匯流排控制器的差異,不考慮其實現細節地與硬體設備通訊。
IIC設備驅動主要包含了數據結構i2c_driver和i2c_client,我們需要根據具體設備實現其中的成員函數。
i2c-dev.c文件中實現了I2Cdriver,提供了一個通用的I2C設備的驅動程序,實現了字元類型設備的訪問介面,實現了對用戶應用層的介面,提供用戶程序訪問I2C設備的介面,包括實現open,release,read,write以及最重要的ioctl等標准文件操作的介面函數。我們可以通過open函數打開I2C的設備文件,通過ioctl函數設定要訪問從設備的地址,然後就可以通過read和write函數完成對I2C設備的讀寫操作。
通過I2Cdriver提供的通用方法可以訪問任何一個I2C的設備,但是其中實現的read,write及ioctl等功能完全是基於一般設備的實現,所有的操作數據都是基於位元組流,沒有明確的格式和意義。為了更方便和有效地使用I2C設備,我們可以為一個具體的I2C設備開發特定的I2C設備驅動程序,在驅動中完成對特定的數據格式的解釋以及實現一些專用的功能。
㈤ 在linux上怎樣增加一個i2c設備
假設手上有一塊從淘寶上買來的開發板,我要在開發板的I2C匯流排上增加一個從設備(如at24c08),那麼我要怎樣寫這個「I2C設備驅動」,讓
應用程序可以訪問at24c08呢?
先來看一個最簡單的i2c設備驅動:
static struct i2c_board_info at24cxx_info = { //所支持的i2c設備的列表
I2C_BOARD_INFO("at24c08", 0x50), //一項代表一個支持的設備,它的名字叫做「at24c08」,器件地址是0x50
};
static struct i2c_client *at24cxx_client;
static int at24cxx_dev_init(void)
{
struct i2c_adapter *i2c_adap; //分配一個適配器的指針
i2c_adap = i2c_get_adapter(0); //調用core層的函數,獲得一個i2c匯流排。這里我們已經知道新增的器件掛接在編號為0的i2c匯流排上
at24cxx_client = i2c_new_device(i2c_adap, &at24cxx_info); // 把i2c適配器和新增的I2C器件關聯起來,這個用了i2c匯流排0,地址是0x50。這就組成了一個客戶端
at24cxx_client i2c_put_adapter(i2c_adap);
return 0;
}
static void at24cxx_dev_exit(void)
{
i2c_unregister_device(at24cxx_client);
}
mole_init(at24cxx_dev_init);
mole_exit(at24cxx_dev_exit);
從上面的程序可以看到,寫一個i2c設備驅動程序,與寫普通的字元驅動基本一樣。特別之處是它調用了i2c的core層的函數,以獲得對i2c匯流排的控制。因為用的是開發板,板上的與soc晶元(一般來說就是arm的晶元)i2c匯流排驅動一般都做好了,直接調用core層的函數就可以控制soc的i2c模塊了。也就是說,寫i2c設備驅動不需要關注arm內部的i2c模塊的寄存器,我們需要關注的是設備(at24c08)的寄存器以及它的datasheet對時序的要求。
其實,添加i2c設備的方法很靈活。根據Linux的官方文檔《linux-3.4.2\Documentation\i2c\instantiating-devices》,添加i2c設備的方法總結有4種:
1. i2c_register_board_info:根據匯流排編號、設備名字(「at24c08」)、設備地址(0x50)注冊一個字元驅動。這種方法最簡單、最粗暴,最貼近平時在開片機上開發i2c器件的。
2. i2c_new_device:根據i2c匯流排的編號,聲明一個i2c設備:這種方法就是上面例子用的方法。這種方法也簡單,但是需要事先知道器件掛接在哪條匯流排上。對於設備,還實現知道了設備地址0x50,匯流排適配器也支持名字為「at24c08」的設備
3. i2c_new_probed_device:
4.從用戶空間實例化一個器件:這個方法相當智能快速,如下輸入指令,即可增加一個i2c設備,同時增加了對應的設備文件。
# echo eeprom 0x50 > /sys/bus/i2c/devices/i2c-3/new_device
根據英文文檔的標題,添加i2c設備有稱之為「i2c設備的實例化」。
從上述可以知道,在實例化一個i2c設備之前,除了有對應的驅動支持匯流排外(這里是匯流排0),還需要有一個驅動使用了匯流排0發送時序,支持名字為"at24c08"的器件。這個驅動用匯流排驅動的函數,配置了at24c08的寄存器。