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.

TMS320C6472 I2C bus hang

Other Parts Discussed in Thread: OMAPL138

Hi,

I need to know how to generate samples the SDA line and force the clock to toggle.

I checked sprue11c.pdf and it seems that I need to add special circuitry to detect the I2C bus hanging and correct for it. This is not an option for me since we are at the last stages of the design.

Can I do the same thing by writing to the I2C registers or maybe change the I2C pins configuration to act as GPIO pin so I can read and write to them?

thanks.

Khaled.

  • Khaled,

    You can refer below thread where you can find some interesting solutions for I2C bus hang.

    e2e.ti.com/.../480412

    Regards,
    Senthil
  • Senthil
    In the link that you have provided the answer was never verified. But it doesn't matter, I could do the verification my self.
    This is said, do you have an example code on how to set the MODE Register and execute the 9 reads? Do I just write to the DXR register 9 times?
    If you have an example code, it will cut my trial and error time.
    thanks.
    Khaled.
  • Khaled,

    I am not aware of this. I will request my software team to check on this.

    Regards,
    Senthil
  • Sorry for the delay in responding.
    Yes, you have to change the pin I2C mdoe to GPIO mode (PINMUX config) then toggle the SCL line (GPIO) like below to do bus recovery.

    /* Send high and low on the SCL line */
    for (i = 0; i < 9; i++) {
    gpio_set_value(scl_pin, 0);
    udelay(20);
    gpio_set_value(scl_pin, 1);
    udelay(20);
    }
  • Thank you for the reply.

    But I was under the impression that the pins of C6472 can't be configured as standard GPIO's!

    In all cases, I'm not able to find the command gpio_set_value( ) not the variable scl_pin. Do I need a library for that?

    Currently I"m using a CSL command to read and write to the 16 GPIO pins available

       pinNum = CSL_GPIO_PIN0 ... CSL_GPIO_PIN15  //select the pin

       CSL_gpioInit(&pContext); //initialize CSL

       GpioHandle = CSL_gpioOpen(&gpioObj, CSL_GPIO, NULL, &status);  //open CSL

       CSL_gpioHwSetup(GpioHandle, &hwSetup);  //setup GPIO's

        if(val) CSL_gpioHwControl(GpioHandle, CSL_GPIO_CMD_SET_BIT, &pinNum);     //set the GPIO
        else   CSL_gpioHwControl(GpioHandle, CSL_GPIO_CMD_CLEAR_BIT, &pinNum); //clear the GPIO

    Khaled.

  • Dear Khaled,
    Sorry, actually I have given this "gpio_set_value" for your understanding, this API is used in Linux driver.
    You need to set/clear the OUT register of particular GPIO to toggle.
    You can use CSL APIs to do.
  • Hi,

    But again this is what I'm trying to solve: I'm not sure how to control the C6472 I2C pin to toggle at will. As I mentioned in my previous e-mail, I was under the impression that this particular chip pin can't be configured as regular GPIO's!

    Currently I'm using the SCL library and at last stage of the design and a couple weeks per-delivery. Changing the code to use a new library is out of the question.
     I need a solution that uses the SCL one.

    Is there a solution that fit in my frame work?

    Khaled.

  • Hi Titus.
    Do you have additional information if I can re-configure the C6472 and how to do it?
    Khaled.
  • Dear Khaled,
    Apologize for the delayed response on this.
    I think, we can't toggle the I2C pin if that pins were not shared (PINMUX) with GPIO.

    I will also confirm with HW team.
  • Hi Titus,

    As soon as you have a confirmation, please let me know.

    If if its not possible to toggle that pin by configuring it as a GPIO, does the hardware team has "code" that  I could use to get this bus un-stuck?

    thanks.

    Khaled.

  • Dear Khaled,
    I emailed to HW experts on this, expecting reply from them, in parallel can you please try the 2nd method to recover the bus mentioned below wiki ?
    processors.wiki.ti.com/.../I2C_Tips

    Taken from OMAPL138 Linux for your reference:
    It seems need to set FDF (free data format) flag in I2C MDR register.
    flag |= DAVINCI_I2C_MDR_FDF;// free data format mode
    flag &= ~DAVINCI_I2C_MDR_TRX;// receive byte
    // Set STT to begin transmit now DXR is loaded
    flag |= DAVINCI_I2C_MDR_STT;
    davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
  • Titus,
    We are making progress :-)
    Using the 2th method, I got 9 clock cycles out of the I2C SCL (see code below) :-)

    Two issues that need further investigation:
    1) the SCL bus was stuck low after the 9 clock cycles! I had to issue a reset command to get it back to high. Why?
    2) The start and the ack bits where transmitted on the SDA bus. Is that to be expected?

    Khaled.

    tmp = 0x0000;
    tmp &= ~I2C_VAL_REG_MDR_IRS; //reset
    DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, tmp);

    tmp = 0x0000;
    tmp &= ~I2C_VAL_REG_MDR_FREE; //stop if breakpoint
    tmp |= I2C_VAL_REG_MDR_IRS; //take out of reset
    tmp |= I2C_VAL_REG_MDR_FDF; //free data mode
    tmp |= I2C_VAL_REG_MDR_MST; //master mode
    tmp &= ~I2C_VAL_REG_MDR_TRX; //receive mode
    tmp |= I2C_VAL_REG_MDR_RM; //repeat
    DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, tmp);

    tmp |= I2C_VAL_REG_MDR_STT; //start condition
    DEVICE_REG32_W (DEVICE_I2C_BASE + I2C_REG_MDR, tmp);