1、背景介绍
RXS2448是三代交换和二代交换1848有很多类似的地方。原以为IIC时序会继承,然后直接上IDT1848IIC驱动发现并不能成功读取数据。
借由调试RXS2448 I2C访问驱动编写熟悉I2C读写时序编程,我们这里RXS2448做从机模式。
2、实现过程
2.1 、slave adderss 确认
阅读RXS2448硬件手册I2C章节。根据硬件管脚设置可以确认slave addres。可以看到高三位一倍写死,后面4位可以由硬件配置。
2.2、read write 时序
值得注意的是读写中的SLV_PA(外设地址空间),意思就是rxs2448的可以直接访问的IIC地址空间只有0x00-0xff的256-byte的地址空间,所有的外设地址空间的访问都要通过I2C的内部地址空间间接访问,懂得这个道理下面就好实现读取数据了。
接下来看读写的时序,这里可以看到我们在读写的时候,需要设置外设地址(peripheral Address)。
例如读取我们读取寄存器为0的数据。我们首先要做的是把寄存器0写入I2C的内部地址空间0x10-0x13,然后再读0x14-0x17就把寄存器0中的数据读出来了。(具体的寄存器和I2C的内部地址含义需要看手册)。
这样下来read 寄存器的操作流程就是
write : slave Address 0x10 Reg(0ffset)
write :slave Address 0x14
read:buff(即为Reg 0的值)。读实现的代码段。写的操作流程与读类似,在此不再赘述。
static ssize_t cps1848_eeprom_read( struct i2c_client *client,
char *buf, unsigned offset, size_t count)
{
struct i2c_msg msg[3];
u8 msgbuf[5];
u8 slv_pa[2] = {0x14,0};
unsigned long timeout, transfer_time;
int status;
struct cps1848_data *data = i2c_get_clientdata(client);
struct cdns_i2c *id = client->adapter->algo_data;
memset(msg, 0, sizeof(msg));
msgbuf[0] = 0x10;
msgbuf[1] = (u8)(offset & 0xff);
msgbuf[2] = (u8)((offset >> 8) & 0xff);
msgbuf[3] = (u8)((offset >> 16) & 0xff);
msg[0].addr = client->addr;
msg[0].buf = msgbuf;
msg[0].len = 5;
msg[1].addr = client->addr;
msg[1].buf = slv_pa;
msg[1].len = 1;
msg[2].addr = client->addr;
msg[2].flags = I2C_M_RD;
msg[2].buf = buf;
msg[2].len = count;
/*
* Reads fail if the previous write didn't complete yet. We may
* loop a few times until this one succeeds, waiting at least
* long enough for one entire page write to work.
*/
timeout = jiffies + msecs_to_jiffies(read_timeout);
do {
transfer_time = jiffies;
status = i2c_transfer(client->adapter, msg, 2);
if (status == 3)
return count;
/* REVISIT: at HZ=100, this is sloooow */
msleep(1);
} while (time_before(transfer_time, timeout));
return -ETIMEDOUT;
}