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: I2CMBMON isn't show correct status of I2C bus

Part Number: TM4C1294NCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

I'm working on a project which is uses I2C bus and I found some strange behavior of I2C Master Bus Monitor (I2CMBMON) register.

As described in datasheet it should show SDA and SCL signal status, but it show it correctly only after Power ON or Reset CPU. If I do a peripheral reset of I2C controller or Disable/Enable cycle it shows always 3 that mean that SDA and SCL are in HIGH level even if the actual level is LOW. I'm trying to use this register in my I2C bus recovery function.

I've created a simple CCS project which demonstrate it on EK-TM4C1294XL board (see in attached file). The project just print the I2CMBMON status on UART0, after Peripheral reset of I2C and after Disable-Enable cycle. I've connected PG0 & PG1 to GND, thus the SDA and SCL become 0, but I2CMBMON shows correct state only in first time. I've also add send STOP right after Peripheral reset and Dis/En cycle, but without success. I've also used MAP_ variance of I2C functions, but also without success.

To run the project you need to update TIVAWARE_DIR to your path in 'Project properties->CCS Build->Variables' tab.

So can anybody tell me how to get correct I2C bus state?i2c-reset-test.zip

  • Hi Dmitry,
    First of all your code selects I2C0 while you talk about grounding PG0 and PG1 pins which are are for I2C1. I will also suggest you check the I2CMBMON in real I2C operation with the bus connected to an external device and ensure proper pullup resistors are present on the SCL and SDA buses. Please note that there is internal pullup on the the SDA and SCL pins.
  • #define I2C_BASE    I2C0_BASE

    I2C1 is the main I2C controller in my project and I've also checked the issue on other interface. On I2C0 I connect to ground PB2 and/or PB3 with the same result.

    I found this issue in real I2C operations. I'm useing second EK-TM4C1294 Stellaris board in BOM Bootloader mode (Flash is erased) as I2C slave device. And also in my test project I do I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP after peripheral reset, but it isn't help.

    I'm trying to read I2CMBMON in my I2C_ErrorRecovery function, which is run before each I2C transaction.

    uint32_t I2C_ErrorRecovery(i2c_dev* p_i2c)
    {
        uint32_t ret = RET_OK;
        uint8_t count = 0;
        if (MAP_I2CMasterBusBusy(p_i2c->base) || (3 != MAP_I2CMasterLineStateGet(p_i2c->base)))
        {
            ret = RET_ERR;
            while(count++ < 9)
            {
    #ifdef USE_GPIO_RECOVERY
                MAP_GPIOPinTypeGPIOOutput(p_i2c->gpio_base, p_i2c->scl_gpio_pin);
                MAP_GPIOPinWrite(p_i2c->gpio_base, p_i2c->scl_gpio_pin, 0);
                MAP_SysCtlDelay(400);
                MAP_GPIOPinTypeGPIOInput(p_i2c->gpio_base, p_i2c->scl_gpio_pin);
    
                MAP_GPIOPinConfigure(p_i2c->scl_gpio_mode);            
                MAP_GPIOPinTypeI2CSCL(p_i2c->gpio_base, p_i2c->scl_gpio_pin);
    #else
                MAP_I2CMasterControl(p_i2c->base, I2C_MASTER_CMD_FIFO_BURST_SEND_ERROR_STOP);
                MAP_SysCtlDelay (400);
    #endif
                if (!MAP_I2CMasterBusBusy(p_i2c->base) && (3 == MAP_I2CMasterLineStateGet(p_i2c->base)))
                {
                    ret = RET_OK;
                    break;
                }
            }
        }
        return ret;
    }
  • Hi,

     I think what happened is that you reset the peripheral as in below code and causes the I2C control registers and configuration to be lost. 

       UARTprintf("\033[2J\033[H");

       UARTprintf(I2C_STR" Reset Test\n");

       UARTprintf(I2C_STR" MON %X\n", I2CMasterLineStateGet(I2C_BASE));

       SysCtlPeripheralReset(SYSCTL_PERIPH_I2C);

       while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C));

  • I 'LIKE' vendor's Charles analysis.

    During development of such a diagnostic aid - nothing prevents your routing 'SDA & SCL' to 2 (other) MCU GPIO pins (set as inputs) - which will provide further confirmation of those 2 key signal levels.    There is always value to such, 'Strength in Numbers.'

    It is hoped that you are NOT relying upon the enfeebled (far too high value) MCU pull-ups to SDA/SCL - but instead employ (more proper) 4K7-10K (external Rs) - which provide faster signal response and less rounded signal edges...

  • Hi Charles,

    I've add I2CMasterInitExpClk function after peripheral reset and this resolve the issue in the test project.

    SysCtlPeripheralReset(SYSCTL_PERIPH_I2C);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C));
    I2CMasterInitExpClk(I2C_BASE, g_ui32SysClock, false);

    And after Disable-Enable and this works too

    MAP_SysCtlPeripheralDisable(SYSCTL_PERIPH_I2C);
    SysCtlDelay(1000);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_I2C);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_I2C));
    I2CMasterInitExpClk(I2C_BASE, g_ui32SysClock, false);