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.

TM4C1294NCPDT: Problems Resetting I2C Communication

Part Number: TM4C1294NCPDT

Hi - We have a Tiva TM4C1294NCPDT communicating with an Analog Devices ADXL355 accelerometer. I'm seeing an issue where communication drops out sometimes; possibly due to noise. This results in the I2C_MASTER_ERR_ARB_LOST error returned from the TivaWare Lib I2CMasterErr() function.

When this happens, I'm having trouble restarting communication with the accelerometer. Even when performing a reset on the I2C peripheral using SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0) and then reinitializing using SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0) I still get the same I2C_MASTER_ERR_ARB_LOST error and cannot reestablish communication with the accelerometer.

The only way to reestablish communication is with a reset or power cycle of the Tiva, which is very undesirable for our use case.  Any information anyone can provide on reestablishing communications using the TivaWare without a power cycle or reset would be very helpful.


Thank you,
Terence

  • What is the state of the SDA line when you have this error? If you get noise that generates extra transitions on SCL or SDA, the slave and master will be out of synchronization. The solution is to use SCL as a digital I/O and bit-bang it low/high until the slave releases SDA. Here is some information on I2C that you may find helpful.

    https://www.ti.com/lit/an/slva704/slva704.pdf

    https://www.ti.com/lit/an/slyt770/slyt770.pdf

  • Hi Bob - Thanks for the feedback.  I was hoping to do this without resorting to bit-banging.  Are you sure it's not somehow possible using a TivaWare function? For example, maybe using I2CMasterTimeoutSet()?

  • Check the SCL and SDA lines. If the slave is holding SDA low, the only way to get the slave out of this state is with edges on SCL. Since the I2C module sees this as a different master holding the bus, it will not attempt to drive SCL. Bit banging is the only solution I know. Resetting the module, or time-out of the master does not change the state of the slave. 

  • Hmmmmm....  After hooking up a logic analyzer and recreating the issue, I actually see both SDA and SCL remaining high indefinitely.  I'm going to have to investigate farther.  However, I do appreciate the confirmation that bit banging very well may be the only way to recover.

  • Hi Bob - Apologies for the delay, I'm just getting back to this now.  I've done some more investigation.  Due to the length of the I2C wire required, we're using an I2C extender between the Tiva and the accelerometer.  The lines going from our board with Tiva to our board with the accelerometer have the following lines:

    • VEXT
    • 3.3VDC
    • SCL
    • SDA
    • IO_B (Interrupt line from the accelerometer)
    • IO_A (Additional interrupt line from the accelerometer)
    • Ground

    I'm finding when I disconnect/reconnect *only* VEXT is when communication ceases between the Tiva and the accelerometer.  This is very repeatable.  I attached a logic analyzer to trigger when the disconnect/reconnect of VEXT occurs, capturing the SDA and SCL lines on both the accelerometer and the Tiva side.  Here are a couple of examples:

    As can be seen in the above logic analyzer images, it appears some noise is introduced to SDA and SCL when disconnecting VEXT.  Note how in both of the above cases (and in every case of the many cases I've examined), the SDA and SCL lines remain high indefinitely after the VEXT line is disconnected.

    SDA and SCL being high indicate the I2C bus is idle.  What I'm confused about is why the Tiva can't reestablish I2C communication.  I attempt to do so using the following code where I momentarily disable the I2C peripheral and then reenable it using the same initialization code used at startup of the board:

    static const uint32_t I2C_DELAY = 500
    
    ...
    
    SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0);
    MAP_SysCtlDelay(I2C_DELAY);
    
    // Enable the peripheral
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C0);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C0))
    
    // Enable the IO Pins
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOL))
    
    // Set the pin multiplexors
    GPIOPinConfigure(GPIO_PB3_I2C0SDA); //PB3 should be SDA
    GPIOPinConfigure(GPIO_PB2_I2C0SCL); //PB2 should be SCL
    
    // Assign pins to SCL and SDA
    GPIOPinTypeI2CSCL(GPIO_PORTB_BASE, GPIO_PIN_2);
    GPIOPinTypeI2C(GPIO_PORTB_BASE, GPIO_PIN_3);
    
    // Configure Data pin type (no need to configure Clk - it is done automatically)
    GPIOPadConfigSet(GPIO_PORTB_BASE, GPIO_PIN_3, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_OD);
    
    MAP_I2CMasterInitExpClk(I2C0_BASE, SysClock, true); // false = 100kbps true = 400kbps
    MAP_SysCtlDelay(I2C_DELAY);
    
    MAP_I2CMasterTimeoutSet(I2C0_BASE, 0x7D);
    MAP_SysCtlDelay(I2C_DELAY);
    
    // Wait until the Master is not busy sending
    if(!TiltSensorI2CWaitOnMasterBusy()) return false;
    MAP_SysCtlDelay(I2C_DELAY);
    
    uint32_t I2CMasterErrorValue = MAP_I2CMasterErr(I2C0_BASE);
    if (I2CMasterErrorValue != I2C_MASTER_ERR_NONE)
    {
        return false;   // An error happens here.  The return value from MAP_I2CMasterErr() is I2C_MASTER_ERR_ARB_LOST
    }
    
    return true;

    Any thoughts or suggestions you have on this issue would be very much appreciated.  Thank you.

  • Terence Darwen said:
    we're using an I2C extender between the Tiva and the accelerometer

    Typically I2C extenders are used in pairs. Is it possible that your I2C extender circuit is actively driving either SCL or SDA high? That could cause a loss of arbitration error.

  • Bob Crosby said:
    Terence Darwen
    we're using an I2C extender between the Tiva and the accelerometer

    Typically I2C extenders are used in pairs. Is it possible that your I2C extender circuit is actively driving either SCL or SDA high? That could cause a loss of arbitration error.

    Right, my mistake, I didn't design this board, I'm just the embedded software engineer working on the firmware.  After discussing with our electrical engineer, the I2C extenders are indeed used in pairs.  There is one on our custom board w/ the Tiva and one on the accelerometer's board.

    Bob Crosby said:

    Is it possible that your I2C extender circuit is actively driving either SCL or SDA high? That could cause a loss of arbitration error.

    Good suggestion.  As suggested by my EE colleague, I tested this by getting the board into the previously mentioned "bad state" where I2C communication no longer occurs and the SDA and SCL lines are both indefinitely high on both sides (the accelerometer and Tiva).  I then introduced a 4K resistor to ground as shown in the picture below.

    When doing this, the lines frequently remain high.  This leads me to believe it's not the extender driving the lines high.

    However, here's an experiment I tried with results I found interesting:

    I have a TM4C1294XL dev board just like this one.  I wrote identical I2C firmware to what runs on our custom board as far as it querying the accelerometer during a periodic systick interrupt.  I hooked up only the SDA and SCL lines from the dev board into the I2C lines between our custom board and accelerometer board, but leave the dev board powered off.  I then get the I2C communication between our custom board and the accelerometer into the previously mentioned "bad state".  I then power on the dev board and, immediately, I2C communication is properly working for both the dev board to the accelerometer and our custom board to the accelerometer.  After this, I can even power off the dev board and I2C communication will continue between our custom board and accelerometer.

    I'm not exactly sure what conclusion to draw from this other than nothing is forcing the SDA and SCL lines high or low when in the "bad state"...  Any thoughts?

  • My best guess is that the noise causes the I2C module to think it lost arbitration to another master. It stays in that state until it sees a valid stop condition. When you added the extra I2C master, it did a successful start - stop combination that released the bus. Unfortunately it looks like SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C0) just disables the clock to the module. It does not reset the module. Can you try changing the SCL/SDA lines into open-drain GPIO outputs. Then simulate a stop condition with SDA low, SCL low, SCL high, SDA high. I would try this myself, but I have not figured out how to get in the "locked up" condition with my hardware. You may have to follow the datasheet instructions on recovering from lost arbitration.

  • Hi Bob - As you suggested, bit-banging a start and then a stop did the trick.  Works every time.  Huge thanks for your help with this!