爲什麼重複啓動基於I2C操作,在linux下不支持?
事實上,他們是支持的。
如果您正在尋找在用戶空間執行重複的啓動條件的方式,你可能需要做ioctl()
與I2C_RDWR
要求,如它的描述here(見原題最後的代碼片段)和here(代碼有問題)。
下面描述了在內核空間中執行重複啓動的方式。
在Linux內核I2C讀取repeated start condition操作由默認爲組合(寫/讀)消息來執行。
下面是一個例子如何執行組合I2C傳輸:
/**
* Read set of registers via I2C using "repeated start" condition.
*
* Two I2C messages are being sent by this function:
* 1. I2C write operation (write register address) with no STOP bit in the end
* 2. I2C read operation
*
* @client: I2C client structure
* @reg: register address (subaddress)
* @len: bytes count to read
* @buf: buffer which will contain read data
*
* Returns 0 on success or negative value on error.
*/
static int i2c_read_regs(struct i2c_client *client, u8 reg, u8 len, u8 *buf)
{
int ret;
struct i2c_msg msg[2] = {
{
.addr = client->addr,
.len = 1,
.buf = ®,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf,
}
};
ret = i2c_transfer(client->adapter, msg, 2);
if (ret < 0) {
dev_err(&client->dev, "I2C read failed\n");
return ret;
}
return 0;
}
要閱讀僅1個字節(單個寄存器值),可以使用下一個輔助函數:
/**
* Read one register via I2C using "repeated start" condition.
*
* @client: I2C client structure
* @reg: register address (subaddress)
* @val: variable to store read value
*
* Returns 0 on success or negative value on error.
*/
static int i2c_read_reg(struct i2c_client *client, u8 reg, u8 *val)
{
return i2c_read_regs(client, reg, 1, val);
}
下面是例證對於i2c_read_regs(client, reg, 1, val)
電話:
- 設備地址是
client->addr
個
- 寄存器地址是
reg
1
意味着我們想要讀出的數據的1個字節(上圖片粉紅色矩形)
- 讀出的數據將駐留在
val
![enter image description here](https://i.stack.imgur.com/Hz803.png)
注意:如果您的I2C控制器(或其驅動程序)不支持組合消息中的重複啓動,則仍然可以使用bit-bang實現I2C,它是i2c-gpio驅動程序。
如果什麼都行不通,您可以嘗試下一步作爲最後的手段。出於某種原因,我不太記得了,爲了使重複開始工作,我需要添加I2C_M_NOSTART
到第一條消息的.flags
,像這樣:
struct i2c_msg msg[2] = {
{
.addr = client->addr,
.flags = I2C_M_NOSTART,
.len = 1,
.buf = ®,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = len,
.buf = buf,
}
};
如Documentation/i2c/i2c-protocol
指出:
如果您爲第一個部分消息 設置了I2C_M_NOSTART
變量,我們不生成Addr
,但我們確實生成了startbit S
。
參考文獻:
[1] I2C on STLinux
幾件事情:SOC/HW你使用的是哪個?某些i2c主機控制器可能不支持重複啓動(這就是爲什麼他們的驅動程序可能沒有重複啓動代碼)。檢出支持'REPEAT_START'作爲Tegra I2C主機控制器的[Tegra-I2C驅動程序](http://lxr.free-electrons.com/source/drivers/i2c/busses/i2c-tegra.c#L554)支持重複啓動模式。另外像'i2cset' /'i2cget'這樣的用戶空間工具非常簡單,並且可能不支持i2c操作的重複啓動模式。 – TheCodeArtist
@TheCodeArtist它看起來像OP只是使用不正確的API發送重複啓動。我在回答中添加了關於用戶空間方法的註釋。 –
@ TheCodeArtist它的mediatek MT7621A SoC。已經,我也檢查,如果i2c主機控制器或其驅動程序不支持重複啓動。 – coder007