I want read temperature from BMP180 to NetRouter(a development board base on mt7620a) by i2c bus.
1. I modify mt7620a.dtsi to enable i2c device and rebuild openwrt with i2c support
mt7620a.dtsi file:
menuconfig:
2. Update openwrt system, and I can found /dev/i2c-0
3. I try to run my program but I keep get "i2c-read line busy"
my program:
#include <stdio.h>
#include <stdint.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#define BMP180_I2C_ADDR (0xee)
#define BMP180_I2C_ADDR_R (BMP180_I2C_ADDR)
#define BMP180_I2C_ADDR_W (BMP180_I2C_ADDR | 1)
#define BMP180_REG_ADDR_TEMPERATURE (0x2E)
#define I2C_DEV_NAME "/dev/i2c-0"
static int set_i2c_register(int file,
unsigned char addr,
unsigned char reg,
unsigned char value) {
unsigned char outbuf[2];
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[1];
messages[0].addr = addr;
messages[0].flags = 0;
messages[0].len = sizeof(outbuf);
messages[0].buf = outbuf;
/* The first byte indicates which register we'll write */
outbuf[0] = reg;
/*
* The second byte indicates the value to write. Note that for many
* devices, we can write multiple, sequential registers at once by
* simply making outbuf bigger.
*/
outbuf[1] = value;
/* Transfer the i2c packets to the kernel and verify it worked */
packets.msgs = messages;
packets.nmsgs = 1;
if(ioctl(file, I2C_RDWR, &packets) < 0) {
perror("Unable to send data");
return 1;
}
return 0;
}
static int get_i2c_register(int file,
unsigned char addr,
unsigned char reg,
unsigned char *val) {
unsigned char inbuf, outbuf;
struct i2c_rdwr_ioctl_data packets;
struct i2c_msg messages[2];
/*
* In order to read a register, we first do a "dummy write" by writing
* 0 bytes to the register we want to read from. This is similar to
* the packet in set_i2c_register, except it's 1 byte rather than 2.
*/
outbuf = reg;
messages[0].addr = addr;
messages[0].flags = 0;
messages[0].len = sizeof(outbuf);
messages[0].buf = &outbuf;
/* The data will get returned in this structure */
messages[1].addr = addr;
messages[1].flags = I2C_M_RD/* | I2C_M_NOSTART*/;
messages[1].len = sizeof(inbuf);
messages[1].buf = &inbuf;
/* Send the request to the kernel and get the result back */
packets.msgs = messages;
packets.nmsgs = 2;
if(ioctl(file, I2C_RDWR, &packets) < 0) {
perror("Unable to send data");
return 1;
}
*val = inbuf;
return 0;
}
int main()
{
int fd_i2c = 0;
int ret = -1;
unsigned char val;
fd_i2c = open(I2C_DEV_NAME, O_RDWR);
if (fd_i2c < 0)
{
perror(I2C_DEV_NAME);
goto clean;
}
while(1)
{
set_i2c_register(fd_i2c, BMP180_I2C_ADDR, 0xF4, 0x2E);
get_i2c_register(fd_i2c, BMP180_I2C_ADDR, 0xF6, &val);
printf("val: %d\n", val);
}
ret = 0;
clean:
if (fd_i2c >= 0)
{
close(fd_i2c);
}
return ret;
}
My openwrt version: 15.05
Please help, thanks