I2C Timing Collisions

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

I2C Timing Collisions

5,029 Views
eric_escobar
Contributor I

Hi,

I'm running FreeRTOS and I have two independent threads (of the same priority) running I2C communications for two separate I2C buses on a K64 family microcontroller. Each thread polls a device and then sleeps for 1000 ms. 

When the two threads are started via the vTaskStartScheduler() call, they run near concurrently, and after a few minutes one of the I2C busses is hung. I grabbed a  couple scope captures and show that the clock signal seems to be corrupted. See "communication_failed_1.png" and "communication_failed_2.png"

However I staggered the threads such that one had an initial delay so that the two threads ran near sequentially, and there never was an issue with the communication. See "staggered_thread_start.png".

Has anyone observed something like this? Is there a configuration required to allow communication on two independent I2C busses to run concurrently?

0 Kudos
Reply
6 Replies

5,016 Views
eric_escobar
Contributor I

Hi Erich,

Thanks for the response. I do believe they are strong enough, the I2C lines are pulled up to 3.3V via 2.2k resistors.

I agree, it looks like some cross talk, however I was attributing that to coupling with the scope probes.

 

0 Kudos
Reply

5,011 Views
ErichStyger
Specialist I

2.2k sounds good (in many cases only 4.7k are used and are usually good too).

I'm wondering if you are doing anything special in your I2C transmit/receive operations (maybe changing the I2C hardware somehow). I would make sure and check if plenty of stack/memory is allocated for each task, just to get a possible memory/stack overflow out of the equation. Just a rough guess.

0 Kudos
Reply

5,003 Views
eric_escobar
Contributor I

Hi Erich,

I doubled checked, and each task is only using 25-30% of its allocated stack, so I don't think its a memory/stack overflow.

The I2C buses are configured in the auto generated board.c/peripherals.c files.

As for the transmit receive operations, I'm using the I2C_RTOS_Transfer() API. I set up the transfer structure and then call the API function. The microcontroller is continuously polling various status parameters from the slave devices. I have the following code snippet repeated for the ~20 status parameters, then the task sleeps for 1 second and then polls again.

The communication does work for a few seconds then after a few minutes one of the two buses hangs.

// Make sure bus is not in use
i2cStatus = I2C_MasterGetStatusFlags(busId);
while (kI2C_BusBusyFlag & i2cStatus)
{
    i2cStatus = I2C_MasterGetStatusFlags(busId);
}
// Set up Transfer Structure
masterXfer.direction = kI2C_Read;
masterXfer.subaddress = 0x8B;
masterXfer.data = (uint8_t*)&status;
masterXfer.dataSize = 2;
// Initiate Transfer
I2C_RTOS_Transfer(i2cX_RtosHandle, &masterXfer);

 

0 Kudos
Reply

4,978 Views
ErichStyger
Specialist I

I think I cannot comment much. Have mostly used a single I2C bus with multiple tasks, and using a mutex to implement the serialization. I have a few applications using two different I2C on Kinetis, accessed each by multiple tasks, and guarded with mutex too, and never faced such a problem.

But I have not used that I2C_RTOS_Transfer() API: I always used a direct API guarded with that above mutex. Not sure if this helps.

0 Kudos
Reply

5,008 Views
bobpaddock
Senior Contributor III

"maybe changing the I2C hardware somehow"

A lot of Freescale/NXP example code uses |= (OR) rather than = (Assignment) for "Write 1 to clear".
At best this wastes space and time, at worse it clears unexpected bits.

 

0 Kudos
Reply

5,023 Views
ErichStyger
Specialist I

Are your pull-ups strong enough? At least some signals show some kind of cross-talk (not sure from the pictures).

I would check if using stronger (external, of course) pull-ups will help.

0 Kudos
Reply