The BCM2835 ARM Peripherals document claims that the BSC (the I2C controller in BMC2835) is I2C 2.1 compliant so it must support repeated start. And indeed, it does. However, the documentation of that feature is quite minimal, limited to the one example of how the 10-bit addressing can be achieved with BSC. The procedure in section 3.3 (pages 36-37) describing reading of 10-bit-addressed slave is an example of the more general one.
In brief, the procedure is that a write is started and then a read is queued before the write is completed. When a read is available to teh decice's state machine when the write ends, BSC does not generate stop condition but a repeated start, re-addressing, and read.
That functionality has been implemented in theRPi device driver (i2c-bcm2708.c). The catch here is that the feature, called as "combined" transaction, is disabled by deafault and has to be enabled to work.
So, once one has the i2c driver installed (insmod i2c-dev.ko, insmod i2c-bcm2708.ko), and made available (chmod 666 /dev/i2c-*), then one needs to turn on the combined transactions (chmod 666 /sys/module/i2c_bcm2708/parameters/combined, echo -n 1 > /sys/module/i2c_bcm2708/parameters/combined).
Now one can read even those old, repeated-start-picky EEPROMs like XR24C02 like
Code: Select all
...
struct i2c_msg rdwr_msgs[2] = {
{ // Start address
.addr = 0x50,
.flags = 0, // write
.len = 1,
.buf = ®_address
},
{ // Read buffer
.addr = 0x50,
.flags = I2C_M_RD, // read
.len = 16,
.buf = buffer
}
};
struct i2c_rdwr_ioctl_data rdwr_data = {
.msgs = rdwr_msgs,
.nmsgs = 2
};
file = open( "/dev/i2c-1", O_RDWR );
...
result = ioctl( file, I2C_RDWR, &rdwr_data );
if ( result < 0 ) {
printf( "rdwr ioctl error: %d\n", errno );
perror( "reason" );
} else {
printf( "rdwr ioctl OK\n" );
for ( i = 0; i < 16; ++i ) {
printf( "%c", buffer[i] );
}
printf( "\n" );
}
...