i2cdetect工具原理说明
在嵌入式的开发,特别是与硬件交互时,经常会使用i2cdetect工具用于判断器件是否存在,但是返回显示的UU和–实际表示什么含义?
i2cdetect的使用示例
i2cdetect -y {bus}
例如:i2cdetect -y 10
i2cdetect原理
i2cdetect工具来源于i2c-tools:https://github.com/suapapa/i2c-tools.git
- 当使用i2cdetect工具扫描到实际器件时,显示器件地址;
- 当使用i2cdetect工具未扫描到实际器件时,显示
--
; - 当使用i2cdetect工具扫描时,发现地址已在驱动使用,显示
UU
4. 遍历扫描地址0x08-0x77,i2c-tools工具中的函数 目录:tools/i2cdetect.c
static int scan_i2c_bus(int file, int mode, unsigned long funcs,
int first, int last)
5. 首先使用ioctl(file, I2C_SLAVE, address)时,发现地址已经在驱动中使用,会返回EBUSY,显示为'UU',例如,eeprom驱动已经在/sys目录下创建了对应eeprom的文件,此时使用ioctl(file, I2C_SLAVE, address)命令访问此地址时返回EBUSY
调用kernel中的函数driver/i2c/i2c-dev.c中调用
static const struct file_operations i2cdev_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = i2cdev_read,
.write = i2cdev_write,
.unlocked_ioctl = i2cdev_ioctl,
.compat_ioctl = compat_i2cdev_ioctl,
.open = i2cdev_open,
.release = i2cdev_release,
};
6. 在0x30-0x3f和0x50-0x5f使用MODE_READ,其他地址使用MODE_QUICK
MODE_READ对应函数i2c_smbus_read_byte(file),读一个byte,但是读取过程不符合标准i2c访问路径,仅是用于检测地址是否存在,所以访问过程是发送地址都直接进行了读字节操作,此时返回的字节是当前器件地址指向的位置,有些器件是offset为0位置所在的值,有些器件不是
MODE_QUICK对应函数i2c_smbus_write_quick(file, I2C_SMBUS_WRITE)
- drivers/i2c/i2c-core-smbus.c
- s32 i2c_smbus_read_byte(const struct i2c_client *client)
- - i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_READ, 0,
I2C_SMBUS_BYTE, &data);
- - - s32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
unsigned short flags, char read_write,
u8 command, int protocol, union i2c_smbus_data *data) i2ctrace在这个函数中添加
- - - - res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
command, protocol, data); 此处进行的MODE_READ和MODE_QUICK的区分,MODE_READ是写完地址后直接读取一个字节数据; MODE_QUICK 仅写地址后判断是否有ACK响应
- - - - - status = __i2c_transfer(adapter, msg, nmsgs);
- drivers/i2c/busses/i2c-aspeed.c
- - .master_xfer = aspeed_i2c_master_xfer
i2c访问成功返回对应的'地址',访问失败返回'--'
获取8bit地址,bit0读是1写是0
static inline u8 i2c_8bit_addr_from_msg(const struct i2c_msg *msg)
{
return (msg->addr << 1) | (msg->flags & I2C_M_RD ? 1 : 0);
}