網上介紹i2c總線的資料比較多,對於i2c基礎這裏就不細談了。對於初入門的linux驅動工程師還是有些困難,此文章主要介紹了i2c子系統的數據處理流程,以及編寫過程。相對於其他參考,該文檔減少了長篇文字(枯燥),以圖文和源代碼的方式來進行介紹。好了廢話不多說,讓我們一起進入正文,下面是參考一些網上大神的資料,以及自己的分析方式:
一、linux i2c驅動框架:
對linux驅動框架分析時,框架 ——》 結構體 ——》 框架 ——》源代碼分析;
目前多數主控芯片都含有i2c控制器,因此驅動開發工程師編寫驅動時需要將對應的gpio接口配置成i2c功能無需過分關注時鐘,只需要按照芯片要求的格式進行讀寫操 作,linux 中i2c驅動也提供了具體的讀寫接口;(是不是感覺i2c驅動簡單很多了^_^)
二、 i2c驅動編寫
經過以上分析可以得知linux i2c驅動需要 驅動開發工程師實現 i2c-driver 和 i2c-client;
1、 需要再開發板的扳文件中(board-xxx.c)中 i2c_board_info中添加相應的硬件信息,然後內核會幫你註冊一個i2c_device設備;
例:static struct i2c_board_info i2c_info[] = {
{
I2C_BOARD_INFO("dm365evm_keys", 0x25), //0x25,0x50,0x18均爲i2c從設備地址一般爲8位,不帶讀寫標識
},
{
I2C_BOARD_INFO("24c256", 0x50),
.platform_data= &eeprom_info,
},
{
I2C_BOARD_INFO("tlv320aic3x", 0x18),
},
};
i2c_board_info主要用於構建信息表來列出存在的i2c設備,用於增長i2c驅動模塊的驅動樹,對於主板,會調用i2c_new_device()創建client設備
2、其中i2c-driver中主要是 i2c_driver 註冊,註銷,以及 file_operations函數的實現。
3、i2c驅動中最重要的爲次設備的讀寫操作:(引用http://blog.csdn.net/zclongembedded/article/details/8255977)
i2c-core.c中提供了 i2c_master_send i2c_master_recv 和 i2c_transfer 接口與i2c從設備進行數據交互,最好對i2c_transfer進行封裝使用,以提高代碼移植性,通用性;
以上三個函數本身不具備驅動物理硬件完成消息傳遞的功能,它只是尋找i2c_adapter對應的i2c_algorithm,並使用i2c_algorithm的master_xfer()函數真正驅動硬件函數; (http://tscsh.blog.163.com/blog/static/2003201032013519111134879/)
static ssize_t yyy_write(struct file* file,char * buf,size_t count,loff_t off) 調用過程:
{
struct i2c_client* client = (struct i2c_client*)file->private_data; app: write
i2c_msg msg[1]; ↓
char* tmp = kmalloc(count,GFP_KERNEL); i2c設備驅動文件接口 xxx_write()
int ret; ↓
if(NULL == tmp) i2c核心 i2c_transfer()
return -ENOMEM; ↓
if(copy_from_user(tmp,buf,count)) i2c總線驅動 master_xfer()
{
kfree(tmp);
return -EFAULT;
}
msg[0].addr = client->addr; //地址
msg[0].flags=0; //寫
msg[0].len = count; //要寫的字節
msg[0].buf = tmp; // 要寫的數據
ret = i2c_transfer(client->adapter,msg,1);
return (1 == ret)? count: ret;
}
注:i2c寫設備經歷過程 1)在字符設備驅動中構造i2c_msg; 2)調用i2c_transfer將i2c_msg傳送給i2c核心;3)i2c_transfer找到對應的algorithm通信方法函數 master_xfer 最終完成i2c_msg消息的處理
對內容有異議者希望不吝指教;