This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

c6713b - External Slave Device Hanging the Bus by Holding SDA Low

I have some problems with I2C0 on the c6713b.

 

Sometimes the Bus is hanging and SDA ist Low  until I toggle the SCL Line manually. Now I am trying to do this as described in the I2C Tips but it doesn't seem to work.

 

http://processors.wiki.ti.com/index.php/I2C_Tips

Option 2: Many devices don't mux SCL/SDA with GPIO since the I2C I/O cells are often special open drain cells. A workaround has been reported to work even on these devices. By configuring the I2C for "free data format" and then reading a byte the I2C will immediately start sending clocks to input data (rather than trying to send an address). This can be used to free up the bus.

 

Does anyone know how to send clocks on SCL even if SDA is held low?!

 

thx fabi

 

  • What happened when you tried option 2? Did the SCL line not toggle?

    In what cases does the bus hang? Is it when the device resets during an I2C transfer? If so your best option might be to prevent that from happening in the first place.

    Jeff

  • > What happened when you tried option 2? Did the SCL line not toggle?

    Exactly! The SCL line is not toggling. I tried this by holding SDA low (short-circuit to ground). I think my configuration for reading in free-data-format is ok, because I can read and see SCL toggle while SDA is not Low. Is there a special configuration to read/send while SDA is held Low?

     

    > In what cases does the bus hang? Is it when the device resets during an I2C transfer?

    The bus hangs only sometimes, during normal operation. I don't reset the device and I don't reset the I2C Bus...

     

    I made a log with a logic-analyzer. When the bus hang occurs, the c6713 seems to toggle only 7 bits instead of 8 +1 ack/nack. As you can see SDA is Low after that. I can recover from this state  by short-circuit SCL to ground for one time!

     

                 

     

    Hope you can help!

     

    -Fabian

  • It looks like its the C6713 holding the SDA low rather than the slave device. What happens if you reset the chip in this state, does the SDA line go back high?

    Jeff

  • Also can you send a dump of the I2C registers so we can see if any arbitration errors showed up?

    Jeff

  • > It looks like its the C6713 holding the SDA low rather than the slave device. What happens if you reset the chip in this state, does the SDA line go back high?

    No, doesn't help, SDA stays Low during a reset of the DSP. Also resetting I2C0 by software doesn't help.

     

    > Also can you send a dump of the I2C registers so we can see if any arbitration errors showed up?

    I get an arbitration error when I try to send/read while SDA is low. I will send you the dump of the I2C registers in a few minutes...

     

     

  • I made a printf with the registers STR and MDR. Do you need other registers? I can't do it over JTAG at the moment...

     

         -> I2C0 AL Error -   STR: 0x00000400    MDR: 0x00004a20

     

    -Fabian

  • As you can see, there is no AL bit set in STR. I made a mistake by reading the register not in the interrupt service routine... Here are the right values:

     

    I2C0 NACK - STR: 0x00001404 MDR: 0x00004620

    This is a NACK error, because one of the slaves is not connected to the bus.

     

    I2C0 AL Error - STR: 0x00001400 MDR: 0x00004220

    This is the first AL error. It seems to be different from the next one I receive.

     

    I2C0 AL Error     - STR: 0x00001410 MDR: 0x00004220

    Every following AL error is looking like this one.

     

    -Fabian

     

  • Can you describe the intended bus transaction? From your scope, you send out data 0x00, 0xC3, and 0xCE. What is the next byte you are trying to send out?

    The next byte on the line shows 0xC6. If this differs from what you are sending out, that would indicate the slave is also driving the data lines there and it loses arbitration once a bit differs

    Also what is the part number for the slave device?

    Jeff

  • Are you implementing the NACK handling like in the I2C Tips article?  I've seen the AL error when not doing the proper NACK handling because the bus never gets released and so BB=1, so you get AL on the next STT.

  • I made another log...

     

     

    I'm trying to send a general call to 8 slaves. This is the sequence I wanted to send:

           0x00 0x8A 0x87 0x8B 0x88 0x85 0x88 0x80 0x80

    The bus seems always to hang after bit 7... 

     

    > Also what is the part number for the slave device?

    The slaves are NXP LPC2141. I think the error handling in the slaves is working, I had never problems with them...

     

    > Are you implementing the NACK handling like in the I2C Tips article?

    I think so...

     

         Uint32 I2C_interrupt = I2C_RGET(I2CISR0);

         //Check for AL Interrupt
         if (I2C_interrupt==0x01)
          {

                I2C_sendStop(h_I2C0);            // send STP to end transfer
                I2C_FSETS(I2CSTR0,AL,CLR);       // clear AL bit

                iic0_error |= I2C0_AL_ERROR_DETECTED;
                iic0_busy = FALSE;

                return;

          }

         //Check for NACK Interrupt
         if (I2C_interrupt==0x02)
          {

                I2C_sendStop(h_I2C0);             // send STP to end transfer
                I2C_FSETS(I2CSTR0,NACK,CLR);      // clear NACK bit

                iic0_error |= I2C0_NACK_ERROR_DETECTED;
                iic0_busy = FALSE;

                return;

          }

     

    Any ideas? Do you have working I2C0 code with interrupts for me?! That would be great!

     

    -Fabian

  • Is there anyway to toggle SCL while SDA is Low?! I think that would solve my Problem, because short-circuit SCL to ground for a moment will release the bus!

     

    -Fabian

  • The issue looks like it is with the microcontrollers on the bus.You're trying to write 0x85, but the sequence on the bus is 10000100. It looks like one of the microcontrollers is driving SDA low for that last bit, which causes loss of arbitration.

    Try doing the same sequence except sending a STOP then START between each call to the slaves.

    Jeff

  • > Try doing the same sequence except sending a STOP then START between each call to the slaves.

    Sorry, I don't understand that. Can't figure out what you are meaning...

     

    -Fabian

  • The issue occurs when you are writing the 0x85 on the bus.  In the I2C protocol nobody ever drives the bus high, you simply stop driving and let the pullup bring the signal high.  If you take a look at the waveform you showed you'll see that for the 0x85 SCL goes high "forever" on the 8th clock.  Correspondingly SDA is low, but since we are writing 0x85 we expect SDA to be high!  The only explanation is that something else on the bus is holding it low.  This is exactly the error that causes "arbitration lost".

    So you need to figure out which device is holding SDA low and figure out how to prevent that error.  I like Jeff's idea to shorten your transfer size.  That might make a difference.  Another possibility might be to slow down your I2C clock speed.  Of course, I2C has clock stretching capabilities so the devices should be able to slow it down themselves, but then again one of the devices isn't acting properly so it might be messing that up too...

  • To address a specific device on the I2C bus, you send a START (SDA falling while SCL high), and then the address. Usually, unless the device sees a STOP (SDA rising while SCL high) it will continue to think the data is intended for itself, and may drive the bus if certain commands are issued.

    After you are done addressing a specific device, issue a STOP before trying to address a new device.

    Jeff

  • >The only explanation is that something else on the bus is holding it low. 

     

    I think I know what's happening with my Bus. One of the Slaves seems to receive an additional clock (transmit error) and is then sending the acknowledge bit to early. The Master wants to transmit a high on SDA but the slave is holding it low. The slave is waiting for a SCL low to release the bus, the master is waiting for a free bus and not toggling SCL -> infinite loop...

     

    So I think this is not a software problem. I compared another I2C  Master (LPC2138) with the c6713. The LPC shows a different behavior when SDA is held Low. It is toggling SCL when SDA is held Low without problems and so this kind of error can't happen. The c6713 is not toggling SCL... Do you know why? And is option 2 described in http://processors.wiki.ti.com/index.php/I2C_Tips working? I tried it several times but it doesn't seem to work.

     

    -Fabian

     

     

     

     

  • Fabian Laasch said:
    The c6713 is not toggling SCL... Do you know why?

    Yes, because it has lost control of the bus so it is relinquishing control to let the other device take over.  That's actually what the I2C spec requires.

    Fabian Laasch said:
    And is option 2 described in http://processors.wiki.ti.com/index.php/I2C_Tips working? I tried it several times but it doesn't seem to work.

    I don't have personal experience with this option, so perhaps there are some nitty gritty things we are missing.  For starters I recommend that you make sure you have cleared out any errors (NACK, AL) from the status register.  I also recommend clearing the BB bit.  If that doesn't work perhaps try resetting the I2C and giving that a shot.

    If that doesn't work then you could connect a GPIO pin to SCL (don't remember exact GPIO options on 6713 but I'd look for one with an internal pullup or no pullup/pulldown at all).  For normal operation you can configure it as an input.  To free up the bus you would set the output to logic level 0 and then switch between input and output to drive SCL.  Of course that will require a hardware mod so I hope we can figure a trick to make the FDF mode work for you.

  • Fabian Laasch said:
    I think I know what's happening with my Bus. One of the Slaves seems to receive an additional clock (transmit error) and is then sending the acknowledge bit to early.

    Maybe you could use an oscilloscope to confirm.  Our I2C peripheral will reject certain noise glitches on the line.  Do you know if this slave has this capability?  Perhaps its configurable?  The best thing would be to try and get rid of this problematic noise!