photomankc
Posts: 74
Joined: Fri Aug 24, 2012 12:58 pm

i2c repeated start transactions

Tue Aug 28, 2012 3:58 am

Lord.... maybe I should go back to the world of the MicroController.

I have a sensor I want to read through /dev/i2c-0. It's an IMU device that in order to read any data from the device I MUST be able to specify the register I want to read from first. So to read register I need to do:
| START | WR ADR | REG | REP_START | RD ADR | BYTE | STOP |

The basic read() can not do this. It will only issue the device read address and has no capacity to do the initial write of the register address plus repeated start I need. The device will not respond to a read with no register proceeding it. I looked into some userspace Linux I2C examples that make use of:
i2c_smbus_read_i2c_block_data()

However attempting to use that results in an "undeclared in this scope" message even when I have the same headers listed as the examples. I'm not sure where I go from here? I have to be able to issue a repeated start for several of the devices I use but I can't find any example that doesn't use those smbus funtion calls.

User avatar
PeterO
Posts: 3557
Joined: Sun Jul 22, 2012 4:14 pm

Re: i2c repeated start transactions

Tue Aug 28, 2012 11:02 am

I used the examples here to get me started with writing i2c code on my Pi.
http://www.robot-electronics.co.uk/htm/ ... amples.htm
HTH

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

photomankc
Posts: 74
Joined: Fri Aug 24, 2012 12:58 pm

Re: i2c repeated start transactions

Tue Aug 28, 2012 2:57 pm

Thanks Peter,

Unfortunately that covers the same ground with read() and write() which don't support the 'combined write/read' operations needed. What I ended up doing was sucking down a copy of the i2c-dev.h file from older versions of the LM-Sensors project that had the function definitions for the i2c_smbus* functions. That has made the compiler happy for now so I can at least move forward to getting a test going to see if I can read the registers on the IMU.

The Parallax microcontroller I wrote I2C driver code for was much more flexible but I think there is enough present in those functions to get what I need out of the majority of devices I would be connecting with it.

User avatar
PeterO
Posts: 3557
Joined: Sun Jul 22, 2012 4:14 pm

Re: i2c repeated start transactions

Tue Aug 28, 2012 3:15 pm

Maybe I'm misinterpreting your sequence
| START | WR ADR | REG | REP_START | RD ADR | BYTE | STOP |

but to me that looks like the sequence used to read a register from a MCP23017.
See http://ww1.microchip.com/downloads/en/D ... 21952b.pdf


Did you look at this example ?
http://www.robot-electronics.co.uk/files/rpi_srf08.c
At the end it seems to do what you are trying to do, it writes a register address and then reads multiple bytes back from the device.

In which case it can be done with just read and write, but I'm still an i2c noob so I may have missed something :-)

What exactly is the device you are communicating with ?

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
joan
Posts: 12705
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: i2c repeated start transactions

Tue Aug 28, 2012 3:27 pm

Sounds similar to the functionality which seems to be provided by the I2C_RDWR ioctl

Code: Select all

/* This is the structure as used in the I2C_RDWR ioctl call */
struct i2c_rdwr_ioctl_data {
	struct i2c_msg __user *msgs;	/* pointers to i2c_msgs */
	__u32 nmsgs;			/* number of i2c_msgs */
};

photomankc
Posts: 74
Joined: Fri Aug 24, 2012 12:58 pm

Re: i2c repeated start transactions

Tue Aug 28, 2012 6:09 pm

PeterO wrote: Did you look at this example ?
http://www.robot-electronics.co.uk/files/rpi_srf08.c
At the end it seems to do what you are trying to do, it writes a register address and then reads multiple bytes back from the device.
Close, but that will not work. The write function will STOP the bus when it completes. A repeated start is a START condition that is given without a previous STOP being issued. The IMU will not properly respond if you do this:
| START | WR ADR | REG | STOP | | START | RD ADR | BYTE | STOP |

The i2c_smbus_* functions I got my hands on are wrappers around the ioctl function that does what I'm looking for but until I found the code I wasn't clear about that. It just makes it a little easier to work with it. All the other functions come back to this one with the right parameters.

Code: Select all

	extern inline s32 i2c_smbus_access(int file, char read_write, u8 command, 
50	                                   int size, union smbus_data *data)
51	{
52	  struct i2c_smbus_data args;
53	  int res;
54	
55	  args.read_write = read_write;
56	  args.command = command;
57	  args.size = size;
58	  args.data = data;
59	  return ioctl(file,I2C_SMBUS,&args);
60	}

..
..
..

extern inline s32 i2c_smbus_read_byte_data(int file, u8 command)
83	{
84	  union smbus_data data;
85	  if (i2c_smbus_access(file,SMBUS_READ,command,SMBUS_BYTE_DATA,&data))
86	    return -1;
87	  else
88	    return 0x0FF & data.byte;
89	}
the linux/i2c-dev.h header does not define these functions. The [command] value is what I need. It's the value that follows the write address to specify the register and then a repeated start is issued and the read address is sent and the byte is collected.

The device is a Pololu Mini-IMU9. 3 axis accelerometer, gyro, and compass.

User avatar
PeterO
Posts: 3557
Joined: Sun Jul 22, 2012 4:14 pm

Re: i2c repeated start transactions

Tue Aug 28, 2012 6:33 pm

Right, I'm with you now 8-)
PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),Aeromodelling,1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
Gert van Loo
Posts: 2407
Joined: Tue Aug 02, 2011 7:27 am
Contact: Website

Re: i2c repeated start transactions

Tue Aug 28, 2012 8:13 pm

Hi guys,
just a general remark. We know there is a bug in the I2C hardware where the clock streching is
not working at arbitrary points. It is working during the ack phase.
We did not test the I2C master under all possible conditions. Just keep that in mind
when something continuously, repeatedly refuses to work.

Tripel Hop
Posts: 10
Joined: Wed Jun 27, 2012 12:12 am

Re: i2c repeated start transactions

Tue Aug 28, 2012 9:25 pm

I did some direct programming of the I2C controller (BSC0) from user-space. It occured to me the BCM2835 doesn't support I2C repeated start. See the BCM2835 datasheet chapter 3 for more information.

ksangeelee
Posts: 192
Joined: Sun Dec 25, 2011 5:25 pm
Location: Edinburgh, UK
Contact: Website

Re: i2c repeated start transactions

Tue Aug 28, 2012 10:05 pm

Tripel Hop wrote: I did some direct programming of the I2C controller (BSC0) from user-space. It occured to me the BCM2835 doesn't support I2C repeated start. See the BCM2835 datasheet chapter 3 for more information.
I'd reached that conclusion myself a while back, but I wonder if there isn't a way to make the peripheral do effectively do a restart by just starting a read after a write.

I'm thinking along the lines of a write with DLEN set to 2, for example, but only one byte written to the FIFO. When either DLEN transitions to 1, or when TXE (or TXW) is asserted, then set up a read and start a transfer (C.ST | C.CLEAR | C.READ) - perhaps after waiting enough time for the underlying TX register to shift the bits out.

I can't try this myself at the moment (trying hard not to get distracted from a de-clutter exercise on my desk), but thought I'd at least suggest it as a possible option.

Tripel Hop
Posts: 10
Joined: Wed Jun 27, 2012 12:12 am

Re: i2c repeated start transactions

Tue Aug 28, 2012 11:11 pm

ksangeelee wrote:
Tripel Hop wrote: I did some direct programming of the I2C controller (BSC0) from user-space. It occured to me the BCM2835 doesn't support I2C repeated start. See the BCM2835 datasheet chapter 3 for more information.
I'd reached that conclusion myself a while back, but I wonder if there isn't a way to make the peripheral do effectively do a restart by just starting a read after a write.

I'm thinking along the lines of a write with DLEN set to 2, for example, but only one byte written to the FIFO. When either DLEN transitions to 1, or when TXE (or TXW) is asserted, then set up a read and start a transfer (C.ST | C.CLEAR | C.READ) - perhaps after waiting enough time for the underlying TX register to shift the bits out.

I can't try this myself at the moment (trying hard not to get distracted from a de-clutter exercise on my desk), but thought I'd at least suggest it as a possible option.
I wouldn't go that way. Back in the C64 days one could try and actually succeed in fooling the hardware. That worked because you knew the exact timing of your system and your software.

With a pre-emptive scheduling Linux inbetween, with software interrupts flying around and an application processor relying on on-chip cache memories, the whole thing has become asynchronous so one can't achief this exact timing in software anymore.

If the repeated start is required on the rpi, the best you can do is bypass the BSC0 and start bit-banging the I2C protocol yourself, just as you would do with an 8051 or any other cpu without I2C controller. The I2C protocol is full-state so you can easily do that from Linux user-space without having to worry about exact timings.

Tripel Hop
Posts: 10
Joined: Wed Jun 27, 2012 12:12 am

Re: i2c repeated start transactions

Tue Aug 28, 2012 11:33 pm

photomankc wrote:Close, but that will not work. The write function will STOP the bus when it completes. A repeated start is a START condition that is given without a previous STOP being issued. The IMU will not properly respond if you do this:
| START | WR ADR | REG | STOP | | START | RD ADR | BYTE | STOP |
If this is true, then the IMU is not compliant with the I2C specification. Sending STOP/START or REPEATED START is the decision of the I2C master, the I2C slave must behave the same in both cases.

ksangeelee
Posts: 192
Joined: Sun Dec 25, 2011 5:25 pm
Location: Edinburgh, UK
Contact: Website

Re: i2c repeated start transactions

Wed Aug 29, 2012 1:07 am

Tripel Hop wrote:
ksangeelee wrote:
I'm thinking along the lines of a write with DLEN set to 2, for example, but only one byte written to the FIFO. When either DLEN transitions to 1, or when TXE (or TXW) is asserted, then set up a read and start a transfer (C.ST | C.CLEAR | C.READ) - perhaps after waiting enough time for the underlying TX register to shift the bits out.
I wouldn't go that way. Back in the C64 days one could try and actually succeed in fooling the hardware. That worked because you knew the exact timing of your system and your software.
Given what you said about the possibility of user space bit-banging, if it turns out that DLEN=2 and one FIFO push results in TXE raised and the BSC0 stalled waiting for more data in the FIFO, then timing may not be an issue as long as there's a delay at least long enough for the shift-register to complete before triggering the read.

photomankc
Posts: 74
Joined: Fri Aug 24, 2012 12:58 pm

Re: i2c repeated start transactions

Wed Aug 29, 2012 6:05 am

Tripel Hop wrote: If this is true, then the IMU is not compliant with the I2C specification. Sending STOP/START or REPEATED START is the decision of the I2C master, the I2C slave must behave the same in both cases.


Well, you may be correct here. The datasheet for the devices on the IMU clearly calls out a repeated start as being required. However a quick check of the scope after getting this talking tonight also clearly shows that device is in fact working just as expected despite the fact that the I2C hardware is generating at | STOP | START | and not a repeated start.

I know my PICAXE 20M2 based slave controller on another project is picky about that. It will not allow you to read a register location if you stop, it will reset to zero and the subsequent read starts there, not the register you wrote. It appears this device is not so picky. I am definately reading and writing the proper registers despite the lack of the repeated start.

Tripel Hop
Posts: 10
Joined: Wed Jun 27, 2012 12:12 am

Re: i2c repeated start transactions

Wed Aug 29, 2012 4:42 pm

ksangeelee wrote:
Tripel Hop wrote:
ksangeelee wrote:
I'm thinking along the lines of a write with DLEN set to 2, for example, but only one byte written to the FIFO. When either DLEN transitions to 1, or when TXE (or TXW) is asserted, then set up a read and start a transfer (C.ST | C.CLEAR | C.READ) - perhaps after waiting enough time for the underlying TX register to shift the bits out.
I wouldn't go that way. Back in the C64 days one could try and actually succeed in fooling the hardware. That worked because you knew the exact timing of your system and your software.
Given what you said about the possibility of user space bit-banging, if it turns out that DLEN=2 and one FIFO push results in TXE raised and the BSC0 stalled waiting for more data in the FIFO, then timing may not be an issue as long as there's a delay at least long enough for the shift-register to complete before triggering the read.
So you want the write transfer to end up waiting for more data and then reprogram BSC0 with a read transfer, right?

You can use usleep() to wait for the depletion of the shift-register. The value given to usleep() is a minimum wait time you can calculate, because you know the clock speed (on SCL) and you know the number of bits that will go over the I2C bus. One problem: you've to be sure the I2C slave won't stretch the clock line while BSC0 is executing the write transfer, else timing is a problem again.

If you want to go this way, be sure the BCM2835 will behave as you expected all the time. You may want to check the SDL and SDA lines with an oscilloscope just to be sure the BCM2835 won't generate spikes or so on these lines while your software is reprogramming the write transfer into a read transfer. After all it's not documented in the datasheet.

ksangeelee
Posts: 192
Joined: Sun Dec 25, 2011 5:25 pm
Location: Edinburgh, UK
Contact: Website

Re: i2c repeated start transactions

Wed Aug 29, 2012 6:48 pm

Tripel Hop wrote: So you want the write transfer to end up waiting for more data and then reprogram BSC0 with a read transfer, right?

You can use usleep() to wait for the depletion of the shift-register.
Yes, that's what I had in mind. A further thought that occurred to me was to use S.TA (Transfer Active) to detect when the controller has gone idle, assuming that 'idle' in the datasheet means 'not transferring any bytes' rather than just the opposite of S.DONE. The datasheet is vague on a lot of the BSC, so it would need to be tried to be sure.

Tripel Hop
Posts: 10
Joined: Wed Jun 27, 2012 12:12 am

Re: i2c repeated start transactions

Wed Aug 29, 2012 11:13 pm

ksangeelee wrote:
Tripel Hop wrote: So you want the write transfer to end up waiting for more data and then reprogram BSC0 with a read transfer, right?

You can use usleep() to wait for the depletion of the shift-register.
Yes, that's what I had in mind. A further thought that occurred to me was to use S.TA (Transfer Active) to detect when the controller has gone idle, assuming that 'idle' in the datasheet means 'not transferring any bytes' rather than just the opposite of S.DONE. The datasheet is vague on a lot of the BSC, so it would need to be tried to be sure.
I haven't used the S.TA bit so far, just the S.DONE bit, but it may be the clue to a rock solid solution. My understanding from the datasheet is that condition S.TA=0 & S.DONE=0 indicates a stalled transfer waiting for FIFO access but again I haven't used this state.

Have a look at the C source code of the Axiris Abiocard here: http://www.axiris.be/download/abiocard/abiocard.tar.gz It may come in handy for your own testing purposes. I used chunks of this source code myself for checking out certain things about the BSC by adding lots of printf() statements.

cdan
Posts: 5
Joined: Tue Nov 27, 2012 12:09 pm

Re: i2c repeated start transactions

Thu Jan 03, 2013 8:34 pm

Hello,
I am stuck on this problem too, with a MLX90614. Isn't there any way to get support from Broadcom on this matter?

Best regards,
Dan.

MrMarkus
Posts: 33
Joined: Sat Sep 22, 2012 9:07 am

Re: i2c repeated start transactions

Wed Jan 16, 2013 10:44 am

Hi all,

We got stuck on this too while testing the PiXi-200 add-on board. I hope to be able to find a solution where the I2C can be 'tweaked' through the FPGA we have on the PiXi-200 before the I2C bus gets to the MMA7660 or MAG3110 we have on the board. In our case the FPGA works as an I2C 'switch' which distributes the I2C bus to a separate bus for each slave so we have the ability to 'tweak' the bus if needed.

However, the simple work-around that we ended up using was to simply read a block of 3-8 or more registers, starting at addres 0x00 each time.

If you do a (dummy) write to the slave to set the read address - note the I2C 'stop' will reset the internal address to zero after sending the (dummy) read address, which is what we want to happen for the work-around. Then implement (say) a 3-8 byte read from the slave. You can then get extract the data from the address you're interested in based on the byte position in the stream of bytes you get back.

Single writes or multiple writes should work, I think it's only reads to specific addresses that become a problem because of the 'repeated start' issue.

Someone just came up to me just 10 minutes ago showing that he'd got the accellerometer running in this manner on the PiXi-200, and was able to demonstrate a simple digital spirit level.

Hopefully you can use a similar work-around.

Best regards,

Mark

penguin1024
Posts: 6
Joined: Sun Dec 30, 2012 3:50 pm

Re: i2c repeated start transactions

Sun Mar 03, 2013 11:13 am

Hi all,
We had the same issue when trying to read an ADT7410 temperature sensor. The datasheet says we need to send a repeated start to read a specific adress on the chip.
It looks like the Raspberry Pi doesn't support repeated start - on the oscilloscope it shows, as mentioned in the previous posts, a | STOP | START | signal instead of a repeated start.
Writing works well, because no repeated start condition is called.
We used the "bus.read_word_data()" function in python-smbus to read the first word, which contains the full temperature data.
It looks like there's a bigger issue somewhere in the base I2C driver or in the BCM2835.
It might be possible to bypass this issue by using standard GPIO pins and manually sending the clock and the signals, but it's a somewhat complicated way.
I hope it will be fixed someday - it's a quite big issue, as many I2C-compliant chips need the repeated-start condition.
Good luck to you all with your projects!
penguin1024

techpaul
Posts: 1514
Joined: Sat Jul 14, 2012 6:40 pm
Location: Reading, UK
Contact: Website

Re: i2c repeated start transactions

Sun Mar 03, 2013 10:37 pm

Most devices that 'claim' they need a repeated start dont, they CAN work with repeated start but WILL work with start stop.

Suggest you look at this page for an understanding of python-smbus transactions that are supported.

Beyond that look for other libraries or methods for talking to Linux I2C driver
Just another techie on the net - For GPIO boards see http:///www.facebook.com/pcservicesreading
or http://www.pcserviceselectronics.co.uk/pi/

penguin1024
Posts: 6
Joined: Sun Dec 30, 2012 3:50 pm

Re: i2c repeated start transactions

Mon Mar 04, 2013 6:01 pm

Hi there!
First, thank you for your answer.
I already checked if the device would work with a start/stop condition, but it resets the pointer to 0 after each stop signal.
Python-smbus documentation is quite limited, the following page is the only one i found with a full list of commands supported:
http://wiki.erazor-zone.de/wiki:linux:python:smbus:doc

We have tried some other ways using C, but it also failed (same issue). We'll keep looking for other libraries/ways to do it.
Thank you very much
penguin1024

techpaul
Posts: 1514
Joined: Sat Jul 14, 2012 6:40 pm
Location: Reading, UK
Contact: Website

Re: i2c repeated start transactions

Mon Mar 04, 2013 7:20 pm

Try reading this document http://git.kernel.org/cgit/linux/kernel ... s-protocol I linked before, failing that you need to look up I2C driver details

Look at detailed documents for Wiring Pi and other libraries
Just another techie on the net - For GPIO boards see http:///www.facebook.com/pcservicesreading
or http://www.pcserviceselectronics.co.uk/pi/

penguin1024
Posts: 6
Joined: Sun Dec 30, 2012 3:50 pm

Re: i2c repeated start transactions

Tue Mar 05, 2013 7:44 pm

techpaul wrote:Try reading this document http://git.kernel.org/cgit/linux/kernel ... s-protocol I linked before, failing that you need to look up I2C driver details

Look at detailed documents for Wiring Pi and other libraries
I thought something was missing in your reply :lol:
Thank you, i'll have a look.
penguin1024

wallasey
Posts: 25
Joined: Fri Nov 16, 2012 5:10 pm

Re: i2c repeated start transactions

Mon Mar 18, 2013 1:02 am

Hi,

Browsing the Broadcom manual, I saw that the BSC peripheral supports 10 bit addressing by use of a repeated start. The method described just polls for 'transfer active' after initiating a write transfer, then sends a read.

It seems to work for me with the Freescale MPL3115A2.
A solution is part of a bundle of Perl modules I release at http://raspberry.znix.com/, but the C part is now part of the bcm2835 library - see bcm2835_read_register_rs at http://www.open.com.au/mikem/bcm2835/group__i2c.html

Hope it helps

Return to “Interfacing (DSI, CSI, I2C, etc.)”

Who is online

Users browsing this forum: Kubas_inko and 6 guests