i2c的时序分为四部分:起始信号,数据传输,应答信号,停止信号:
staticint i2c_read_bytes(struct i2c_client *client, u8 cmd, u8 *data, u8 data_len)
{
struct i2c_msg msgs[2];
int ret;
u8 *buffer;
buffer = kzalloc(data_len, GFP_KERNEL);
if (!buffer)
return-ENOMEM;;
msgs[0].addr = client->addr;
msgs[0].flags = client->flags;
msgs[0].len = 1;
msgs[0].buf = &cmd;
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0) {
dev_err(&client->adapter->dev, "i2c read failed\n");
kfree(buffer);
return ret;
}
msgs[1].addr = client->addr;
msgs[1].flags = client->flags | I2C_M_RD;
msgs[1].len = data_len;
msgs[1].buf = buffer;
ret = i2c_transfer(client->adapter, &msgs[1], 1);
if (ret < 0)
dev_err(&client->adapter->dev, "i2c read failed\n");
else
memcpy(data, buffer, data_len);
kfree(buffer);
return ret;
}
注:板子上i2c总线4有个i2c设备,i2c地址为0x6a
以下demo是通过kernel驱动读写i2c设备。
dts修改:
&i2c4 {
status = "okay";
i2ctest: i2ctest@0 {
compatible = "rockchip,i2c-test";
reg = <0x6a>;
status = "okay";
};
};
kernel驱动代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
static int i2c_read_bytes(struct i2c_client *client, u8 cmd, u8 *data, u8 data_len)
{
struct i2c_msg msgs[2];
int ret;
u8 *buffer;
buffer = kzalloc(data_len, GFP_KERNEL);
if (!buffer)
return-ENOMEM;;
msgs[0].addr = client->addr;
msgs[0].flags = client->flags;
msgs[0].len = 1;
msgs[0].buf = &cmd;
msgs[1].addr = client->addr;
msgs[1].flags = client->flags | I2C_M_RD;
msgs[1].len = data_len;
msgs[1].buf = buffer;
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret < 0)
dev_err(&client->adapter->dev, "i2c read failed\n");
else
memcpy(data, buffer, data_len);
kfree(buffer);
return ret;
}
*/
static int i2c_write_bytes(struct i2c_client *client, u8 *data, u8 data_len)
{
struct i2c_msg msgs[1];
u8 *buffer;
int ret = 0;
printk("---->:%s\n" ,__func__);
buffer = kzalloc(data_len + 1, GFP_KERNEL);
if (!buffer)
return-ENOMEM;
memcpy(buffer, data, data_len);
msgs[0].addr = client->addr;
msgs[0].flags = client->flags;
msgs[0].len = data_len;
msgs[0].buf = buffer;
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (ret < 0)
dev_err(&client->adapter->dev, "i2c write failed\n");
kfree(buffer);
return ret;
}
static struct of_device_id i2c_test_of_match[] = {
{ .compatible = "rockchip,i2c-test"},
{ },
};
MODULE_DEVICE_TABLE(of, i2c_test_of_match);
static int i2c_test_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
{
const struct of_device_id *match;
uint8_t pre_cmd_data[2]={0};
int i;
printk("---->:%s\n" ,__func__);
pre_cmd_data[0]=0x0f;
pre_cmd_data[1]=0xbb;
if (i2c->dev.of_node) {
match = of_match_device(i2c_test_of_match, &i2c->dev);
if (!match) {
dev_err(&i2c->dev,"Failed to find matching dt id\n");
return -EINVAL;
}
}
for(i=20; i>=0; i--){
i2c_write_bytes(i2c,pre_cmd_data,2);
mdelay(100);
}
return 0;
}
static const struct i2c_device_id i2c_ids[] = {
{ "i2c-test" },
{ },
};
MODULE_DEVICE_TABLE(i2c, i2c_ids);
static struct i2c_driver i2c_test_driver = {
.driver = {
.name = "i2c-test",
.owner = THIS_MODULE,
.of_match_table =of_match_ptr(i2c_test_of_match),
},
.probe = i2c_test_probe,
.id_table = i2c_ids,
};
module_i2c_driver(i2c_test_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jstl " );
MODULE_DESCRIPTION("i2c test driver");
测得波形
从波形读得数据:0xd4 0x0f 0xbb
其中:0xd4为:i2c地址+读写标志,即:0xd4(8b’11010100)=0x6a(7b’1101010)+写标志(1b’0)
0x0f 0xbb为数据
注:板子上i2c总线4有个i2c设备,i2c地址为0x6a
以下demo是直接在应用层读写i2c设备,因此,kernel中只要把i2c接口打开即可。
dts把i2c4开启:
&i2c4 {
status = "okay";
};
应用层代码:
#include "encryptic.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG_TAG "encryptchip"
#define DEBUG
#define I2C_M_WR 0x0000
#define I2C_M_RD 0x0001 /* read data, from slave to master */
#define IIC_MSGBUF_LENGTH 256
#define IIC_READ_COUNT_MAX 50
#define IC_CMD_SN_LENGTH 19
#define IC_SN_OFFSET 1
#define IC_SN_LENGTH 16
#define IC_CMD_VER_LENGTH 5
#define IC_VER_OFFSET 1
#define IC_VER_LENGTH 2
#define IC_CERT_RANDOM_OFFSET 1
#define IC_CERT_RANDOM_LENGTH 48
#define IC_CERT_DATA_OFFSET 49
#define IC_CERT_DATA_LENGTH 131
#define IC_CERT_LENGTH 182
#define IC_SIGN_LENGTH 51
#define IC_CMD_KEY_LENGTH 51
#define IC_KEY_OFFSET 1
int I2C_WriteNbyte(unsigned char i2c_no, unsigned char dev_addr, unsigned char reg_addr, unsigned char send_len, unsigned char send_buf[])
{
int tmp_ret = 0;
struct i2c_rdwr_ioctl_data ctl_data;
int device_fd = -1;
if (send_buf == NULL) {
printf("\nwrite data buf is NULL\n");
return -1;
}
if (send_len < 1)
{
printf("write data length error \n");
return -1;
}
if (i2c_no == 7) {
device_fd = open("/dev/i2c-7", O_RDWR);
} else if (i2c_no == 4) {
device_fd = open("/dev/i2c-4", O_RDWR);
} else if (i2c_no == 2) {
device_fd = open("/dev/i2c-2", O_RDWR);
} else if (i2c_no == 1) {
device_fd = open("/dev/i2c-1", O_RDWR);
} else {
device_fd = open("/dev/i2c-0", O_RDWR);
}
if (device_fd < 0) {
printf("\nwrite open error!\n");
return -1;
}
ctl_data.nmsgs = 1;
ctl_data.msgs = (struct i2c_msg *)malloc(ctl_data.nmsgs * sizeof(struct i2c_msg));
if (!ctl_data.msgs){
printf("Memory alloc error\n");
return 0;
}
ctl_data.msgs[0].len = send_len+1;
ctl_data.msgs[0].addr = dev_addr;
ctl_data.msgs[0].flags = I2C_M_WR;
ctl_data.msgs[0].buf = (unsigned char*)malloc(send_len+1);
ctl_data.msgs[0].buf[0] = reg_addr;
memcpy(&ctl_data.msgs[0].buf[1], send_buf, send_len);
#ifdef DEBUG
for (int i=0; i<send_len+1; i++)
{
printf("\n %02x",ctl_data.msgs[0].buf[i]);
}
printf("\n");
#endif
tmp_ret = ioctl(device_fd, I2C_RDWR, &ctl_data);
printf(":send_len=%d\n" ,ctl_data.msgs[0].len);
if (tmp_ret < 0)
{
printf("\nwrite error!\n");
close(device_fd);
return -1;
}
usleep(10 * 1000);
if (device_fd >= 0) {
close(device_fd);
device_fd = -1;
}
return tmp_ret;
}
int I2C_ReadNbyte(unsigned char i2c_no, unsigned char dev_addr, unsigned char reg_addr, unsigned char rev_len, unsigned char rev_buf[])
{
int tmp_ret = -1;
struct i2c_rdwr_ioctl_data ctl_data;
int device_fd = -1;
if (rev_buf == NULL) {
printf("\nread data buf is NULL\n");
return -1;
}
if (i2c_no == 7) {
device_fd = open("/dev/i2c-7", O_RDWR);
} else if (i2c_no == 4) {
device_fd = open("/dev/i2c-4", O_RDWR);
} else if (i2c_no == 2) {
device_fd = open("/dev/i2c-2", O_RDWR);
} else if (i2c_no == 1) {
device_fd = open("/dev/i2c-1", O_RDWR);
} else {
device_fd = open("/dev/i2c-0", O_RDWR);
}
if (device_fd < 0) {
printf("\nread open error!\n");
return -1;
}
ctl_data.nmsgs = 2;
ctl_data.msgs = (struct i2c_msg *)malloc(ctl_data.nmsgs * sizeof(struct i2c_msg));
if (!ctl_data.msgs){
printf("Memory alloc error\n");
return 0;
}
ctl_data.msgs[0].len = 1;
ctl_data.msgs[0].addr = dev_addr;
ctl_data.msgs[0].flags = I2C_M_WR;
ctl_data.msgs[0].buf = (unsigned char*)malloc(1);
ctl_data.msgs[0].buf[0] = reg_addr;
ctl_data.msgs[1].len = rev_len;
ctl_data.msgs[1].addr = dev_addr;
ctl_data.msgs[1].flags = I2C_M_RD;
ctl_data.msgs[1].buf = (unsigned char*)malloc(rev_len);
memset(ctl_data.msgs[1].buf, 0, rev_len);
tmp_ret = ioctl(device_fd, I2C_RDWR, &ctl_data);
if (tmp_ret < 0)
{
printf("\nread error!\n");
close(device_fd);
return -1;
}
memcpy(rev_buf, ctl_data.msgs[1].buf, rev_len);
usleep(10 * 1000);
if (device_fd >= 0) {
close(device_fd);
device_fd = -1;
}
return tmp_ret;
}
static bool cmdToBuffer(unsigned char *cmd, int cmdlen, unsigned char databuf[])
{
int i;
unsigned char Xor;
Xor = cmdlen;
databuf[0] = cmdlen;
for(i=0;i<cmdlen;i++)
{
databuf[i+1] = cmd[i];
Xor ^= cmd[i];
}
databuf[i+1] = Xor;
return true;
}
static int checkResult(unsigned char Result[], int ResultLen)
{
int i;
unsigned char Xor;
if(Result[ResultLen-2] != 0x90)
return 1;
Xor = 0;
for(i=0;i<(ResultLen-1);i++)
{
Xor ^= Result[i];
}
if(Xor != Result[i])
return 2;
return 0;
}
void EncryptIC_Init(void)
{
printf("\nEncryptIC_Init\n");
}
int iic_send_recv(char* send, int send_len,char* recv,int recv_len)
{
int i = 0;
unsigned char buf[128];
int nret;
unsigned char send_data[10];
memset(send_data, 0, sizeof(send_data));
cmdToBuffer(send, send_len, send_data);
while(1)
{
sleep(2);
#ifdef DEBUG
//send_data[0]= 0x0f;
printf("write data:\n");
for(i=0;i<3;i++)
printf("%02x",send_data[i]);
printf("\n");
#endif
//I2C_WriteNbyte(4, 0x2a, 0x54, 3, send_data);
I2C_WriteNbyte(4, 0x6a, 0x06, 1, send_data);
usleep(10*1000);
sleep(1);
memset(buf, 0, sizeof(buf));
//I2C_ReadNbyte(4, 0x2a, 0x55, recv_len+2, buf);
//I2C_ReadNbyte(4, 0x6a, 0x06, 1, buf);
//for(i = 0; i < IIC_READ_COUNT_MAX; i++)
{
//if(I2C_ReadNbyte(7, 0x2a, 0, recv_len+2, buf) >= 0)
//break;
}
//if(i >= IIC_READ_COUNT_MAX)
//return -1;
#ifdef DEBUG
printf("read data:\n");
for(i=0;i<0x12;i++)
printf("%02x",buf[i]);
printf("\n");
#endif
}
nret = checkResult(buf, recv_len+2);
if(nret != 0)
return nret;
for(i=0;i<recv_len;i++)
recv[i] = buf[i+1];
return 0;
}
int main()
{
int ret = 0;
unsigned char read_cert[1] = {0x01};
unsigned char cert_buf[128] = {0};
ret = iic_send_recv(read_cert,1,cert_buf,0x12);
printf("\nret:%d\n",ret);
#ifdef DEBUG
printf("cert_buf:\n");
for(int i=0;i<113;i++)
printf("%02x",cert_buf[i]);
#endif
return 0;
}
执行应用:
root@linaro-alip:~# encryptic
write data:
010100
06
01
<debug>:send_len=2
read data:
000000000000000000000000000000000000
测得波形
从波形读得数据:0xd4 0x06 0x01
其中:0xd4为:i2c地址+写标志,即:0xd4(8b’11010100)=0x6a(7b’1101010)+写标志(1b’0)
0x06 0x01为数据。