Electronic – I2C read/write failure under heavy interrupt load

i2c

In my system, I am using I2C and I realize under heavy interrupt load (from other sources), I2C communication is easily disrupted. Is this expected behavior for I2C? I would have expected despite interrupt load, it would still be ok since I2C is not exactly a time critical interface, clock is provided with data.

Update:

The processor is STM32. The interrupts are due to ADC, I cannot disable interrupts during the read events therefore I must find a solution where I can make the i2c communication more stable. The STM32 is master and the slave is another device (accelerometer).

Update2:

When I connect a logic analyzer to the clock with a small flying cable, the problem disappears. Interestingly, there is no interrupt load, read write works well, when there is interrupt load, they don't. However, if I attach the probe to the clock, read write works under interrupt load as well. I think, there is a capacitance issue somewhere.

Best Answer

This is a software issue, you are spending too much time servicing interrupts & your I2C routine is not able to handle it (so that's two things which are not right). I have been through several similar situations.

First: You need to do as little as possible in the interrupts, only read & store the data, don't do any processing that you could do outside the ISR, maths can take a LOT of CPU cycles and the CPU cannot do anything else while in that interrupt.

Second: Investigate DMA to automate things, so your interrupts become almost a background automated process.

Third: If I2C is important, put THAT in an interrupt too, but make sure you work out the priorities!

Fourth: Work out why your I2C routine is failing, I2C itself can stand up to very intermittent timings, pauses & waits etc. so your routine may need modifying to allow this.

Fifth: See if you can "chain" interrupts, you may find you can service the ADC reads more efficiently, or put the ADC in a different mode where it does more work for you before interrupting (EG wait for all readings to be available, then read all in one hit, rather than 8 separate interrupts for 8 separate ADC channel reads).

Sixth: Use an oscilloscope or logic analyser, and spare IO pins on the board, to trace how much time you're spending in each bit of code, to see if you can speed it up. (Set pin high when you enter a function/ISR, set it low again on exit).

Seventh: Decide if you really need to read the ADC so much, will going slower make things worse? It's counter-intuitive but sometimes running slower actually gives nicer results, doing the work of averaging the signal for you and cutting down on spikes/transients which could cause problems or require extra processing to remove. We improved a motor control PID routine by simply running it 1/4 the speed, freeing up a load of CPU time in the process.