Hey, I am debugging the IMX258 sensor, I want to implement dynamic debugging 16bit registers, but I can’t use i2cget, i2cset, i2cdump. I wrote an application to read the write, but the read and write sensors have been abnormal:
“[ 114.047928] tegra-vii2c 546c0000.i2c: no acknowledge from address 0x1a
ioctl error2: Remote I/O error”
code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#if 0
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#else
#define I2C_M_WT 0x0000/* write data, from master to slave /
#define I2C_M_RD 0x0001/ read data, from slave to master /
#define I2C_M_TEN 0x0010 / this is a ten bit chip address /
#define I2C_M_STOP 0x8000 / if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_NOSTART 0x4000 / if I2C_FUNC_NOSTART /
#define I2C_M_REV_DIR_ADDR 0x2000 / if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_IGNORE_NAK 0x1000 / if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_NO_RD_ACK 0x0800 / if I2C_FUNC_PROTOCOL_MANGLING /
#define I2C_M_RECV_LEN 0x0400 / length will be first received byte */
#define I2C_ADDR (0x48>>1)
#define I2C_ADDR_16BIT 1 // 1:16bit i2c_addr 0:8bit i2c_addr
#define I2C_RETRIES 0x0701 /*设置收不到ACK时的重试次数 /
#define I2C_TIMEOUT 0x0702 / 设置超时时限的jiffies */
#define I2C_SLAVE 0x0703 /*设置从机地址 /
#define I2C_SLAVE_FORCE 0x0706 / 强制设置从机地址 */
#define I2C_TENBIT 0x0010 //0x0704 /*选择地址位长:=0 for 7bit , != 0 for 10 bit */
#define I2C_FUNCS 0x0705 /*获取适配器支持的功能 */
#define I2C_RDWR 0x0707 /*Combined R/W transfer (one STOP only) /
#define I2C_PEC 0x0708 / != 0 to use PEC with SMBus */
#define I2C_SMBUS 0x0720 /*SMBus transfer */
#define I2C_SMBUS_BYTE_DATA 2
#define I2C_SMBUS_READ 1
#define I2C_SMBUS_WRITE 0
#define I2C_SMBUS_BLOCK_DATA 5
#define I2C_SMBUS_I2C_BLOCK_DATA 8
#define I2C_SLAVE_FORCE 0x0706
#define I2C_SMBUS_BLOCK_MAX 32
// exact-width types
typedef chars8;
typedef shorts16;
typedef ints32;
typedef unsigned charu8;
typedef unsigned shortu16;
typedef unsigned intu32;
typedef floatf32;
typedef doublef64;
typedef unsigned char u8;
typedef unsigned short int u16;
typedef unsigned int u32;
union i2c_smbus_data {
unsigned char byte;
unsigned short word;
unsigned char block[I2C_SMBUS_BLOCK_MAX + 2];
};
struct i2c_smbus_ioctl_data {
char read_write;
unsigned char command;
int size;
union i2c_smbus_data *data;
};
struct i2c_msg {
u16 addr;/* slave address*/
u16 flags;
u16 len;/* msg length*/
u8 buf;/ pointer to msg data*/
} ;
/* In ./include/linux/i2c-dev.h /
struct i2c_rdwr_ioctl_data {
/ pointers to i2c_msgs */
struct i2c_msg msgs;
/ number of i2c_msgs */
u32 nmsgs;
};
int Standard_i2c_open(int index)
{
char dev_name[32];
sprintf(dev_name, "/dev/i2c-%d", index);
printf("%s:index = %d\r\n",dev_name,index);
return open("/dev/i2c-6", O_RDWR);
}
#if I2C_ADDR_16BIT
int write_16bit_i2c(int bus_index, u8 device_addr/8bits/, u32 register_addr, unsigned char *pBuffer)
{
struct i2c_rdwr_ioctl_data e2prom_data;
int i2c_dev_fd = -1;
char reg_buf[3]={0,0,0};
int ret;
/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf(“standard_i2c_read Standard_i2c_open Failed\n”);
goto OVER;
}
ioctl(i2c_dev_fd,I2C_TIMEOUT,1);/*超时时间*/
ioctl(i2c_dev_fd,I2C_RETRIES,2);/*重复次数*/
e2prom_data.nmsgs=1;
e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));
if(!e2prom_data.msgs)
{
perror("malloc error");
goto _OVER_;
}
reg_buf[0] = (register_addr >> 8) & 0xFF; //e2prom数据地址 16bit
reg_buf[1] = register_addr & 0xFF ; //e2prom数据地址
reg_buf[2] = pBuffer[0] ; //写一个数据
(e2prom_data.msgs[0]).len=3; //
(e2prom_data.msgs[0]).addr=device_addr; // e2prom 设备地址
(e2prom_data.msgs[0]).flags=I2C_M_WT; //write
(e2prom_data.msgs[0]).buf = reg_buf;
ret=ioctl(i2c_dev_fd,I2C_RDWR,(unsigned long)&e2prom_data);
if(ret<0)
{
perror("ioctl error2");
goto _OVER_;
}
printf("** %x ** \n",pBuffer[0]);
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
if(e2prom_data.msgs != NULL)
{
free(e2prom_data.msgs);
}
}
int read_16bit_i2c(int bus_index, u8 device_addr/8bits/, u32 register_addr, unsigned char *pBuffer)
{
struct i2c_rdwr_ioctl_data e2prom_data;
int i2c_dev_fd = -1;
char reg_buf[2]={0,0},buf[2]={0,0};
int ret;
/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf(“standard_i2c_read Standard_i2c_open Failed\n”);
goto OVER;
}
printf(“%s:%d\r\n”,FUNCTION,LINE);
ioctl(i2c_dev_fd,I2C_TIMEOUT,5);/超时时间/
ioctl(i2c_dev_fd,I2C_RETRIES,2);/重复次数/
printf(“%s:%d\r\n”,FUNCTION,LINE);
e2prom_data.nmsgs=2;
e2prom_data.msgs=(struct i2c_msg*)malloc(e2prom_data.nmsgs*sizeof(struct i2c_msg));
if(!e2prom_data.msgs)
{
perror("malloc error");
goto _OVER_;
}
reg_buf[0] = (register_addr >> 8) & 0xFF; //e2prom数据地址 16bit
reg_buf[1] = register_addr & 0xFF ; //e2prom数据地址
e2prom_data.nmsgs=2;
(e2prom_data.msgs[0]).len=2; //e2prom 要写的字节数
(e2prom_data.msgs[0]).addr=device_addr; // e2prom 设备地址
(e2prom_data.msgs[0]).flags=I2C_M_WT; //write
(e2prom_data.msgs[0]).buf = reg_buf;
(e2prom_data.msgs[1]).len=1; //读出的数据个数
(e2prom_data.msgs[1]).addr=device_addr; // e2prom 设备地址
(e2prom_data.msgs[1]).flags=I2C_M_RD;//read
(e2prom_data.msgs[1]).buf=buf;
ret=ioctl(i2c_dev_fd,I2C_RDWR,(unsigned long)&e2prom_data);
if(ret<0)
{
perror("ioctl error2");
goto _OVER_;
}
printf("***0x%x***\n",(e2prom_data.msgs[1]).buf[0]);
pBuffer[0] = (e2prom_data.msgs[1]).buf[0];
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
if(e2prom_data.msgs != NULL)
{
free(e2prom_data.msgs);
}
}
//#else
int read_8bit_i2c(int bus_index, unsigned char device_addr/8bits/, unsigned char register_addr, unsigned char *pBuffer, int byte_number)
{
struct i2c_smbus_ioctl_data ioctl_data;
union i2c_smbus_data smbus_data;
int ret_val = -1;
int i2c_dev_fd = -1;
int index = 0;
/**/
if(byte_number >= I2C_SMBUS_BLOCK_MAX)
{
printf("standard_i2c_read Invalid parameter(%d >= %d)\n", byte_number, I2C_SMBUS_BLOCK_MAX);
return -1;
}
/**/
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf("standard_i2c_read Standard_i2c_open Failed\n");
goto _OVER_;
}
/*set address*/
ioctl(i2c_dev_fd, I2C_TENBIT, 0);
if(ioctl(i2c_dev_fd, I2C_SLAVE_FORCE, (device_addr)& 0x7f) < 0)
{
perror("i2c ioctl:");
printf("standard_i2c_read ioctl(I2C_SLAVE) Failed\n");
goto _OVER_;
}
/**/
smbus_data.block[0] = byte_number;
ioctl_data.read_write = I2C_SMBUS_READ;
ioctl_data.command = register_addr;
ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
ioctl_data.data = &smbus_data;
if(ioctl(i2c_dev_fd, I2C_SMBUS, &ioctl_data) != 0)
{
printf("standard_i2c_read ioctl(I2C_SMBUS) Failed(%d)\n", index);
goto _OVER_;
}
if(smbus_data.block[0] != byte_number)
{
printf("standard_i2c_read ioctl read Failed(%d)(%d)\n", smbus_data.block[0], byte_number);
goto _OVER_;
}
for(index = 0; index < byte_number; index ++)
{
pBuffer[index] = smbus_data.block[index + 1];
}
ret_val = 0;
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
return ret_val;
}
int write_8bit_i2c(int bus_index, unsigned char device_addr/8bits/, unsigned char register_addr, unsigned char *pBuffer, int byte_number)
{
struct i2c_smbus_ioctl_data ioctl_data;
union i2c_smbus_data smbus_data;
int ret_val = -1;
int i2c_dev_fd = -1;
int index = 0;
/**/
if(byte_number >= I2C_SMBUS_BLOCK_MAX)
{
printf("standard_i2c_write ioctl Invalid parameter(%d)\n", byte_number);
return -1;
}
i2c_dev_fd = Standard_i2c_open(bus_index);
if(i2c_dev_fd < 0)
{
printf("standard_i2c_write Standard_i2c_open Failed\n");
goto _OVER_;
}
/*set address*/
ioctl(i2c_dev_fd, I2C_TENBIT, 0);
if(ioctl(i2c_dev_fd, I2C_SLAVE_FORCE, (device_addr) & 0x7f) < 0)
{
perror("i2c ioctl:");
printf("standard_i2c_write ioctl(I2C_SLAVE) Failed\n");
goto _OVER_;
}
/**/
smbus_data.block[0] = byte_number;
for(index = 0; index < byte_number; index ++)
{
smbus_data.block[index + 1] = pBuffer[index];
}
/**/
ioctl_data.read_write = I2C_SMBUS_WRITE;
ioctl_data.command = register_addr;
ioctl_data.size = I2C_SMBUS_I2C_BLOCK_DATA;
ioctl_data.data = &smbus_data;
/**/
if(ioctl(i2c_dev_fd, I2C_SMBUS, &ioctl_data) != 0)
{
printf("standard_i2c_write ioctl(I2C_SMBUS) Failed(%d)\n", index);
goto _OVER_;
}
ret_val = 0;
_OVER_:
if(i2c_dev_fd >= 0)
{
close(i2c_dev_fd);
}
return ret_val;
}
int usage(char *pname)
{
printf(“%s i2c_ch <8/16> [value]\n”, pname);
return 0;
}
/* read ./iis 16 0x24 0x0111 /
/ write ./iis 16 0x24 0x0111 0x3 */
int main(int argc, char *argv)
{
unsigned char i2c_dev;
unsigned int i2c_reg;
unsigned char value[4];
unsigned int readvalue;
unsigned char reg_bit;
int i;
int i2c_channel;
if(argc < 3)
{
usage(argv[0]);
exit(1);
}
i2c_channel = strtoll(argv[1],NULL,0);
reg_bit=strtoll(argv[2], NULL, 0);
i2c_dev=strtoll(argv[3], NULL, 0);
i2c_reg=strtoll(argv[4], NULL, 0);
printf("reg_bit i2c_channel= %x,reg_bit=%x,i2c_dev=%x,i2c_reg=%x \n",i2c_channel,reg_bit,i2c_dev,i2c_reg);
if(argc == 5)
{
if(16 == reg_bit){
read_16bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0]);
}else{
read_8bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0], 1);
}
printf("read reg 0x%x value: 0x%x \n",i2c_reg,value[0]);
}
else if(argc == 6)
{
value[0]=strtoll(argv[5], NULL, 0);
if(16 == reg_bit){
write_16bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0]);
}else{
write_8bit_i2c(i2c_channel, i2c_dev,i2c_reg, &value[0], 1);
}
printf("write reg 0x%x value: 0x%x \n",i2c_reg,value[0]);
}
}