1、iic匯流排:
struct bus_type i2c_bus_type = ;
呼叫位置iic-core.c:
i2c_init(void)
retval = bus_register(&i2c_bus_type);
iic裝置模型:
i2c_new_device(i2c_client結構體)
i2c_register_adapter(i2c_adapter結構體)
iic驅動模型:
i2c_register_driver(i2c_driver結構體)
前兩者是裝置模型,後乙個是驅動模型。
2、i2c_register_adapter是介面卡,對應我們開發板的iic控制器:
adap->dev.bus = &i2c_bus_type;
adap->dev.type = &i2c_adapter_type;
而i2c_new_device是我們的iic裝置了,如iic晶元:
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;
最後i2c_register_driver是我們的iic驅動,一般由i2c_add_driver進行包裝,使用的結構體是i2c_driver,這個主要用來實現iic協議。
3、現在我們來看框架:
i2c_register_driver驅動註冊過程:
static struct i2c_driver at24_driver = ,
.probe = at24_probe,
.remove = __devexit_p(at24_remove),
.id_table = at24_ids,};
然後通過i2c_add_driver(&at24_driver)註冊:
i2c_register_driver
res = driver_register(&driver->driver); //掛到iic匯流排驅動鏈表,從iic裝置鍊錶進行匹配,注意這裡只針對iic裝置,對iic介面卡沒有用,這點看iic匯流排匹配函式就知道。匹配成功的話,呼叫驅動probe函式,由於當前沒有iic裝置,所以不會呼叫。
2、iic裝置註冊過程:
首先是介面卡,因為介面卡是iic控制器,是核心所在。注意介面卡有編號的adapter->nr,iic裝置是根據編號來掛到介面卡的。
這部分是通過平台匯流排模型來實現的,所以這部分是驅動工程師負責的地方,具體如下:
平台裝置:
static struct resource s3c_i2c_resource = ,
[1] = ,
};struct platform_device s3c_device_i2c1 = ;
而平台驅動:
static struct platform_driver s3c24xx_i2c_driver = ,};
這樣以匹配就呼叫s3c24xx_i2c_probe函式:
s3c24xx_i2c_probe函式任務:
1、設定s3c24xx_i2c結構體:
i2c->adap.algo = &s3c24xx_i2c_algorithm; //底層操作函式,主要包括傳輸函式等。
獲取硬體資訊填充結構體,註冊中斷
platform_set_drvdata(pdev, i2c);
2、ret = i2c_add_numbered_adapter(&i2c->adap);
//通過i2c_register_adapter註冊介面卡,
注意i2c_add_numbered_adapter裡的i2c_scan_static_board_info函式,這個函式回去__i2c_board_list鍊錶找是否有iic裝置使用了本介面卡,如果有要掛到本介面卡,而該鍊錶是通過i2c_register_board_info函式來實現的!所以對於iic裝置的註冊有多種方式,一種直接i2c_new_device,一種就是這種情況,通過i2c_register_board_info函式實現,不過還有其他方式,這裡就略去。再者i2c_add_numbered_adapter會呼叫device_register進而和iic匯流排驅動匹配,不過不會匹配成功的,原因如下:
i2c_device_match
i2c_verify_client(dev);
(dev->type == &i2c_client_type)? to_i2c_client(dev): null; //介面卡dev->type =i2c_adapter_type,返回null,不進行匹配!!
接著就是iic裝置註冊,針對於iic晶元之類的:
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
1、設定struct i2c_client*client;結構體
client->adapter = adap; //介面卡
client->addr = info->addr;//位址
status = i2c_check_client_addr_validity(client); //檢查位址是否有效,手段:發乙個開始訊號看看對方是否回應
strlcpy(client->name, info->type, sizeof(client->name)); //裝置名字
status = device_register(&client->dev); 這個就重要啦,又來匹配了,並且iic驅動前面已經有了,所以匹配成功,呼叫驅動的probe函式!
2、要先填充i2c_board_info結構體,然後實現第1的賦值。
現在看看驅動的probe函式:
at24_probe:
1、struct at24_data *at24設定
at24->bin.read = at24_bin_read; //最終將會呼叫底層的讀函式
at24->bin.write = at24_bin_write;
err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); //通過建立檔案實現讀寫,這個例子比較特殊,我們可以實現為file_operation來讀寫(建立裝置檔案)。
i2c_set_clientdata(client, at24); //at24放到clien結構體裡的私有資料。
到這裡就ok了。
總結一下:
iic介面卡註冊:
介面卡對應於我們的iic控制器,通過平台匯流排實現的,主要就是硬體相關的操作,尤其是底層的讀寫操作之類的,這些操作供給iic驅動層的操作函式呼叫。
iic的裝置註冊:
strlcpy(info.type, "wm8990", i2c_name_size); //設定i2c_board_info
adapter = i2c_get_adapter(setup->i2c_bus); //這點說明介面卡必須先註冊,裝置是掛在介面卡上
client = i2c_new_device(adapter, &info); //註冊裝置,掛到介面卡,匹配iic匯流排的驅動,如果存在呼叫驅動probe
i2c_put_adapter(adapter)
iic驅動註冊:
static int __init at24_init(void)
實現了協議層的操作:
static ssize_t at24_read(struct at24_data *at24,
char *buf, loff_t off, size_t count)
static ssize_t at24_write(struct at24_data *at24, const char *buf, loff_t off,
size_t count)
這些操作基底要靠介面卡的底層來實現傳輸
最後一點:裝置節點也是交給驅動層來實現
工作流程:
1、iic驅動和iic裝置匹配,獲取裝置位址和名字等;
2、操作裝置節點從iic驅動函式集開始,這些最終要依靠介面卡的底層操作來支撐完成!!
iic裝置層:位址和名字等
iic驅動層:iic協議
iic介面卡層:底層實現
iic匯流排從機仲裁 IIC學習筆記
iic inter integrated circuit 積體電路匯流排 iic通訊協議是飛利浦公司於80年代初發明的一種運用於晶元與晶元之間進行資訊交換的序列 同步 半雙工通訊協議。應用場合 晶元與晶元之間。板間通訊。共模通訊。抗干擾能力很差。1 iic協議有兩根匯流排 時鐘匯流排sck,資料匯流...
多從器件的IIC匯流排除錯心得
畫了個sheild板子掛滿了各種iic sensor器件和感測器模組,結果發現調起來並不容易。上拉恢復波形不好,其實跟上拉電阻關係不大,下面這個波形,我即使把上拉電阻改小到1k到330r都很難糾正好,最後發現原因是匯流排上有其他iic器件的vcc供電沒有給上。導致clk dat引腳的上拉充電恢復電流...
iic匯流排從機仲裁 I2C匯流排的仲裁機制
在多主的通訊系統中。匯流排上有多個節點,它們都有自己的定址位址,可以作為從節點被別的節點訪問,同時它們都可以作為主節點向其他的節點傳送控制位元組和傳 送資料。但是如果有兩個或兩個以上的節點都向匯流排上傳送啟動訊號並開始傳送資料,這樣就形成了衝突。要解決這種衝突,就要進行仲裁的判決,這就是i 2c匯流...