linux核心I2C子系統學習(一)

2021-06-18 13:49:35 字數 3740 閱讀 3543

這部分準備分幾個部分進行分析總結

因為i2c的通訊肯定至少要有2個晶元完成,所以它的驅動是由2大部分組成:

主晶元的i2c的驅動

從晶元的i2c的驅動

注:萬一選的都不支援咋辦???(慘了,只能2個晶元的驅動都得實現了,不過過程差不多)

(一).主晶元的i2c的驅動:(具體如何實現在後面在具體講解)

首先要檢視linux核心是否支援主晶元中i2c驅動器,如果支援就配置一下就ok了,否則要編寫主控晶元的i2c驅動器

編寫方法:

第一.要有i2c匯流排驅動(首先要查查核心i2c檔案是否支援這種匯流排驅動,一般都有支援,如果沒有只好自己倒霉自己寫了)

第二.i2c裝置驅動(主控晶元的位址等等資訊)

這個過程都是差不多的,以後在分析。

一般的主控晶元的i2c控制器linux核心基本上支援的很好,如:2410的i2c驅動器的支援

(二).從晶元的i2c的驅動:

下面主要分析從晶元的i2c驅動(也有2種方式,第乙個是利用核心提供的i2c-dev.c來構建,另乙個是自己寫)

主要分析第一種方式:

利用系統給我們提供的i2c-dev.c來實現乙個i2c介面卡的裝置檔案。然後通過在應用層操作i2c介面卡來控制i2c裝置。

i2c-dev.c並沒有針對特定的裝置而設計,只是提供了通用的read()、write()ioctl()等介面,應用層可以借用這些介面訪問掛接在介面卡上的i2c裝置的儲存空間或暫存器,並控制i2c裝置的工作方式。但是readwrite方法適用性有限。

所以用ioctl方法來操作:

一般都不會使用i2c-dev.c的read()、write()方法。最常用的是ioctl()方法。ioctl()方法可以實現上面所有的情況(兩種資料格式、以及i2c演算法和smbus演算法)。

針對i2c的演算法,需要熟悉

struct i2c_rdwr_ioctl_data 、struct i2c_msg。使用的命令是i2c_rdwr。

struct i2c_rdwr_ioctl_data 

;struct i2c_msg ;

針對smbus演算法,需要熟悉struct i2c_smbus_ioctl_data。使用的命令是i2c_smbus。對於smbus演算法,不需要考慮「多開始訊號時序」問題。

struct i2c_smbus_ioctl_data ;

首先在核心中已經包含了對s3c2410 中的i2c控制器(匯流排驅動)驅動的支援。提供了i2c演算法(非smbus型別的,所以後面的ioctl的命令是i2c_rdwr)

static const struct i2c_algorithm s3c24xx_i2c_algorithm = ;

另外一方面需要確定為了實現對at24c02 e2prom的操作,需要確定從機晶元的位址及讀寫訪問時序。

在網上找了個例子:

具體分析如下:

#include #include #include #include #include #include #include #include #define i2c_retries 0x0701

#define i2c_timeout 0x0702

#define i2c_rdwr 0x0707

/*********定義struct i2c_rdwr_ioctl_datastruct i2c_msg,要核心一致。兩個重要的結構體*******/

struct i2c_msg

;struct i2c_rdwr_ioctl_data

;int main()

e2prom_data.nmsgs=2;

/**因為操作時序中,最多是用到2個開始訊號(位元組讀操作中),所以此將

*e2prom_data.nmsgs配置為2

*/e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));

if(!e2prom_data.msgs)

ioctl(fd,i2c_timeout,1);/*超時時間*/

ioctl(fd,i2c_retries,2);/*重複次數*/

/***write data to e2prom**/

/**/

e2prom_data.nmsgs=1;

(e2prom_data.msgs[0]).len=2; //1個 e2prom 寫入目標的位址1個資料

(e2prom_data.msgs[0]).addr=0x50;//e2prom 裝置位址

(e2prom_data.msgs[0]).flags=0; //write

(e2prom_data.msgs[0]).buf=(unsigned char*)malloc(2);

(e2prom_data.msgs[0]).buf[0]=0x10;// e2prom 寫入目標的位址

(e2prom_data.msgs[0]).buf[1]=0x58;//the data to write

ret=ioctl(fd,i2c_rdwr,(unsigned long)&e2prom_data);

if(ret<0)

sleep(1);

/******read data from e2prom*******/

e2prom_data.nmsgs=2;

(e2prom_data.msgs[0]).len=1; //e2prom 目標資料的位址

(e2prom_data.msgs[0]).addr=0x50; // e2prom 裝置位址

(e2prom_data.msgs[0]).flags=0;//write

(e2prom_data.msgs[0]).buf[0]=0x10;//e2prom資料位址

(e2prom_data.msgs[1]).len=1;//讀出的資料

(e2prom_data.msgs[1]).addr=0x50;// e2prom 裝置位址

(e2prom_data.msgs[1]).flags=i2c_m_rd;//read

(e2prom_data.msgs[1]).buf=(unsigned char*)malloc(1);//存放返回值的位址。

(e2prom_data.msgs[1]).buf[0]=0;//初始化讀緩衝

ret=ioctl(fd,i2c_rdwr,(unsigned long)&e2prom_data);

if(ret<0)

printf("buff[0]=%x/n",(e2prom_data.msgs[1]).buf[0]);

close(fd);

i2c_put_adapter(client->adapter);釋放i2c匯流排

return 0;

}

以上講述了一種比較常用的利用i2c-dev.c操作i2c裝置的方法,這種方法可以說是在應用層完成了對具體i2c裝置的驅動工作。

接下來準備具體分析如何寫第一部分!

linux驅動開發擴充套件 i2c子系統核心部分分析

drivers i2c i2c core.c postcore initcall i2c init module exit i2c exit static int init i2c init void endif retval i2c add driver dummy driver 為i2c匯流排新...

對i2c子系統的理解

驅動i2c控制器歸根到底是對iic控制器的暫存器進行讀寫,因此,理解了linux中是怎樣通過層層呼叫來操作iic的暫存器,便理解了整個iic子系統的輪廓。下面以公司使用的重力感測器 bma250 驅動為例來描述這個輪廓。首先介紹三個比較重要的驅動檔案 bma250.c drivers gsensor...

Linux驅動程式設計 基於I2C子系統的I2C驅動

中,我新增了很多注釋,應該不難理解,有錯誤大家可以指出來,我再改正 include include include include include include include define i2c major 365 主裝置號 define i2c minor 0 從裝置號 define i2c...