How to clear I2C busy status

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

How to clear I2C busy status

17,376 Views
petershih
Contributor III

Hi:

I am working on I2C driver for our system with Kinetis K65 MCU (MK60FN1M0VLQ15) with CW 10.6. MCU works as master and communication with other peripherals on the line like temperature sensor, pressure sensor, accelerometer. The driver is developed based on the example provided from "C:\Freescale\CW MCU v10.6\MCU\CodeWarrior_Examples\Kinetis_Examples\k60\i2c\Sources" and operates pretty well. However, since we have some hardware noisy on the line and sometimes make I2C failure. My task is if I can detect the failure condition happened and clear it.

I was able to find whenever failure condition happened, the data line is low, and "busy" flag is set in the i2c status register. (See the attachment for detail). I am always able to reset the MCU to clear the issue, which means the data line is not holding by any I2C slave. I have tried to clear the busy flag by reissue "start" and "stop" condition, disable I2C module, turn off I2C clock. re-declare as GPIO output and try to bring them high on purpose, However, the signal lever doesn't change, and as soon as I enable the I2C module, the busy flag is set right away. If you have any recommendation, please let me know. Thank you very much.

pastedImage_0.bmp

Tags (3)
7 Replies

7,184 Views
mjbcswitzerland
Specialist V

Chris

Your customer's case is a result of the slave driving the lines due to the master stopping its operation half-way through. This is something that can always happen in every system since slave devices are not connected to the processor's reset line and so every I2C driver needs to have such a dead-lock recovery mechanism otherwise the "product" will at some point likely fail (due to a reset during data transfer at a critical point in time) and only recover after a power cycle.

Many drivers (eg. KSDK, PE generated etc.) don't have this mechanism and so it is necessary to add it to achieve a reliable product, as your customer has already found out (maybe the hard way)....

More details at

I2C device dead-lock recovery

Regards

Mark

7,184 Views
chris_brown
NXP Employee
NXP Employee

Hi Peter,

Has this issue been resolved?

If not, we have another customer that has experienced a similar issue.  I do not think they are experiencing exactly the same thing, but you could try this (as it did work for them).

i2c_master_state_t master;

void

init_i2c_master( void )

{

  uint8_t i;

  //Initialize the I2C master mode driver

  I2C_DRV_MasterInit(I2C_PORT_0, &master);

  // Experiencing I2C communications lockup when during the I2C communications,

  //  the processor experiences brownout  or is put into a low power state because of loss of power.

  //  Toggling the clock after initializing i2c to fix the problem.

  //  Set PTE24 (I2C0_SCL) as GPIO output.

  PORT_HAL_SetMuxMode(PORTE,24u,kPortMuxAsGpio);

  GPIO_HAL_SetPinDir(GPIOE, 24, kGpioDigitalOutput);

  // Set PTE25 (I2C0_SDA) as GPIO Input

  PORT_HAL_SetMuxMode(PORTE,25u,kPortMuxAsGpio);

  GPIO_HAL_SetPinDir(GPIOE, 25, kGpioDigitalInput);

  // Generate 12 clcok cycles at the same freq as is normally used

  //  (toggle line high and low)

  for(i=0; i<12; i++)

  {

  GPIO_HAL_SetPinOutput(GPIOE, 24);

  delay_usec(125);  // I2C is running at 4 kbit/s. 4 KHz freq ==> 250 usec.

  GPIO_HAL_ClearPinOutput(GPIOE, 24);

  delay_usec(125);

  }

  // Set the I2C0_SCL line high

  GPIO_HAL_SetPinOutput(GPIOE, 24);

  // Initialize IO pins as I2C

  configure_i2c_output_pins(I2C_PORT_0);

}

Please let me know if this works.

Thanks,

Chris

7,184 Views
chris_brown
NXP Employee
NXP Employee

Hi Peter,

What are the values of your pull-up resistors?

Also as I mentioned before, it seems that the *SLAVE* is unable to perform its duties in the acknowledge phase.  So, does this happen with a shorter wire length?

When you see the failure, can you unplug the slave (need to make sure that your pull-ups will still be connected to the master when you do this)?  What do the I2C lines do then? 

Do you have any other details about when/how this lockup is happening?  Are you entering a low-power mode?  Is a brownout condition happening? 

Thanks,

Chris

0 Kudos

7,183 Views
chris_brown
NXP Employee
NXP Employee

Hi Peter,

It doesn't appear to me that your pins are floating. The clock and data lines appear to be getting pulled to solid highs and lows. From the oscilloscope capture you have, it appears that the slave is unable to acknowledge /not-acknowledge the address that you are putting on the bus.  This suggests that you have some other kind of contention on the bus.  Are you able to share your schematics?  It would be good to at least see the I2C portion of your schematic.  If not, can you give a good, detailed, specific description of what's on the bus and what values you are using for all resistors and capacitors (if any) attached to the I2C bus?

It may also be that your I2C pins are configured as push-pull input/output as opposed to open-drain (as they should be).  Can you make sure that your ODE bit is set in the PCR register of the I2C pins that you are using?

One more thing that we noticed is that a high value of the clock line is at a significantly lower voltage than that of the data line (i.e., Data line high voltage is ~3.3V,  Clock line high voltage is <3.0V).  Can you explain why that is?  This should not be the case in a well put together I2C bus. 

Thanks,

Chris

0 Kudos

7,184 Views
petershih
Contributor III

Hi Chris:

Thanks your reply. We do have pull-up resister on the bus. However, we are using the I2C bus on a long wire, more than 50 ft, which probably out of specification. Our hardware engineer is working on it to improve the performance.

You mentioned "ODE" option on the GPIO output. Since we are using the port as I2C, I didn't declare the port with ODE enabled. I have tried to declare output with ODE bit set, before turn on I2C. I didn't see the situation improved. I am still get some lockup situation happened.

You also mentioned the voltage level problem. Our hardware engineer is trying to look for the cause of the problem, It seems some of the boards ave problem. Thank your very much to point out this potential problem.

However, as firmware development, we would like to see if we can detect failure and recover it. As I mentioned before, both SDA and CLK line level are normaI. I just don't understand why I cannot clear the busy flag even though disable I2C module and turn off I2C clock. Hope I didn't miss any procedure. Thanks your help.

0 Kudos

7,184 Views
mjbcswitzerland
Specialist V

Hi

It looks like the data line is floating and doesn't have a pull-up connected (?)

The uTasker I2C driver has been used in many products with I2C and in one case, with intensive I2C master usage, there were occasional busy line conditions which were however signalled by arbitration loss (in a master only environment - on a KL43, which I think has the same I2C controller revision as the K65).

The "workaround" that has proven to be reliable is the following:

        while ((ptrI2C->I2C_S & I2C_IBB) != 0) {                         // wait until the stop has actually been sent to avoid a further transmission being started in the mean time
            if ((ptrI2C->I2C_S & I2C_IAL) != 0) {                        // arbitration lost flag set
                ptrI2C->I2C_S = I2C_IAL;                                 // clear arbitration lost flag
                ptrI2C->I2C_C1 &= ~(I2C_IEN);                            // disable I2S to clear busy
                fnDelayLoop(100);                                        // short delay before re-enabling the I2C controller (without delay it doesn't generate any further interrupts)
                ptrI2C->I2C_C1 |= (I2C_IEN);                             // re-enable
            }
        }

Although your case may be different.

Regards

Mark

0 Kudos

7,184 Views
petershih
Contributor III

Hi Mark:

Thanks your reply. Our system is operating under one master device only. On the other hand, when the issue happened, the "ARBL" bit of the status register is clear. It doesn't look like the "arbitration loss" situation happened. Thank you very much!

0 Kudos