linux下IIC驅動開發分析(3)

2021-06-19 19:31:07 字數 4117 閱讀 1430

在系統開機時,首先裝載的是

i2c匯流排驅動。乙個匯流排驅動用於支援一條特定的

i2c匯流排的讀寫。乙個匯流排驅動通常需要兩個模組,乙個

struct i2c_adapter

和乙個struct i2c_algorithm

來描述:

static struct

i2c_adapter

pb1550_board_adapter =;

這個樣例掛接了乙個叫做

「pb1550 adapter」

的驅動。但這個模組並未提供讀寫函式,具體的讀寫方法由第二個模組,

struct i2c_algorithm

提供。

static struct

i2c_algorithm

au1550_algo =

;i2c_adap->algo = &au1550_algo;

這個樣例給上述匯流排驅動增加了讀寫「演算法

」。通常情況下每個

i2c匯流排驅動都定義乙個自己的讀寫演算法,但鑑於有些匯流排使用相同的演算法,因而可以共用同一套讀寫函式。本例中的驅動定義了自己的讀寫演算法模組,起名叫

「au1550 algorithm」。

全部填妥後,通過呼叫:

i2c_add_adapter(i2c_adap);

將這兩個模組註冊到作業系統裡,匯流排驅動就算裝上了。對於

amd au1550

,這部分已經由

amd提供了。

i2c的裝置驅動是通過

i2c_add_driver(&my_driver)

向i2c-core

註冊的,

my_driver

中的核心是

detach_client 

和attach_adapter

函式,在

attach_adapter

中通過probe

探測到匯流排上的裝置並把裝置和驅動建立連線以完成裝置的初始化。

裝置驅動透過

i2c匯流排同具體的裝置進行通訊。乙個裝置驅動有兩個模組來描述,

struct i2c_driver

和struct i2c_client。

當系統開機、

i2c匯流排驅動裝入完成後,就可以裝入裝置驅動了。首先裝入如下結構:

static struct i2c_driver zlg7290_driver = ;

i2c_add_driver(&zlg7290_driver);

這個i2c_driver

一旦裝入完成,其中的

attach_adapter

函式就會被呼叫。

如何探測匯流排上的裝置、

linux

中i2c

裝置位址如何標識並引用?

i2c中,

典型的attach_adapter

如下所示:

static int my_attach(struct i2c_adapter *adapter)

static int

zlg7290_detect

(struct i2c_adapter *adapter, int address, int kind)

3.2.2.1

iic裝置探測

注意探測可能會找到多個裝置,因而不僅乙個

i2c匯流排可以掛多個不同型別的裝置,乙個裝置驅動也可以同時為掛在多個不同

i2c匯流排上的裝置服務。

每當裝置驅動探測到了乙個它能支援的裝置,它就建立乙個

struct i2c_client

來標識這個裝置:

struct i2c_client *new_client;

…… new_client->addr = address;

new_client->adapter = adapter;

new_client->driver = &zlg7290_driver;

new_client->flags = 0;

strlcpy(new_client->name, dev_name, i2c_name_size);

if ((err =

i2c_attach_client

(new_client)))

可見,乙個

i2c_client

代表著位於

adapter

匯流排上,位址為

address

,使用zlg7290_driver

來驅動的乙個裝置。它將匯流排驅動與裝置驅動,以及裝置位址繫結在了一起。乙個

i2c_client

就代表著乙個

i2c裝置。

當得到i2c裝置後,就可以直接對此裝置進行讀寫:

extern int i2c_master_send(struct i2c_client *,const char* ,int);

extern int i2c_master_recv(struct i2c_client *,char* ,int);

3.2.2.2

linux

下iic

裝置位址

addr_data

是在

include/linux/i2c.h

中定義的或自己在自己驅動程式中定義的乙個

i2c_client_address_data

結構:

static struct i2c_client_address_data addr_data =

若自己不定義,則用

i2c.h

中的預設定義。

struct i2c_client_address_data ;

根據作者自行定義裝置位址與否,有兩種情形:

a.採用預設定義,一般是不會

work,

畢竟大多數

i2c-core

中是不可能提前知道所接裝置位址的,這樣通過

i2c_probe()

探測肯定不可能找到,也不可能建立兩者之間的聯絡;況且,

i2c_probe()

屬於i2c-core

中的函式,

i2c-core

中管理著所有註冊過的裝置和驅動列表,

i2c_probe()

中也不能隨意傳入位址,否則容易導致系統混亂或有潛在的風險,所以

i2c-core

也不允許這麼做!

b.作者自行定義位址結構

典型例子如下:

若自行定義,則參考如下:

static unsigned short normal_i2c = ;///

實際裝置的位址

list

static unsigned short probe[2] = 

;static unsigned short ignore[2] =  

;static struct i2c_client_address_data addr_data = ;

或者根本就不定義完整的

i2c_client_address_data

結構,只根據需要定義

normal_i2c,probe,ignore

,forces,

然後呼叫

i2c_probe(adapter,&addr_data,

&my_probe)

即可。

在my_probe()

中把實際的位址賦於

i2c_client

,呼叫i2c_set_clientdata()

設定i2c_client->dev->drv_data,

並呼叫i2c_attach_client(client)

向系統註冊裝置。

最後,i2c_probe()

中探測時的位址優先順序:

forces, probe, normal_i2c(

其中忽略

ignore

中的項)。

i2c裝置在實際使用中比較廣泛,

sensor,rtc,audio, codec,etc.

因裝置複雜性不同,

linux

中有些驅動中對位址的定義不在同一檔案,這時多數情況都在

arch

中對裝置作為

platform_device

進行初始化並註冊的**中。

九 IIC驅動原理分析

學習目標 學習iic驅動原理 一 iic匯流排協議 iic序列匯流排包括一條資料線 sda 和一條時鐘線 scl 支援 一主多從 和 多主機 模式 每個從機裝置都有唯一的位址來識別。圖 1 iic 主從結構 二 iic訊號和時序 iic匯流排有3種型別訊號 1 開始訊號s scl為高電平,sda由高...

IIC驅動程式分析(一)

根據上一節課的分析,我們來解讀這段 include include include include include include include static unsigned short ignore static unsigned short normal addr 位址值是7位 static...

IIC驅動程式分析(二)

在上一節的實驗中,我們採用的是normal i2c 的方式,即 要發出s訊號和裝置位址並得到ack訊號,才能確定存在這個裝置。那麼如果本身不存在這個裝置當然啊不會給出應答訊號,這是就不會呼叫i2c probe adapter,addr data,at24cxx detect 函式中的at24cxx ...