Helpful I2C Observations

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

Helpful I2C Observations

1,881 Views
geoffreyfurman
Contributor I

I just fixed an i2c bug in our system and thought I would post my observations.

Observation 1

The datasheet for the JM60 says the only sources of I2C interrupts are:

 

TCF Transfer complete flag

ARBL Arbitration lost

IASS Addressed as slave

 

We had an I2C master entering the ISR with NONE of these bits set.

Upon inpsection we found that MST was 0 indicating that the master was no longer the master for an unspecified reason.

 

Observation 2

The problem was caused by an I2C timing violation, SCL and SDA rising simultaneously, which was occasionally interpreted as a STOP condition.

The timing violation was generated by the master during a read cycle when the bus turn around occurred.

My code was originally:

 

IICC1_TX = 0;     //Place the bus in master receiver mode

dummy = IICD;    //Release the bus to perform the read cycle

With this code a condition on the bus can occur where SDA and SCL rise together which is not allowed on the I2C bus.

Granted that SDA nominally leads SCL by the time of the instruction but on the slow rising I2C bus confusion can occur.

 

I modified it as such:

 

IIC1_TX = 0;

__asm NOP;

__asm NOP;

__asm NOP;

__asm NOP;

dummy = IICD;

 

When you do this you will see on the oscope that SDA clear rises in advance of SCL preventing the timing violation.

The number of NOPs may be dependent on how soft the pullups are.  I chose a number that was clearly resolvable on the oscope.

Labels (1)
Tags (3)
1 Reply

701 Views
geoffreyfurman
Contributor I

Okay the one thing I know for sure is that as soon as I make a statement I will prove myself wrong.

The last email is erroneous.  This is the best answer that I have from 2 more days of testing........

The I2C slave logic does not properly time the data to clock setup on the first bit (bit 7) shifted out.

When the slave writes to IICD it puts D7 onto the bus and releases the clock simultaneously.  This violates a data setup time specified in the I2C specification of 4-5us for 100KHz mode or 0.6us for 400KHz mode.

You will not see this condition IF the slave releases SCL BEFORE the master releases SCL  The difference in time must be the setup time you require.

You can see this if you delay the slave writing to the IICD until after the master releases SCL.  In our case this was the difference between writing to IICD ASAP and calling a subroutine to supply the data.  As always, your results will vary.

WHY IS THIS A PROBLEM?

We had code the was running for years and started a new development where all of sudden I2C reads did not work at all.  The change was a reasonable change but IT DID NOT WORK.  Because we violated the setup time the master erratically detected a STOP on the bus and failed to complete the transaction.

SOLUTION:

This is a real solution that should work ALL THE TIME without special timing considerations.

We have an extra port pin on the slave's SCL which we use to stretch SCL manually.  When it is time to write to IICD (SCL is already low) we:

1. Drive SCL low via the port pin

2. Write to IICD.  SDA will respond immediately but clock is held off by the port pin OR the master.

3. Wait desired setup time and release SCL via the port pin (make it an input)

The desired delay you choose can be I2C specified setup time but in all reality most devices will be happy as long as some setup is provided for SDA to SCL.

This solution will work for fast/slow masters or fastd/slow slaves.  It is a robust fix.