在linux驅動中i2c系統中主要包含以下幾個成員:
i2c adapter 即i2c介面卡
i2c driver 某個i2c裝置的裝置驅動,可以以driver理解。
i2c client 某個i2c裝置的裝置宣告,可以以device理解。
是cpu整合或外接的i2c介面卡,用來控制各種i2c從裝置,其驅動需要完成對介面卡的完整描述,最主要的工作是需要完成i2c_algorithm結構體。這個結構體包含了此i2c控制器的資料傳輸具體實現,以及對外上報此裝置所支援的功能型別。i2c_algorithm結構體如下:
struct i2c_algorithm ;
如果乙個i2c介面卡不支援i2c通道,那麼就將master_xfer成員設為null。如果介面卡支援smbus協議,那麼需要去實現smbus_xfer,如果smbus_xfer指標被設為null,那麼當使用smbus協議的時候將會通過i2c通道進行**。master_xfer指向的函式的返回值應該是已經成功處理的訊息數,或者返回負數表示出錯了。functionality指標很簡單,告訴詢問著這個i2c主控器都支援什麼功能。
在核心的drivers/i2c/i2c-stub.c中實現了乙個i2c adapter的例子,其中實現的是更為複雜的smbus。
smbus 與 i2c的區別
通常情況下,i2c和smbus是相容的,但是還是有些微妙的區別的。
時鐘速度對比:
i2csmbus最小無
10khz
最大100khz(標準)400khz(快速模式)2mhz(高速模式)
100khz超時無
35ms
在電氣特性上他們也有所不同,smbus要求的電壓範圍更低。
具體的i2c裝置驅動,如相機、感測器、觸控螢幕、背光控制器常見硬體裝置大多都有或都是通過i2c協議與主機進行資料傳輸、控制。結構體如下:
struct i2c_driver ;
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) //一般編寫驅動過程中物件常是driver型別,可以通過to_i2c_driver找到其父型別i2c_driver
如同普通裝置的驅動能夠驅動多個裝置一樣,乙個i2c driver也可以對應多個i2c client。
以重力感測器axll34x為例,其實現的i2c驅動為:
static const struct i2c_device_id adxl34x_id = , //匹配i2c client名為adxl34x的裝置
}; module_device_table(i2c, adxl34x_id);
static struct i2c_driver adxl34x_driver = ,
.probe = adxl34x_i2c_probe, //組裝裝置匹配時候的匹配動作
.remove = adxl34x_i2c_remove, //組裝裝置移除介面
.id_table = adxl34x_id, //制定匹配裝置列表
}; module_i2c_driver(adxl34x_driver);
這裡要說明一下module_i2c_driver巨集定義(i2c.h):
#define module_i2c_driver(__i2c_driver) \
module_driver(__i2c_driver, i2c_add_driver, \
i2c_del_driver)
#define i2c_add_driver(driver) \
i2c_register_driver(this_module, driver)
module_driver():
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
\module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
\module_exit(__driver##_exit);
理解上述巨集定義後,將module_i2c_driver(adxl34x_driver)展開就可以得到:
static int __int adxl34x_driver_init(void)
module_init(adxl34x_driver_init);
static void __exit adxl34x_driver_exit(void)
module_exit(adxl34x_driver_exit);
這一句巨集就解決了模組module安裝解除安裝的複雜**。這樣驅動開發者在實現i2c驅動時只要將i2c_driver結構體填充進來就可以了,無需關心裝置的註冊與反註冊過程。
即i2c裝置。i2c裝置的註冊一般在板級**中,在解析例項前還是先熟悉幾個定義:
struct i2c_client ;
#define to_i2c_client(d) container_of(d, struct i2c_client, dev) //通常使用device裝置模型進行操作,可以通過to_i2c_client找到對應client指標
struct i2c_board_info ;
//可以看到,i2c_board_info基本是與i2c_client對應的。
#define i2c_board_info(dev_type, dev_addr) \
.type = dev_type, .addr = (dev_addr)
//通過這個巨集定義可以方便的定義i2c裝置的名稱和從位址(別忘了是7bit的)
下面還是以adxl34x為例:
static struct i2c_board_info i2c0_devices = ,
, ,
, };...
i2c_register_board_info(0, i2c0_devices, array_size(i2c0_devices));
這樣adxl34x的i2c裝置就被註冊到了系統中,當名字與i2c_driver中的id_table中的成員匹配時就能夠出發probe匹配函式了。 Linux I2C裝置驅動學習
一 i2c 簡介 1 i2c簡介 a 優點 i2c匯流排僅用兩根訊號線 scl sda 就實現了裝置之間的資料互動,極大簡化了對硬體資源和pcb板佈線空間的占用 b 用途 eeprom 實時鐘 小型lcd等裝置與cpu的介面中 2 i2c驅動體系 i2c框架 通用 適應性強 i2c核心 i2c匯流排...
linux I2C裝置驅動例項 EEPROM
開發板 優龍公司的fs2410 核心版本 linux2.6.28.6 開發環境 ubuntu12.04 交叉編譯器 arm none linux gnueabi gcc 4.3.2 目標 在fs2410上驅動eeprom,實現應用層對eeprom的讀寫操作 一 linux2.6.28.6 系統上 i...
LinuxI2C核心 匯流排驅動與裝置驅動
i2c體系結構分為三個部分 i2c核心 匯流排驅動 裝置驅動 i2c核心 i2c核心提供了一組不依賴硬體的介面函式,i2c匯流排驅動和裝置驅動之間依賴於i2c核心作為紐帶 1 增加 刪除i2c adapter int i2c add adapter struct i2c adapter adap i...