linux 下i2c读写命令,S3C2440 Linux下的I2C驱动以及I2C体系下对EEPROM进行读写操作
成員。我們可以看到消息結構體里面有從設備地址,讀寫標志,數據長度以及存儲數據buf。這些成員我們看完之后會發現它大致符合先給設備地址,然后給寫信號以及數據的時序。其實但我們寫代碼的時候并不一定是addr非得定義在flags前面,因為內核會自動幫助我們完成這些具體的時序操作。但有一點,我們必須要填充好nmsgs以及i2c_msg中的成員。
那么我們具體的i2c下的?ioctl?函數是怎么樣的呢?我們暫且把i2c-dev.c看作一個設備驅動。里面的fops結構體顯示
我們繼續追蹤看看i2cdev_ioctl這個函數
static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = file->private_data;
unsigned long funcs;
dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n",
cmd, arg);
switch (cmd) {
case I2C_SLAVE:
case I2C_SLAVE_FORCE:
/* NOTE: ?devices set up to work with "new style" drivers
* can't use I2C_SLAVE, even when the device node is not
* bound to a driver. ?Only I2C_SLAVE_FORCE will work.
*
* Setting the PEC flag here won't affect kernel drivers,
* which will be using the i2c_client node registered with
* the driver model core. ?Likewise, when that client has
* the PEC flag already set, the i2c-dev driver won't see
* (or use) this setting.
*/
if ((arg > 0x3ff) "|
(((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
return -EINVAL;
if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg))
return -EBUSY;
/* REVISIT: address could become busy later */
client->addr = arg; //設置addr
return 0;
case I2C_TENBIT://設置10 bit地址模式
if (arg)
client->flags |= I2C_M_TEN;
else
client->flags &= ~I2C_M_TEN;
return 0;
case I2C_PEC://設置傳輸后增加PEC標志
if (arg)
client->flags |= I2C_CLIENT_PEC;
else
client->flags &= ~I2C_CLIENT_PEC;
return 0;
case I2C_FUNCS://獲取函數支持
funcs = i2c_get_functionality(client->adapter);
return put_user(funcs, (unsigned long __user *)arg);
case I2C_RDWR://讀取和發送數據
return i2cdev_ioctl_rdrw(client, arg);
case I2C_SMBUS: //SMBUS協議數據傳輸
return i2cdev_ioctl_smbus(client, arg);
case I2C_RETRIES://設置重試次數
client->adapter->retries = arg;
break;
case I2C_TIMEOUT://設置超時時間
/* For historical reasons, user-space sets the timeout
* value in units of 10 ms.
*/
client->adapter->timeout = msecs_to_jiffies(arg * 10);
break;
default:
/* NOTE: ?returning a fault code here could cause trouble
* in buggy userspace code. ?Some old kernel bugs returned
* zero in this case, and userspace code might accidentally
* have depended on that bug.
*/
return -ENOTTY;
}
return 0;
}
對于簡單使用來說,我現在并沒有全深入整明白,所以暫且知道:
ioctl是設備驅動程序中對設備的I/O通道進行管理的函數。
在驅動程序中實現的ioctl函數體內,實際上是有一個switch{case}的結構,每一個case對應一個cmd操作命令,并有相對應的操作。
我這里cmd參數使用的是I2C_RDWR這個命令碼,根據i2c-dev.c里的源碼看i2cdev_ioctl_rdrw結構體可知
I2C 設備的寫操作經歷了如下幾個步驟。
(1) 從用戶空間到字符設備驅動寫函數接口,寫函數構造 I2C 消息數組。
(2) 寫函數把構造的 I2C 消息數組傳遞給 I2C 核心的傳輸函數 i2c_transfer()。
(3) I2C 核心的傳輸函數 i2c_transfer()找到對應適配器 algorithm 的通信方法函數 master_xfer()去最終完成 I2C 消息的處理。
PS:I2c_transfer這個函數實現了core與adapter的聯系。想更深入的探究,可以自己去看看I2C總線驅動中的I2C_algorithm結構以及其中的s3c24xx_i2c_xfer(),s3c24xx_i2c_doxfer()和s3c24xx_i2c_message_start()函數和i2c_transfer()函數。
下面我們看看代碼在開發板中運行的現象:
1.在把可執行文件放入開發板啟動之前我們先檢查下I2C控制器s3c2410-i2c節點是否配置好。
上面的i2c_dev/i2c-0是在注冊i2c-dev.c后產生的,代表一個可操作的適配器。如果不使用i2c-dev.c的方式,就沒有,也不需要這個節點。
2.確保出現I2C控制器s3c2410-i2c后即可通過交叉編譯器將編譯后可執行文件放入開發板中執行。
仔細看上面的結果。可以看到我們原本的數據test1234\n在上面的顯示中出了點問題。后來我又測試一次test123\n與test12345678
我第一次是通過at24.c的read和write以及lseek直接對eeprom讀寫,所以可以一次寫入超過8個字節,第二次通過內部i2c控制器的ioctl來間接讀寫eeprom時則遭遇了阻擊,一次時序,若超過8個字節,超過的字節數自動將前面的數據覆蓋掉。然后我想到at24c02是32個頁,一頁8個字節。通過網上查閱知:
===================================================================================================
================================================================================================================================
由于E2PROM的半導體工藝特性,對E2PROM的寫入時間要5~10ms,但AT24CXX系列串行E2PROM芯片內部設置了一個具有SRAM性質的輸入緩沖器,稱為頁寫緩沖器。CPU對該芯片寫操作時,AT24CXX系列芯片先將CPU輸入的數據暫存頁寫緩沖器內,然后,慢慢寫入E2PROM中。因此,CPU對AT24CXX系列E2PROM一次寫入的數據,受到該芯片頁寫緩沖器容量的限制。頁寫緩沖器的容量:AT24C01A/02為8B,AT24C04/08/16為16B,AT24C32/64為32B。
====================================================================================================
注意:
寫AT24CXX應用時,若CPU需寫入超過芯片頁寫緩沖器容量的字節數據,應在一頁寫完后,隔5~10ms重新啟動一次寫操作。其次,若不是從頁寫緩沖器零地址(指AT24CXX片內末位地址0或8)寫起,一次寫入不能超出頁內地址111,若超出頁寫緩沖器最大地址時,也應將超出部分,隔5~10ms重新啟動一次寫操作。
最后通我們回顧AT24C02的官方datasheet來看看本質:
Byte write:
==================================================================================================================
Byte write的操作時序如上圖所示。主機在發送device address,并且接受到確定回應Ask后再接著發送需要寫的地址(把這個數據寫到芯片的哪個地址上),然后收到確定回應ask后再發送數據。當AT24C02接受完畢這個數據時會輸出一個確認回應Ack,此時主機發送一個停止信號Stop,然后AT240C2進入寫時序,將剛才接受到的數據從緩沖器寫到存儲單元中,并在此期間不響應任何輸入,直到操作完成。
==================================================================================================================
Pagewrite:
==================================================================================================================
Page write前面幾步的操作和Bytewrite操作類似,只是在成功發送第一個數據之后,主機在收到AT24C02的確認回應Ask之后不會發送停止信號Stop而是繼續發送剩余的7個字節數據。直到一個page的8字節數據發送完畢之后才發送停止信號Stop。在頁操作的時候word address用與表示業內的低地址的低3bit會每收到一個數據就自動增長,頁地址維持不變。所以,當業內地址到頂端時,此時假如還有數據,則數據將會被放到頁的起始地址處,頁起始地址中之前存放的數據也將會被覆蓋。即AT24C02頁操作時,寫入的數據大于8byte,則大于8byte的數據將重新從此頁起始處存放,并覆蓋掉之前寫入的的數據
==================================================================================================================
另外我們再說一下隨機讀取:
==================================================================================================================
隨機讀寫的操作就是主機先用一個寫操作來騙過AT24C02器件,使AT24C02內部的data word address中的地址值修改,然后再通過current ad
[1] [2] [3] [4]
本網站轉載的所有的文章、圖片、音頻視頻文件等資料的版權歸版權所有人所有,本站采用的非本站原創文章及圖片等內容無法一一聯系確認版權者。如果本網所選內容的文章作者及編輯認為其作品不宜公開自由傳播,或不應無償使用,請及時通過電子郵件或電話通知我們,以迅速采取適當措施,避免給雙方造成不必要的經濟損失。
總結
以上是生活随笔為你收集整理的linux 下i2c读写命令,S3C2440 Linux下的I2C驱动以及I2C体系下对EEPROM进行读写操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: HTML+CSS+JS实现 ❤️翻页倒计
- 下一篇: linux内核是否支持nfs,嵌入式命令