如何解决i2c I2C_M_REV_DIR_ADDR 问题
我有一个 Jetson Xavier AGX 开发套件。
我在使用 /dev/i2c-8 上的 i2c 设备时遇到了困难,该设备使用非标准协议来更新其固件。
写入事务顺利通过。但是读取事务需要将地址 rw/wr 位设置为 1,这就是问题的开始。
读取事务如下所示:
/******************************************************************************/
// Read transaction
//{DEVICE_ADDR[7:1],1'b1}
// 0xAC Loader Module (shown with bit 0 masked to a 0)
//<ACK_FROM_SLAVE>
//REGISTER_ADDRESS_MSB
// 16-bit register address to allow 65536 registers on slave
//<ACK_FROM_SLAVE>
//REGISTER_ADDRESS_LSB
// 16-bit register address to allow 65536 registers on slave
//<ACK_FROM_SLAVE>
//NUMBER_OF_WORDS_MSB
// Number of 16-bit words to write or read,max of 100
//<ACK_FROM_SLAVE>
//NUMBER_OF_WORDS_LSB
// Number of 16-bit words to write or read,max of 100
//<ACK_FROM_SLAVE>
//WORD_1_MSB_FROM_SLAVE
//<ACK_FROM_MASTER>
//WORD_1_LSB_FROM_SLAVE
//<ACK_FROM_MASTER>
//...
//FINAL_BYTE_FROM_SLAVE
//<ACK_FROM_SLAVE>
/******************************************************************************/
因此,地址为 0x28 的设备和寄存器 0x0000 返回 0x0123 我希望事情会像这样
S 0x51 ACK 0 ACK 0 ACK 0 ACK 1 ACK 0x01 ACK 0x23 ACK P
当我打开总线时,我会检查 i2c 功能
int open(const QString &bus)
{
if ((m_fd = fileOps::open(bus.toLatin1(),O_RDWR)) < -1)
{
qDebug() << Q_FUNC_INFO << "Failed to open i2c bus " << bus;
return -1;
}
unsigned long funcs = 0;
if (ioctl(m_fd,I2C_FUNCS,&funcs))
{
qDebug() << Q_FUNC_INFO << "Could not retrieve bus functionalities";
goto Error;
}
if (!(funcs & I2C_FUNC_PROTOCOL_MANGLING))
{
qDebug() << Q_FUNC_INFO << "The required I2C_FUNC_PROTOCOL_MANGLING functionality is not available";
goto Error;
}
if (!(funcs & I2C_FUNC_NOSTART))
{
qDebug() << Q_FUNC_INFO << "The required I2C_FUNC_NOSTART functionality is not available";
goto Error;
}
if (!(funcs & I2C_FUNC_10BIT_ADDR))
{
qDebug() << Q_FUNC_INFO << "Bus " << bus << " does not support 10-bit chip addressing";
}
return m_fd;
Error:
fileOps::close(m_fd);
return -1;
}
I2C_FUNC_PROTOCOL_MANGLING 和 I2C_FUNC_NOSTART 都存在,所以应该没问题。
我的读取函数如下所示:
int read_word(quint16 reg,quint16 &word)
{
if (!isOpen())
{
qDebug() << Q_FUNC_INFO << "Device not open";
return -1;
}
int retval = 0;
quint8 header[4];
quint8 output[2];
struct i2c_msg msgs[3];
struct i2c_rdwr_ioctl_data msgset[1];
// Header
msgs[0].addr = m_slaveAddress;
msgs[0].flags = I2C_M_REV_DIR_ADDR;
msgs[0].len = 4;
msgs[0].buf = header;
msgs[0].buf[0] = reg >> 8; // REGISTER_ADDRESS_MSB
msgs[0].buf[1] = reg % 256; // REGISTER_ADDRESS_LSB
msgs[0].buf[2] = 0; // NUMBER_OF_WORDS_MSB
msgs[0].buf[3] = 1; // NUMBER_OF_WORDS_LSB
// word
msgs[1].addr = m_slaveAddress;
msgs[1].flags = I2C_M_RD | I2C_M_NOSTART;
msgs[1].len = 2;
msgs[1].buf = output;
msgset[0].msgs = msgs;
msgset[0].nmsgs = 2;
if ((retval = ioctl(m_fd,I2C_RDWR,&msgset)) < 0)
{
int errsv = errno;
qWarning() << "ioctl(I2C_RDWR) failed" << "|" << "retval:" << retval << "|" << "errsv:" << errsv << strerror(errsv);
return retval;
}
qDebug() << "MSB" << output[0];
qDebug() << "LSB" << output[1];
word = output[1] + (output[0] << 8);
return 0;
}
阅读一些手册页,似乎 I2C_M_REV_DIR_ADDR 应该执行反转 rd/wr 位的技巧,但没有效果。
我正在查看来自示波器的信号,无论 I2C_M_REV_DIR_ADDR 是否在第一条消息中设置,rd/wr 位都为 0。
msgs[0].flags 设置为 I2C_M_REV_DIR_ADDR 与设置 0 相同; i2c 流量如下所示:
S 0x50 ACK 0 ACK 0 ACK 0 ACK 1 ACK 0xFF ACK 0xFF ACK P
msgs[0].flags 设置为 I2C_M_RD,地址字节为 0x51,但其余都是垃圾
S 0x51 ACK 0xFF ACK 0xFF ACK 0xFF ACK 0xFF ACK 0xFF ACK 0xFF ACK P
为什么 I2C_M_REV_DIR_ADDR 没有效果?
谢谢, -达米安
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。